1 Star 1 Fork 0

zp2023/STudnets

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
mainwindow.cpp 21.70 KB
一键复制 编辑 原始数据 按行查看 历史
zp2023 提交于 2023-06-18 09:58 +08:00 . students_branch
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QKeyEvent>
#include <QCoreApplication>
#include <QtDebug>
#include <QAbstractItemView>
#include <QMessageBox>
#include <QDateTime>
#include <QFile>
#include <QDesktopServices>
//调用摄像头
#include <QCameraInfo>
#include <QCamera>
#include <QCameraViewfinder>
#include <QCameraImageCapture>
#include <QPixmap>
#include "stusql.h"
#include "login.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_stusql(nullptr)
{
ui->setupUi(this);
m_login.show();
connect(&m_login,&Login::Login_Suc,this, [=](){
bool suc = m_stusql->Login_Suc(m_login.line_user,m_login.line_pwd);
if (suc == true){
m_login.close();
this->show();
}
});
ui->treeWidget->setColumnCount(1);
QTreeWidgetItem* pf = new QTreeWidgetItem(ui->treeWidget,QStringList("学生信息管理系统"));
QTreeWidgetItem* p1 = new QTreeWidgetItem(pf,QStringList("学生管理"));
QTreeWidgetItem* p2 = new QTreeWidgetItem(pf,QStringList("管理员管理"));
QTreeWidgetItem* p3 = new QTreeWidgetItem(pf,QStringList("用户信息管理"));
ui->treeWidget->addTopLevelItem(pf);
pf->addChild(p1);
pf->addChild(p2);
pf->addChild(p3);
ui->treeWidget->expandAll();
ui->stackedWidget->setCurrentIndex(0);
m_stusql = stusql::getInstance(); // 返回的是个指针
if (m_stusql == nullptr)
m_stusql->Init();
showTable_All();
QFile f;
QString dir = QCoreApplication::applicationDirPath(); // 获取程序的位置
f.setFileName(dir + "//" + "stuqss.css"); // 设置名字
qDebug() << dir ;
f.open(QIODevice::ReadOnly);
QString str = f.readAll();
this->setStyleSheet(str);
f.close();
// 对登录界面加载皮肤
f.setFileName(dir + "//" + "login.css"); // 设置名字
f.open(QIODevice::ReadOnly);
str = f.readAll();
// 对登录界面进行刷新
m_login.setStyleSheet(str);
f.close();
showfile();
open_cam();
connect(ui->line_Sea,SIGNAL(returnPressed()),ui->Sea_Btn,SIGNAL(clicked()),Qt::UniqueConnection);
connect(ui->treeWidget,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(selectHero(QTreeWidgetItem*,int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_F6) {
// 就是说按键为F6的时候进行皮肤刷新
QFile f;
QString dir = QCoreApplication::applicationDirPath(); // 获取程序的位置
f.setFileName(dir + "//" + "stuqss.css"); // 设置名字
qDebug() << dir ;
f.open(QIODevice::ReadOnly);
QString str = f.readAll();
this->setStyleSheet(str);
f.close();
// 对登录界面进行刷新
// m_login.setStyleSheet(str);
}
}
void MainWindow::showTable_Page()
{
QStringList head;
head << "序号" << "姓名" << "年龄" << "年级" << "班级" << "学号" << "电话" << "微信";
ui->tableWidget->setHorizontalHeaderLabels(head);
int num = m_stusql->Get_Count();
QList<StuInfo> l;
l = m_stusql->Pag_Stu(num,0); // 偏移量是0,一页数量是num个
ui->tableWidget->setRowCount(num);
for (int i = 1; i < l.size(); ++i) {
ui->tableWidget->setItem(i, 0,new QTableWidgetItem(QString::number(l[i].id)));
ui->tableWidget->setItem(i, 1,new QTableWidgetItem(l[i].name));
ui->tableWidget->setItem(i, 2,new QTableWidgetItem(QString::number(l[i].age)));
ui->tableWidget->setItem(i, 3,new QTableWidgetItem(QString::number(l[i].grade)));
ui->tableWidget->setItem(i, 4,new QTableWidgetItem(QString::number(l[i].uiclass)));
ui->tableWidget->setItem(i, 5,new QTableWidgetItem(QString::number(l[i].studentid)));
ui->tableWidget->setItem(i, 6,new QTableWidgetItem(l[i].phone));
ui->tableWidget->setItem(i, 7,new QTableWidgetItem(l[i].wechat));
}
show_Count();
}
void MainWindow::showTable_All()
{
ui->tableWidget->clear();
ui->tableWidget->setColumnCount(8);
QStringList head;
head << "序号" << "名字" << "年龄" << "年级" << "班级" << "学号" << "电话" << "微信";
ui->tableWidget->setHorizontalHeaderLabels(head);
// 只选中行
// ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); // 可以一次选择多行数据
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); // 不能够进行修改
int num = m_stusql->Get_Count();
QList<StuInfo> l;
l = m_stusql->Sec_Stu(); // 数据库中查询所有学生将其进行存储
ui->tableWidget->setRowCount(num);
for (int i = 0; i < l.size(); ++i) {
ui->tableWidget->setItem(i, 0,new QTableWidgetItem(QString::number(l[i].id)));
ui->tableWidget->setItem(i, 1,new QTableWidgetItem(l[i].name));
ui->tableWidget->setItem(i, 2,new QTableWidgetItem(QString::number(l[i].age)));
ui->tableWidget->setItem(i, 3,new QTableWidgetItem(QString::number(l[i].grade)));
ui->tableWidget->setItem(i, 4,new QTableWidgetItem(QString::number(l[i].uiclass)));
ui->tableWidget->setItem(i, 5,new QTableWidgetItem(QString::number(l[i].studentid)));
ui->tableWidget->setItem(i, 6,new QTableWidgetItem(l[i].phone));
ui->tableWidget->setItem(i, 7,new QTableWidgetItem(l[i].wechat));
}
show_Count();
}
void MainWindow::show_Count()
{
int count = m_stusql->Get_Count();
ui->Stu_Count->setText(QString::number(count));
}
void MainWindow::table_To_excel()
{
//获取保存路径
QString filepath=QFileDialog::getSaveFileName(this,tr("Save"),".",tr(" (*.xlsx)"));
qDebug() << filepath;
if(!filepath.isEmpty()){
QAxObject *excel = new QAxObject(this);
//连接Excel控件
excel->setControl("Excel.Application");
//不显示窗体
excel->dynamicCall("SetVisible (bool Visible)","false");
//不显示任何警告信息。如果为true那么在关闭是会出现类似“文件已修改,是否保存”的提示
excel->setProperty("DisplayAlerts", false);
//获取工作簿集合
QAxObject *workbooks = excel->querySubObject("WorkBooks");
//新建一个工作簿
workbooks->dynamicCall("Add");
//获取当前工作簿
QAxObject *workbook = excel->querySubObject("ActiveWorkBook");
//获取工作表集合
QAxObject *worksheets = workbook->querySubObject("Sheets");
//获取工作表集合的工作表1,即sheet1
worksheet = worksheets->querySubObject("Item(int)",1);
int tableR = ui->tableWidget->rowCount(); // 获取表格的行
int tableC = ui->tableWidget->columnCount(); // 表格的列
//获取表头写做第一行
for (int i=0; i<tableC; i++) {
if ( ui->tableWidget->horizontalHeaderItem(i) != NULL ) {
this->SetCellData(1, i+1, ui->tableWidget->horizontalHeaderItem(i)->text());
}
}
//写数据
for (int i=0; i<tableR; i++) {
for (int j=0; j<tableC; j++) {
if ( ui->tableWidget->item(i,j) != NULL ){
this->SetCellData(i+2, j+1, ui->tableWidget->item(i,j)->text());
}
}
}
workbook->dynamicCall("SaveAs(const QString&)",QDir::toNativeSeparators(filepath));//保存至filepath,注意一定要用QDir::toNativeSeparators将路径中的"/"转换为"\",不然一定保存不了。
workbook->dynamicCall("Close()");//关闭工作簿
excel->dynamicCall("Quit()");//关闭excel
delete excel;
excel=NULL;
}
}
bool MainWindow::SetCellData(int row, int column, QVariant data)
{
bool op = false;
QAxObject *cell = worksheet->querySubObject("Cells(int,int)",row,column);//获取单元格对象
if ( cell ) {
QString strData = data.toString(); //excel 居然只能插入字符串和整型,浮点型无法插入
cell->dynamicCall("SetValue(const QVariant&)",strData); //修改单元格的数据
op = true;
}else {
op = false;
}
return op;
}
void MainWindow::updata_file() // 其实本质上是模拟文件上传,也就是说将文件复制到文件夹内
{
/* 这个是打开文件
QString QFileDialog::getOpenFileName (
QWidget * parent = 0,
const QString & caption = QString(),
const QString & dir = QString(), 文件在哪个文件夹
const QString & filter = QString(),
​ QString * selectedFilter = 0,
​ Options options = 0 );*/
auto str = QFileDialog::getOpenFileName(nullptr,"文件上传", "","*txt");// 这个是打开什么文件夹
qDebug() << str; //打开了D盘,并且选择后是传入的是文件名,而不是目录名;
if (str.isEmpty()) {
QMessageBox::warning(nullptr,"警告","此路径为空!");
return;
}
auto file_str = m_path + "/" + str.section("/",-1);
qDebug() << file_str;
// 判断缓存目录中是否有相同文件名的文件
if(QFile::exists(file_str)){ // 这里检查的是文件名
QMessageBox::warning(nullptr,"警告","此文件已上传,请重新修改文件名");
return;
}
// static bool copy(const QString &fileName, const QString &newName);
bool ret = QFile::copy(str, file_str); // 就是把file的文件拷贝到file_str文件夹目录下
QMessageBox::warning(nullptr,"信息",ret?"成功":"上传失败,可能被占用"); //上传文件流可能更好一些
showfile();
}
void MainWindow::showfile()
{
m_modelitem.clear();
auto path = QApplication::applicationDirPath() + "/data";
m_path = path;
qDebug() << path;
QDir d(path);
if (!d.exists()){
d.mkdir(path);
}
QStringList lFiter;
lFiter << ".txt";
QFileInfoList lFilesInfo = d.entryInfoList((lFiter,QDir::Files));
qDebug() << lFilesInfo; // 将所有文件进行一个传入
QList<QStandardItem*> lRow;
for (int i = 0; i < lFilesInfo.size(); ++i) {
lRow.clear();
QFileInfo &info = lFilesInfo[i];
/*
for (auto file : file_name) {
if (info.baseName() == file){
flag = 1;
continue;
}
else
file_name.append(info.baseName());
qDebug() << "file = " << file ;
}
if (flag == 1)
continue; //将文件名存入应该是可行的但是就是出问题了
// 文件名
*/
QStandardItem* p1 = new QStandardItem(info.baseName());
QStandardItem* p2 = new QStandardItem(info.absoluteFilePath()); // 文件绝对路径
// 文件创建时间
QStandardItem* p3 = new QStandardItem(info.birthTime().toString("yyyy/MM/dd hh:mm:ss"));
QStandardItem* p4 = new QStandardItem(info.lastModified().toString("yyyy/MM/dd hh:mm:ss"));
// 文件大小
QStandardItem* p5 = new QStandardItem(QString::number(info.size() / 1024) +"KB");
qDebug() << info.baseName();
lRow << p1 << p2 << p3 << p4 << p5;
m_modelitem.appendRow(lRow);
}
QStringList lHeader{"文件名", "文件路径", "创建日期", "修改日期", "文件大小"};
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 可以一次选择多行数据
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 不能够进行修改
m_modelitem.setHorizontalHeaderLabels(lHeader);
ui->tableView->setModel(&m_modelitem);
}
void MainWindow::on_Exit_Btn_clicked()
{
exit(0);
}
void MainWindow::on_Simluate_Btn_clicked() // 模拟插入数据
{
// 往数据库里面增加数据
/*
QString name;
quint8 age;
quint16 uiclass;
quint16 grade; // 年级
quint32 studentid;
QString phone;
QString wechat;
*/
printf("看看是不是能调用");
User_Info user;
StuInfo stu;
int begin = m_stusql->max_id() + 1;
QList<StuInfo> l;
for (int i = begin; i < begin + 1000; i++){
if (i % 2 == 0){
stu.id = i;
stu.name = QString("zhangsan%1").arg(i);
stu.age = 17;
stu.uiclass = 1;
stu.grade = 12;
stu.studentid = i;
stu.phone = "123456789";
stu.wechat = "123456789";
}
else if (i % 3 == 0) {
stu.id = i;
stu.name = QString("lisi%1").arg(i);
stu.age = 18;
stu.uiclass = 2;
stu.grade = 13;
stu.studentid = i;
stu.phone = "126789";
stu.wechat = "12789";
}
else if (i % 7 == 0) {
stu.id = i;
stu.name = QString("wawu%1").arg(i);
stu.age = 19;
stu.uiclass = 3;
stu.grade = 14;
stu.studentid = i;
stu.phone = QString("456789");
stu.wechat = QString("456789");
}
else {
stu.id = i;
stu.name = QString("pan%1").arg(i);
stu.age = 20;
stu.uiclass = 4;
stu.grade = 15;
stu.studentid = i;
stu.phone = QString("12124129");
stu.wechat = QString("4567we89");
}
l.append(stu);
}
m_stusql->Add_Stu_plus(l);
showTable_All();
}
void MainWindow::on_Ins_Btn_clicked()
{
m_page.setType(true);
m_page.exec();
showTable_All();
}
void MainWindow::on_Clear_clicked()
{
m_stusql->Cle_Stu();
showTable_All();
}
void MainWindow::on_Upt_Btn_clicked()
{
StuInfo info;
int i = ui->tableWidget->currentRow(); // 修改第i行数据
if (i >= 0){
info.id = ui->tableWidget->item(i,0)->text().toUInt();
info.name = ui->tableWidget->item(i,1)->text();
info.age = ui->tableWidget->item(i,2)->text().toUInt();
info.grade = ui->tableWidget->item(i,3)->text().toUInt();
info.uiclass = ui->tableWidget->item(i,4)->text().toUInt();
info.studentid = ui->tableWidget->item(i,5)->text().toUInt();
info.phone = ui->tableWidget->item(i,6)->text();
info.wechat = ui->tableWidget->item(i,7)->text();
m_page.setType(false, info);
m_page.exec();
}
showTable_All();
}
void MainWindow::on_Del_Btn_clicked()
{
int i = ui->tableWidget->currentRow();
if (i >= 0){
int id = ui->tableWidget->item(i,0)->text().toUInt();
m_stusql->Del_Stu(id);
showTable_All();
QMessageBox::information(this,"提示","删除成功");
}
else {
QMessageBox::critical(this,"错误","删除失败");
}
}
void MainWindow::on_Sea_Btn_clicked()
{
QString str = ui->line_Sea->text();
if (str == ""){
QMessageBox::critical(this,"错误","输入不能为空");
showTable_All();
return;
}
ui->tableWidget->clear();
ui->tableWidget->setColumnCount(8);
QStringList head;
head << "序号" << "名字" << "年龄" << "年级" << "班级" << "学号" << "电话" << "微信";
ui->tableWidget->setHorizontalHeaderLabels(head);
// 只选中行
// ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); // 可以一次选择多行数据
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); // 不能够进行修改
int num = m_stusql->Get_Count();
int index = 0;
QList<StuInfo> l;
l = m_stusql->Sec_Stu(); // 数据库中查询所有学生将其进行存储
for (int i = 0; i < l.size(); ++i) {
if (!l[i].name.contains(str)) {
continue;
}
ui->tableWidget->setItem(index, 0,new QTableWidgetItem(QString::number(index)));
ui->tableWidget->setItem(index, 1,new QTableWidgetItem(l[i].name));
ui->tableWidget->setItem(index, 2,new QTableWidgetItem(QString::number(l[i].age)));
ui->tableWidget->setItem(index, 3,new QTableWidgetItem(QString::number(l[i].grade)));
ui->tableWidget->setItem(index, 4,new QTableWidgetItem(QString::number(l[i].uiclass)));
ui->tableWidget->setItem(index, 5,new QTableWidgetItem(QString::number(l[i].studentid)));
ui->tableWidget->setItem(index, 6,new QTableWidgetItem(l[i].phone));
ui->tableWidget->setItem(index, 7,new QTableWidgetItem(l[i].wechat));
index++;
}
ui->tableWidget->setRowCount(index);
ui->Stu_Count->setText(QString::number(index));
}
void MainWindow::on_Btn_Out_clicked()
{
// 导出数据为excel
table_To_excel();
}
void MainWindow::on_pushButton_clicked()
{
// 在初始化data_show的时候,将做好的hash表当做一个参数传入到data_show的create_Bar()中
data_show = new data_view(nullptr, m_stusql); // 这里有个bug就是,当发现有这个界面时候仍然会出现
data_show->show();
}
void MainWindow::age_count()
{
int min = m_stusql->min_age();
int max = m_stusql->max_age();
for (int i = min; i <= max; ++i){
int count = m_stusql->age_count(i);
if (count != 0)
m_age.insert(i, count);
else
continue;
}
}
void MainWindow::filter()
{
m_modelitem.clear();
auto path = QApplication::applicationDirPath() + "/data";
m_path = path;
QString str_filter = ui->line_Sea_file->text();
qDebug() << path;
QDir d(path);
if (!d.exists()){
d.mkdir(path);
}
QStringList lFiter;
lFiter << ".txt";
QFileInfoList lFilesInfo = d.entryInfoList((lFiter,QDir::Files));
qDebug() << lFilesInfo; // 将所有文件进行一个传入
QList<QStandardItem*> lRow;
for (int i = 0; i < lFilesInfo.size(); ++i) {
lRow.clear();
QFileInfo &info = lFilesInfo[i];
if (!info.completeBaseName().contains(str_filter)) {
continue;
}
QStandardItem* p1 = new QStandardItem(info.baseName());
QStandardItem* p2 = new QStandardItem(info.absoluteFilePath()); // 文件绝对路径
// 文件创建时间
QStandardItem* p3 = new QStandardItem(info.birthTime().toString("yyyy/MM/dd hh:mm:ss"));
QStandardItem* p4 = new QStandardItem(info.lastModified().toString("yyyy/MM/dd hh:mm:ss"));
// 文件大小
QStandardItem* p5 = new QStandardItem(QString::number(info.size() / 1024) +"KB");
qDebug() << info.baseName();
lRow << p1 << p2 << p3 << p4 << p5;
m_modelitem.appendRow(lRow);
}
QStringList lHeader{"文件名", "文件路径", "创建日期", "修改日期", "文件大小"};
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 可以一次选择多行数据
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 不能够进行修改
m_modelitem.setHorizontalHeaderLabels(lHeader);
ui->tableView->setModel(&m_modelitem);
}
void MainWindow::open_cam()
{
QList<QCameraInfo> infos = QCameraInfo::availableCameras(); // 可用的摄像头列表
qDebug() << infos.value(0).deviceName() << infos.value(0).description();
QString cam_name = infos.value(0).deviceName(); // 获取摄像机名字
qDebug() << cam_name ;
ca = new QCamera(cam_name.toUtf8(),ui->widget_cam); // 打开摄像头
QCameraViewfinder *v2 = new QCameraViewfinder(ui->widget_cam);
ui->widget_cam->show();
v2->resize(ui->widget_cam->size());
ca->setViewfinder(v2);
v2->show();
ca->start();
}
void MainWindow::selectHero(QTreeWidgetItem *item, int a)
{
if (item->text(a) == "学生管理") {
ui->stackedWidget->setCurrentIndex(0);
}
else if (item->text(a) == "管理员管理") {
ui->stackedWidget->setCurrentIndex(1);
}
else if (item->text(a) == "用户信息管理") {
// 开启摄像头
ui->stackedWidget->setCurrentIndex(2);
}
else
return;
}
void MainWindow::on_Btn_Up_clicked()
{
showfile();
updata_file();
}
void MainWindow::on_Task_Sea_clicked()
{
if (ui->line_Sea_file->text() == "") {
QMessageBox::warning(nullptr, "警告", "不能为空");
showfile();
return;
}
filter();
}
void MainWindow::on_Task_Del_clicked()
{
QDesktopServices::openUrl(QUrl(m_path)); // QDesktopServices类提供的函数用于访问常见的桌面服务。
}
void MainWindow::on_Task_Ins_clicked()
{
auto index = ui->tableView->currentIndex();
if (!index.isValid()){
return;
}
auto item = m_modelitem.index(index.row(),1); // 返回的是文件绝对路径
auto str = m_modelitem.data(item).toString();
auto ret = QFile::remove(str);
QMessageBox::information(nullptr,"信息",ret?"删除成功":"删除失败");
showfile();
}
/*
文件的加密和解密,这个是对文件名字进行加密和解密
QString jiami = getXorEncryptDecrypt(str, 11);
qDebug() << "str:" << str;
qDebug() << "miwen:" << jiami;
QString jiemi = getXorEncryptDecrypt(jiami, 11);
qDebug() << "jimi:" << jiemi;
*/
/*
void MainWindow::on_Btn_Renam_clicked()
{
auto index = ui->tableView->currentIndex();
auto item = m_modelitem.index(index.row(), 0);
auto str = m_modelitem.data(item).toString();
auto ret = QFile::rename(str, "111.txt");
QMessageBox::information(nullptr,"信息",ret?"删除成功":"删除失败");
showfile();
}*/
void MainWindow::on_Btn_Cam_clicked()
{
capture = new QCameraImageCapture(ca);
QString photo_name = m_stusql->Get_filename();
capture->capture("D:/program/QT/build-students-Desktop_Qt_5_12_10_MinGW_64_bit-Debug/debug/photo/" + photo_name + ".jpg");
QMessageBox::information(this, "good", "good!");
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zp2023/QT-student_man.git
git@gitee.com:zp2023/QT-student_man.git
zp2023
QT-student_man
STudnets
students_branch

搜索帮助