《Delphi程序设计实训教程》课件第7章_第1页
《Delphi程序设计实训教程》课件第7章_第2页
《Delphi程序设计实训教程》课件第7章_第3页
《Delphi程序设计实训教程》课件第7章_第4页
《Delphi程序设计实训教程》课件第7章_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章系教学管理系统之学生教务子系统

-SQL语言在Delphi中的应用

7.1学生教务子系统案例分析

7.2相关知识点

7.3实现方法

7.4案例总结

7.1学生教务子系统案例分析

7.1.1任务的提出

每学期学生要进行选修课程的工作,如果以手工方式进行,比较麻烦且容易出错。考试结束后,学生最关心自己每门课程的分数,以及该课程成绩的总体状况,往往等不到成绩单发送到个人,就去系里询问,这时是系教务干事最忙的时候,没有时间答复学生的咨询。运用学生教务子系统,可解决学生选修课程信息维护和课程成绩查询的问题,使用计算机进行管理,效率高,出错率低,学生满意度高。

学生教务子系统的实现主要是使用数据集组件TQuery。通过本章子系统的实现,我们将学习对数据库中的数据进行维护的另一种方式,即通过数据集组件TQuery使用SQL语句来操作数据集当中的数据。7.1.2系统设计

本章的学生教务子系统的功能模块图如图7.1所示。

图7.1学生教务子系统功能模块图

7.1.3数据库设计及实现

学生教务子系统与教务管理子系统同属于教学管理系统,使用同一个数据库,其设计与实现见第6章。

7.2相

7.2.1TQuery组件在SQL编程中的运用

在Delphi中是通过TQuery组件来实现对SQL语言支持的,也就是说用Delphi开发数据库应用程序时,使用SQL语言操作数据库中的数据的途径是通过TQuery组件。

TQuery组件在Delphi中占有非常重要的地位。

1.TQuery组件的使用

TQuery组件是一个数据集组件,它在Delphi组件面板的“BDE”标签页上,该组件与TTable组件具有很多共同的特性,实现了Delphi对SQL语言的支持。在Delphi开发的数据库应用中,SQL语句是通过TQuery组件传递到要访问的数据库系统的数据库引擎中,由数据库引擎具体执行SQL语句,以实现对数据的操作,而不是传递给Delphi中的BDE,由BDE实施具体的SQL动作。

TTable组件在访问数据库时已经具备很强大的功能,而TQuery组件提供了一些TTable组件不具备的功能,它们是:

●多表联接查询;

●复杂的嵌套查询;

●明确需要使用SQL语言进行的操作。

TTable组件不能使用SQL语言,而TQuery组件可以使用SQL语言,因此TQuery组件也就具备了强大的关系查询能力。

在Delphi应用程序中编写和使用的SQL语句有两种,即静态SQL语句和动态SQL语句。

静态方式是在程序设计阶段,把SQL命令文本作为TQuery组件的SQL属性值进行设置。静态SQL语句在程序设计时便已固定下来,它不包含任何参数和变量。这样,当执行应用程序时,Delphi便执行TQuery组件SQL属性中设置的SQL命令。如果是SQL中的查询命令,把TQuery组件通过TDataSource组件与数据控制组件相连,查询的结果将会显示在与TQuery组件相连接的数据浏览组件中。例如下面的语句便是一条静态SQL语句:

Select*FromSCOREWherecourse='C003'

动态SQL语句也被称作参数化的语句,即SQL语句中包含一些参数变量,在程序中可以动态地为这些参数赋值,在程序运行过程中,各个参数值是可变的。例如下面的语句便是一条动态SQL语句:

Select*FromSCOREWherecourse=:c

2.在TQuery组件中编写简单的SQL查询命令示例

此处我们通过一个简单的实例学习如何使用TQuery组件编写简单的SQL查询命令,并在Delphi应用程序中实现SQL查询。

例如,如果我们想查询出选修课程“C003”的全部学生的学号、课程号及成绩,将结果显示在表格中,可按下列步骤来实现:

(1)在应用程序的窗体中放置一个TQuery组件、一个TDataSource组件和一个TDBGrid组件,TDBGrid组件对象的DataSource属性值为TDataSource组件对象名称,TDataSource组件对象的DataSet属性值为TQuery组件对象名称。

(2)设置窗体TQuery组件对象Query1的DatabaseName属性值为TEACH。

(3)双击ObjectInspector窗口中Query1的SQL属性,将显示StringListEditor窗口,在该窗口中输入SQL语句:

select*fromscorewherecourse='C003'

然后单击“OK”按钮,关闭StringListEditor窗口。

(4)设置Query的Active属性为True。

这样在TDBGrid组件对象上马上可以看见SQL语句查询的结果。

7.2.2SQL语言编程概述

在Delphi应用程序中的SQL命令语句包含在TQuery组件的SQL属性中,TQuery组件的SQL属性是TString类型的,也就是说SQL属性值是一个字符串列表,这个字符串列表非常类似于一个字符串类型的数组。

1.SQL命令文本的编辑

1)使用StringListEditor编辑SQL命令文本

在程序设计过程中,可以通过对象查看器编辑SQL属性。在ObjectInspector中双击SQL属性,这样会打开StringListEditor窗口,如图7.2所示,在其中我们便可以编辑SQL命令。

图7.2编辑SQL命令的StringListEditor窗口

2)在代码中编辑SQL命令文本

可以在代码中编辑SQL命令文本。在程序运行过程中,要想设置TQuery组件的SQL属性,必须首先调用TQuery组件的Close方法关闭当前的TQuery组件,然后调用Clear方法清除SQL属性中现存的SQL命令的文本内容,最后调用Add方法为SQL属性设置新的SQL命令语句。例如:

Query1.Close; //关闭Query1

Query1.SQL.Clear; //清除SQL属性中的SQL命令文本

Query1.SQL.Add('Select*FromSCORE');

Query1.SQL.Add('WhereCOURSE=''C003'''); //添加SQL语句

注意在应用程序中为SQL属性设置新的SQL命令语句时,必须要调用Clear方法清除SQL属性中现存的SQL命令语句;如果不调用Clear方法而直接调用Add方法向SQL属性中设置SQL命令语句,那么新设置的SQL命令语句会追加在现存SQL命令语句的后面,在程序运行时常常会出现出乎意料的查询结果甚至程序无法运行下去。

2.SQL命令的执行

在为TQuery组件设置完SQL属性的属性值之后,即编写好SQL命令之后,可用多种方式来执行SQL命令。

在设计过程中,设置完TQuery组件的SQL属性之后将其Active属性值设置为True,

这样便可以执行SQL属性中的SQL命令,如果应用程序中有与TQuery组件相连的数据控制组件(如TDBGrid、TDBEdit等),那么在这些数据控制组件中会显示SQL命令的执行结果。

在应用程序运行过程中,通过程序调用TQuery组件的Open方法或ExecSQL方法可以执行其SQL属性中的SQL命令。

Open方法和ExecSQL方法是不一样的,在程序设计过程中一定要注意。Open方法只能用来执行SQL语言的查询语句(Select命令),并返回一个查询结果集;而ExecSQL方法主要是用来执行其他的SQL语句,如INSERT、UPDATE、DELETE等命令。例如:

Query1.Open;如果调用Open方法,而没有查询结果时,会出错。此时应该调用ExecSQL方法来代替Open方法:

Query1.ExecSQL;

当然在设计应用程序时,有时程序设计人员是无法确定TQuery组件中的SQL语句是否会返回一个查询结果的。对于这种情况应当用Try…Except模块来设计程序。在Try部分调用Open方法,而在Except部分调用ExceSQL方法,这样才能保证程序的正确运行。

例如:

Try

Query1.Open;

Except

Query1.ExecSQL;

End;

3.通过TQuery组件获得活动的数据

通过TTable组件从数据库中获得的数据都是活动的,也就是说用户可以直接通过数据控制组件对这些数据进行编辑修改。而通过TQuery组件可以获得两种类型的数据:

1)“活动”的数据

这种数据就与通过TTable组件获得的数据一样,用户可以通过数据控制组件来编辑修改这些数据,并且当调用Post方法或当焦点离开当前的数据控制组件时,用户对数据的修改自动地被写回到数据库中。

2)非活动”的数据(只读数据)

对于“非活动”的数据,用户通过数据控制组件不能修改其中的数据。在缺省情况下,通过TQuery组件获得的查询结果数据是只读数据即“非活动”的,要想获得“活动”的数据,在应用程序中必须要设置TQuery组件的RequestLive属性值为True,然而并不是在任何情况下如此设置都可以获得“活动”的数据。要想获得“活动”的数据,除了将TQuery组件的RequestLive属性设置为True外,还要能够返回“活动”的数据,相应的SQL命令语句要满足一定的约束条件。根据查询的数据库类型不同,约束条件也不相同,大致的约束条件如下:

(1)查询只能涉及到一个单独的表;

(2)SQL语句中不能包含ORDERBY命令;

(3)SQL语句中不能含有SUM、AVG等聚集运算符;

(4)在Select后的字段列表中不能有计算字段。

当TQuery组件返回一个“活动”的查询结果数据集时,它的CanModify属性的值会被设置成True。

7.2.3动态SQL语句的使用

动态SQL语句又被称为参数化的SQL语句,在其中包含着在程序过程中可以变化的参数。在实际的程序设计中使用得更多的是动态SQL语句。此处将重点介绍如何给动态SQL语句的参数赋值,以在应用程序中灵活地使用SQL语句。动态SQL语句的编写、执行等与前面介绍的静态SQL语句的编写、执行是相同的。

对于动态SQL语句中的参数,我们可以通过两种途径来为它赋值。

1.使用参数编辑器(ParameterEditor)为参数赋值

具体方法是:选中TQuery组件,在对象查看器中双击Params属性,便可以打开参数编辑器。

例如,在TQuery组件对象Query1的SQL属性中设置如下的SQL语句:

Setect*FromSCOREWherecourse=:c;

Query1的DatabaseName属性为TEACH。Query1的SQL语句中的c为参数变量。双击对象查看器中的Params属性,打开参数编辑器,可看见其中所有的参数(本例中只有一个参数“0-c”),选择参数c,对象查看器内容如图7.3所示。

图7.3参数值的赋值方式之一

在对象查看器中,DateType组合框中选择该参数的数据类型为字符型ftString,ParamType中选择ptInput,在Value编辑框中可以为参数c赋值。这样Query1的SQL查询便准备好了,参数值赋值给了动态SQL语句中相应的参数,此时当把Query1的Active属性设置成True,与Query1组件相连的数据控制组件中便会显示出查询结果。

通过参数编辑器为参数赋值,这种方式缺乏应有的灵活性,在实际应用中用得较少,在实际应用中程序设计人员希望用更灵活方便的方式为参数赋值,这就是我们接下来要介绍的另一种途径。

2.在程序中为参数赋值

在程序中为动态SQL语句的参数赋值有四种方法:

●根据参数在SQL语句中出现的顺序,设置TQuery组件的Params属性值为参数赋值。

●使用ParamValues属性为各参数赋值。

●调用ParamByName方法为各参数赋值。

将TQuery组件的DataSource属性设置为另一个数据源,这样将另一个数据源中与当前TQuery组件的SQL语句中的参数名相匹配的字段值赋给其对应的参数。

1)使用Params属性为参数赋值

TQuery组件有一个Params属性,它们在设计期间不可用,在程序运行期间可用,并且是动态建立的。当为TQuery组件编写动态SQL语句时,Delphi会自动地建立一个数组Params,数组Params是从0下标开始的,依次对应动态SQL语句中的每个参数,也就是说动态SQL语句中第一个参数对应Params[0],第二个参数对应Params[1],依此类推。

例如,有一个TQuery组件对象Query1,我们为它编写的动态SQL语句是:

InsertIntoSCORE(course,student,score)

Values(:cou,:stu,:score)

对于上述这条动态SQL语句中的参数,我们可以利用Query1的Params属性为参数赋值:

Query1.Params[0].AsString:='C003';

Query1.Params[1].AsString:='20060066';

Query1.Params[2].AsInteger:=90;

上述语句将把'C003'赋值给参数:cou,'20060066'赋值给参数:stu,90赋值给参数:score。

2)使用Params的ParamValues属性为参数赋值

TQuery组件有一个Params属性是参数数组,它有一个ParamValues属性,使用ParamValues['参数名']的形式可以直接引用到参数名指定的参数的值。使用这种方式是直接引用到参数的值,所以在使用该形式对参数进行赋值时,不必使用AsString等类型转换函数进行类型转换。使用这种方式时要知道参数的名字。

对于上面的例子,也可以使用下面的方式对参数赋值:

Query1.Params.ParamValues['cou']:='C003';

Query1.Params.ParamValues['stu']:='20060066';

Query1.Params.ParamValues['score']:=90;

3)使用ParamByName方法为参数赋值

ParamByName是一个函数,以动态SQL语句中的参数名字作为调用ParamByName函数的实际参数,这样便可以为它们赋值。使用这种赋值方法,必须要知道动态SQL语句参数的名字。

例如在上面的例子中,也可以用下述方法给参数赋值:

Query1.ParamByName('cou').AsString:='C003';

Query1.ParamByName('stu').AsString:='20060066';

Query1.ParamByName('score').AsInteger:=90;注意使用上述第1)种和第3)种方式对参数进行赋值时,Query1.Params[0]或Query1.ParamByName('cou')等形式引用到的是参数,其类型是TParam类型,而非String、Integer等类型,不能直接进行赋值,所以这两种方式引用参数后都要使用AsString、AsInteger等类型转换函数进行类型转换后再赋值。

4)使用DataSource属性为参数赋值

上述三种方法的共同特点是:在为各参数赋值时,我们是知道各参数对应的具体参数值的。而在具体的应用程序中,有些参数的值常常是无法确定的。例如参数的值来自于另一个查询结果,对于这种情况,Delphi提供了使用DataSource属性为动态SQL语句中的参数赋值。当SQL语句中尚存在没有赋值的参数时,Delphi会自动检查TQuery组件的DataSource属性,如果为DataSource属性设置了属性值(该属性的值是另一个TDataSource组件对象的名字),Delphi会把没有赋值的参数与TDataSource组件对象对应的数据集中的各字段进行比较,Delphi会将同名的字段的值赋值给该参数。这种方法主要是实现主细表数据库应用,与我们在学习使用TTable组件时曾创建主要——明细型数据库应用是相似的。

例如,在如图7.4所示的应用中,在左侧表格中选定了某门课程,右侧表格中相应地显示该门课程的所有成绩,注意右侧表格内容跟随左侧表格中所选定的课程而变化。窗体中放置了如表7-1所示的组件对象。

图7.4TQuery主细表应用

表7-1TQuery主细表应用的主要组件对象及属性表

在窗体的OnCreate事件中加入如下代码:

procedureTForm1.FormCreate(Sender:TObject);

begin

database1.Open;

table1.Open;

query1.Open;

end;

Query1中的动态SQL语句中的参数:id,在设计期间中没有给它赋值,代码中也没有对其赋值。当该应用程序运行时Delphi会自动地到其Datasource属性中说明的数据源datasource1对应数据集table1中查找与参数:id匹配的字段,而table1中正好有一个名字为

id的字段与参数:id相匹配。

这样table1数据集中当前记录的id字段值赋值给了参数:id,

每当移动table1数据集中的记录指针时,参数:id的值会随之改变,而参数:id的值发生改变时,query1中的动态SQL语句会根据新的参数值重新查询,从数据库表中获取相应的成绩数据,这样也就实现了主要-明细型应用。

7.3实

7.3.1教务管理子系统功能模块的创建

在Delphi7中创建一个新的工程,工程名为“STTEACH.dpr”。

1.登录窗体

图7.5登录窗体布局

登录窗体的基本功能和布局与教务管理子系统中的登录窗体相似,如图7.5所示。

将教务子系统中的“clerk_login.pas”和“clerk_login.dfm”文件复制到新工程所存放的文件夹中。将clerk_login窗体添加到STTEACH工程中,再将该窗体另存为“stu_login.pas”,在文件夹中出现“stu_login.pas”及“stu_login.dfm”文件,可将该文件夹中的“clerk_login.pas”和“clerk_login.dfm”文件删除。将窗体布局和“登录”按钮的OnClick代码做适当的修改:

procedureTf_login.Button1Click(Sender:TObject);

begin

...

ift_user['authority']='1'then

...

end;

2.主要功能窗体

学生教务子系统主要功能窗体名为“stu_main.pas”。学生教务子系统有两部分功能:选修课程信息添加、删除和成绩查询、统计。同样,使用PageControl组件的两个TabSheet来实现这两部分功能。

1)学生选修课程记录的添加与删除

该界面的功能是进行学生选修课程的信息维护,包括选课信息的添加和删除,若要修改则应该先删除再添加。左侧DBGrid组件对象显示学生未选修的课程具体信息,右侧DBGrid组件对象显示学生已经选修的课程信息。在左侧表格中选定课程,双击课程或点击“加入”按钮将添加该学生选修该课程的信息至SCORE表。在右侧表格中选定课程,双击课程或点击“删除”按钮将从SCORE表中删除该学生选修该课程的记录。总学分要随加入或删除课程而动态变化,数据表格的内容也要随加入或删除课程而动态变化。

图7.6学生选课管理

表7-2学生选课管理界面主要组件对象及属性表

关闭该窗体将中止整个应用程序的运行。

procedureTf_stu.FormClose(Sender:TObject;varAction:TCloseAction);

begin

application.Terminate;

end;在窗体的标题上显示登录该应用程序的学生姓名,在该窗体创建或显示时执行该代码,将代码放在窗体的OnShow事件中,代码如下:

procedureTf_stu.FormShow(Sender:TObject);

begin

t_student.Filter:='id='''+trim(f_login.Edit1.Text)+'''';

t_student.Filtered:=true;

t_student.Open;

f_stu.Caption:=f_stu.Caption+'--学生:'+t_student['name'];

end;

在“学生选课”页显示时,左侧数据表格要显示学生尚未选修的全部课程具体信息,右侧数据表格中显示学生已经选修的全部课程信息,在总学分处显示该学生已经选修的全部课程的学分总和。这里分别使用了三个TQuery组件对象来实现。注意,此处总学分的计算要求总和,如果使用TTable组件,求总和要在程序中遍历全部数据并求和,很麻烦,而使用SQL语句则直接使用统计函数求和即可。学生选修全部课程信息有课程编号和课程名称,涉及到SCORE和COURSE两个数据表中的数据,使用TTable实现比较麻烦,使用SQL语句进行这样的查询是很容易实现的。而在左侧数据表格中显示学生尚未选修的全部课程具体信息,要从COURSE表中去掉已经选修的课程,然后显示这些课程的信息,使用SQL语句进行这样的查询都比较复杂,更不会使用TTable来实现,故三处的数据都来自TQuery数据集。我们看到此处TabSheet1的OnShow事件代码非常简单,因为大部分工作是在前面设置TQuery组件对象的SQL属性时完成的。注意查看前面属性表格中TQuery组件对象的SQL属性值。注意,由于登录应用程序的学生不同,SQL的内容也会不同,所以三个TQuery组件对象的SQL属性值中都使用了参数,并在程序中动态地给出参数值。

procedureTf_stu.TabSheet1Show(Sender:TObject);

begin

q_course1.Close;

q_course1.Params[0].AsString:=trim(f_login.Edit1.Text);

q_course1.Open;

q_course_selected.Close;

q_course_selected.Params[0].AsString:=trim(f_login.Edit1.Text);

q_course_selected.Open;

q_sum_credit_hour.Close;

q_sum_credit_hour.Params[0].AsString:=trim(f_login.Edit1.Text);

q_sum_credit_hour.Open;

dbgrid1.Columns[0].Width:=52;

dbgrid1.Columns[1].Width:=100;

dbgrid1.Columns[2].Width:=40;

dbgrid1.Columns[3].Width:=30;

dbgrid1.Columns[4].Width:=30;

end;点击“加入”按钮时,使用insertinto语句实现数据的添加。该处并没有使用一个预先定义好SQL属性值的TQuery组件对象,而是在程序中使用SQL属性的Clear、Add等方法动态地设置SQL属性值,这样做是由于此处的添加与后面的删除共用了一个TQuery组件对象。

procedureTf_stu.Button1Click(Sender:TObject);

begin

q_adddel.Close;

q_adddel.SQL.Clear;

q_adddel.SQL.Add('insertintoscore(student,course)');

q_adddel.SQL.Add('values('''+trim(f_login.Edit1.Text)+''','''+q_course1['课程编号']+''')');

q_adddel.ExecSQL;

TabSheet1Show(nil);

end;双击DBGrid1组件对象中的行时,也会将该课程的选修信息添加至SCORE表,也就是相当于点击了“加入”按钮。故在DBGrid1的OnDblClick事件中调用Button1的OnClick事件代码:

procedureTf_stu.DBGrid1DblClick(Sender:TObject);

begin

Button1Click(nil);

end;点击“删除”按钮时,使用deletefrom语句实现数据的删除。该处同样是在程序中动态地设置SQL属性值。

procedureTf_stu.Button2Click(Sender:TObject);

begin

withq_adddeldo

begin

Close;

sql.Clear;

sql.Add('deletefromscore');

sql.Add('whereid='+inttostr(q_course_selected['id']));

ExecSQL;

end;

TabSheet1Show(nil);

end;双击DBGrid2组件对象中的行时,同样相当于点击了“删除”按钮。

procedureTf_stu.DBGrid2DblClick(Sender:TObject);

begin

Button2Click(nil);

end;

2)学生成绩查询与成绩统计

本界面的功能是查询学生的某门课程的成绩,并对该门课程做简单的统计。用一个DBGrid组件对象给出登录该应用程序的学生所选修并有成绩的所有课程信息,提供给学生选择查询成绩的课程。当选定数据表格中的一行时,在界面的右侧给出该学生该课程的成绩,以及选修这门课程的全部学生的成绩的平均值、最高值和最低值。

界面布局如图7.7所示,其主要组件及属性见表7-3。

图7.7成绩查询

表7-3成绩查询界面主要组件对象及属性表

“成绩查询”页显示时,DBGrid3对象中要显示学生选修并有成绩的课程信息,右侧显示第一条记录的课程成绩信息。TabSheet2的OnShow事件代码如下:

procedureTf_stu.TabSheet2Show(Sender:TObject);

begin

q_course_learned.Close;

q_course_learned.Params[0].AsString:=trim(f_login.Edit1.Text);

q_course_learned.Open;

DBGrid3CellClick(nil);

end;点击DBGrid3的单元格时,表示要显示该行对应的课程的该学生成绩、课程的平均成绩、最高成绩和最低成绩。平均成绩、最高成绩和最低成绩分别使用了三个TQuery组件对象,这些TQuery组件对象均使用课程编号作为参数,此处要将选定的课程编号赋值给参数,以下分别使用三种方式引用参数值。DBGrid3的OnCellClick事件代码如下:

procedureTf_stu.DBGrid3CellClick(Column:TColumn);

begin

q_avg.Close;

q_avg.Params.ParamValues['c']:=q_course_learned['课程编号'];

q_avg.Open;

q_max.Close;

q_max.Params[0].AsString:=q_course_learned['课程编号'];

q_max.Open;

q_min.Close;

q_min.Params.ParamByName('c').AsString:=q_course_learned['课程编号'];

q_min.Open;

end;本系统的代码量不大,是因为大量使用了TQuery组件。TQuery组件能够很方便地对多个数据表进行操作,并且能够使用统计函数对数据进行统计,在这样的情况下,我们首选TQuery组件而非TTable组件。

图7.8用户登录窗体

7.3.2系统的实现

程序运行时,同样会先显示用户登录窗体,如图7.8所示。

输入用户名和密码后,单击“登录”按钮,在此将验证用户名、密码和权限是否正确,若其中任一处验证失败,将分别给出错误提示信息。验证通过,将显示主要功能窗体,如图7.9所示。

图7.9选修课程信息维护

在窗体的标题

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论