《计算机与信息工程学院规范化课程.docx》由会员分享,可在线阅读,更多相关《计算机与信息工程学院规范化课程.docx(79页珍藏版)》请在三一办公上搜索。
1、计算机与信息工程学院规范化课程大型数据库案 例丽水学院计算机与信息工程学院周建东2007年11月76目 录案例一:项目管理信息系统.1案例二:微机租赁管理系统.18案例三:丽水学院刷卡考勤系统.49案例一:项目管理信息系统本例是一个简化的“项目管理信息系统”,以项目信息(项目编码、项目名称、开发经费、应用情况和参加人员)以及项目开发人员自身的信息(编码、姓名、性别、出生年月、职称、部门)为主线,以部门表等为辅表,实现了项目和人员信息的录入、查询和管理等功能,展示了用PowerBuilder开发系统的方法和技巧。本系统的主要功能包括以下几部分:项目管理信息系统系统管理统计报表数据处理部门维护人员
2、维护人数统计项目统计更改密码数据备份用户管理项目维护一、创建应用PowerBuilder8.0的应用程序是以工作区文件、目标文件、库文件的形式保存的,因此创建这些文件是编写应用程序的第一步。1创建应用的步骤如下: 在Windows资源管理器中为应用新建一个目录,如D:Project。此目录用于保存本系统的工作区文件、目标文件、应用库文件和数据库文件。 启动PowerBuilder8.0,单击Power工具栏的新建按钮,打开。 在New对话框中选择图标,打开New对话框。 选择保存Workspace的目录(D:Project),并在文件名文本框中输入Project,然后单击“保存”按钮,回到Po
3、werBuilder主界面。 单击Power工具栏中的新建按钮,打开New对话框,选择Target标签页,并双击Application图标,打开Specify New Application and Library对话框。在该对话框中要指定应用对象名及所用库、目标,输入应用对象名后,按Tab键,会以默认方式自动为应用对象指定Library和Target,如下图所示: 单击Finish按钮就建立了一个空白的应用对象project,可以在PowerBuilder的System Tree中看到。2应用的Open事件脚本:SQLCA.DBMS = ODBCSQLCA.AutoCommit = Fals
4、eSQLCA.DBParm = Connectstring=DSN=ProjectCONNECT USING SQLCA;IF SQLCA.SQLCode0 THENBeep(1)MessageBox(连接错误,SQLCA.SQLerrText)Halt CloseELSE/this.ToolbarText = Truethis.ToolBarFrameTitle = 框架窗口工具条this.ToolBarSheetTitle = 当前窗口工具条this.ToolBarPopMenuText = 左边,上边,右边,下边,浮动,显示文字,图标提示OPEN(w_login)END IF上述脚本的作
5、用主要是建立与数据库的连接,然后打开登录窗口。二、创建数据库1数据库设计本系统采用了PowerBuilder8.0自带的一个小型关系数据库Adaptive Server Anywhere7.0。在PowerBuilder8.0集成环境下创建数据库的步骤如下: 单击Power工具栏的DB Profile按钮,打开Database Profiles对话框。 在Database Profiles对话框中展开ODB ODBC列表项,在展开其下面的Utilities列表项。双击Create ASA Database项,系统打开Create ASA Database对话框。 在Create ASA Dat
6、abase对话框中输入Database Name(如D:ProjectProject.db),其余均用默认值。单击OK按钮,系统开始创建数据库。PowerBuilder在创建数据库后,自动创建了ODBC数据源Project和描述文件Project,并自动连接上数据库。如果用Sybase Central创建ASA数据库,还需要手工创建ODBC数据源和描述文件。2创建数据表本数据库包含5个数据表: 部门信息表(department)列名列标识数据类型宽度小数空值主键部门编码dept_idchar20NY部门名称dept_namechar200NN 人员信息表(personnel)列名列标识数据类型
7、宽度小数空值主键编码p_idchar40NY姓名namechar100NN性别sexchar10YN 项目信息表(project)列名列标识数据类型宽度小数空值主键项目编码pro_idchar40NY项目名称pro_namechar400NNoutlaydouble80YN 项目参与人员表(member)列名列标识数据类型宽度小数空值主键项目编码pro_idchar40NY编码p_idchar40NY 系统用户信息表(users)列名列标识数据类型宽度小数空值主键用户编码user_idchar100NY用户姓名user_namechar100NN密码passwdchar60YN创建表的外键和索
8、引以创建表personnel的外键为例,介绍创建外键的步骤。 在数据库画板的Object视图中,找到并双击打开personnel表,右击Foreign Keys,打开弹出式菜单。 在弹出式菜单中选择New Foreign Key菜单项,进入Foreign Key视图。在Gereral标签页中设置外键名称和本表外键对应字段;在Primary Key标签页中设置外键的对应表;在Rules标签页中设置外键连接规则。其创建的外键为:fk_dept_id,外键字段为p_id,对应department表的主键dept_id 设置完成后,单击工具栏上的Save按钮,保存所创建的外键。表member的两个外键
9、,分别为:fk_member_proid:外键字段为pro_id,对应project表的主键pro_idfk_member_pid:外键字段为p_id,对应表personnel的主键p_id3创建编辑风格在数据库画板中创建编辑风格,并设定表中某列的编辑风格,这样在日后生成数据窗口时,该列将使用在数据画板中定义的编辑风格,从而可以节省设计的时间和工作量。本实例需要创建三个编辑风格,分别命名为es_department、es_project和es_personnel,分别用来显示部门数据、项目数据和开发人员数据。这三个编辑风格均使用下拉数据窗口样式,因此,在创建编辑风格之前,首先应创建三个数据窗口
10、对象。创建dddw_department数据窗口对象该数据窗口的表现风格为Tabular,数据源为department表的所有列。在数据窗口画板下,把dept_id设为不可见。该数据窗口的布局如图所示。下面以创建es_department编辑风格为例,介绍具体操作步骤为: 在数据库画板下,打开扩展属性(Extended Attributes)视图,右击Edit Styles项目,显示弹出式菜单。 在弹出式菜单中选择New菜单项,打开Edit Style对话框。 按照下图所示,输入各有关参数。 输入完毕,单击OK按钮,返回数据库画板。三、创建用户对象、全局函数和祖先窗口为了减轻应用程序设计的工作
11、量,以及使应用程序更容易维护,在进行系统开发时往往需要创建一些用户对象。本实例需要创建多个命令按钮用户对象和两个数据窗口用户对象,还需要创建一个用来对用户口令加密的全局函数,创建一个作为所有表单(Sheet)祖先的窗口。1创建命令按钮用户对象为应用中常用的命令按钮创建用户对象,然后根据需要把这些按钮用户对象添加到窗口中,可以使应用界面保持一致,也便于日后维护。本实例需要创建8个按钮用户对象。这8个按钮用户对象的名称、属性和功能如下表所示。名称Text属性值功能uo_ok确定(&Y)确认当前操作uo_closse关闭(&C)关闭当前窗口uo_delete删除(&D)删除当前记录uo_edit编辑
12、(&E)编辑当前记录uo_find查找(&F)打开查询窗口uo_new新增(&N)新增一条记录uo_refresh刷新(&R)刷新当前数据窗口uo_save保存(&S)保存数据下面以关闭按钮用户对象为例,介绍建立按钮用户对象的步骤。 单击Power工具栏上的New按钮,在打开的New对话框中选择PB Object标签页,然后选择Standard Visual图标,在单击OK按钮,打开Select Stantard Visual Type对话框。 在对话框中选择Commandbutton列表项,然后单击OK按钮,打开用户对象画板。 在属性视图中设置有关属性,如下图所示: 在脚本视图中编写该按钮c
13、licked事件的脚本。“关闭”按钮的clicked事件脚本为:Close(Parent) 单击画板工具栏的Save按钮,保存用户对象,名字为uo_close。按照上述办法建立其它按钮用户对象。(除uo_close外,其它按钮不选中Cancel属性,而且不用编写事件脚本)。 2创建数据窗口用户对象本实例需要建立两个数据窗口用户对象。 建立uo_dw_freeform数据窗口用户对象单击Power工具栏上的New按钮,在打开的New对话框中选择PB Object标签页,然后选择Standard Visual图标,再单击OK按钮,打开Select Standard Visual Type对话框,选
14、择datawindow列表项,然后单击OK按钮,打开用户对象画板。 定义外部全局变量。语句如下:String gs_userid,gs_pwd /用户ID,用户密码Boolean gb_manager /管理者 建立用户自定义事件。首先定义API函数subroutine keybd_event(uint bVk,uint bScan,long dwFlags,long dwExtraInfo ) library user32.dllShift_er自定义事件:事件ID为pbm_dwnkey。事件脚本如下:/回车键及下箭头键下移焦点If key = KeyEnter! Or Key = KeyD
15、ownArrow! Thenkeybd_event ( 9, 0, 0, 0 ) / 按下tab keybd_event ( 9, 0, 2, 0 ) / 释放tab Return 0End If /上箭头键上移焦点If Key = KeyUpArrow! Then keybd_event ( 16, 0, 0, 0 ) / 按下shift keybd_event ( 9, 0, 0 , 0 ) / 按下tab keybd_event ( 9, 0, 2, 0 ) / 释放tab keybd_event ( 16, 0, 2, 0 ) / 释放shift Return 1 End If 该事件
16、用来实现在数据窗口中用回车键及上下箭头移动输入焦点。注:用回车键代替Tab键也可以用发送消息的方式来实现: Send(Handle(this),256,9,Long(0,0)Return 1ue_delete自定义事件:事件ID为none。事件脚本如下:/删除当前记录IF GetRow()0 THENIF DeleteRow(0)=1 THENMessageBox(提示,当前记录已被删除,请按保存按钮提交)END IFEND IF该事件用来删除数据窗口的当前记录。ue_refresh自定义事件:事件ID为none。事件脚本如下:/刷新数据This.Retrieve()该事件用来重新检索数据窗口
17、的数据(刷新显示)。ue_save自定义事件:事件ID为none。事件脚本如下:/保存数据IF this.Update()0 THENCOMMIT USING SQLCA;MessageBox(提示,数据已存盘)ELSEROLLBACK USING SQLCA;MessageBox(提示,数据无法存盘,Exclamation!)END IF该事件用来更新并提交数据窗口的当前记录。 编写dberror事件的脚本。MessageBox(数据库错误,错误代码:+string(sqldbcode)+&rn+错误信息:+sqlerrtext)Return 1 以uo_dw_freeform为名保存该用户
18、对象。建立uo_dw_gridform数据窗口用户对象该用户对象继承自uo_dw_freeform,把shift_er自定义事件的脚本更改为:/按回车键向后移焦点IF key = KeyEnter! THENkeybd_event ( 9, 0, 0 , 0 ) / 按下tab keybd_event ( 9, 0, 2, 0 ) / 释放tabReturn 1END IF数据窗口标准类,用回车键、下箭头、上箭头改变输入焦点,适用于grid风格3建立全局函数f_encrypt()该函数用来实现对系统用户口令的加密。函数的定义信息如图所示。函数的脚本如下:/功能:口令加密/参数:字符串/返回值:
19、字符串Integer i,li_kllenString ls_zmklli_kllen=LEN(a_ymm)FOR i = 1 TO li_kllen ls_zmkl = ls_zmkl+CHAR(ASC(Mid(a_ymm,i,1)+i+li_kllen)NEXTRETURN ls_zmkl通过加密函数,保存在数据库的用户密码就不是明文,而是加密的密文。4建立表单(Sheet)祖先窗口w_basesheet该窗口的所有属性均采用默认值。其Open事件的脚本如下:this.X=(w_main.WorkSpaceWidth() - this.Width)/2this.Y=(w_main.Work
20、SpaceHeight() - w_main.mdi_1.MicroHelpHeight - this.Height)/2 - 50上述语句的作用是实现表单窗口在工作区的中间显示。由于主窗口w_main还未创建,因此需要把它们加上注释标记,待创建主窗口后,再去掉注释标记。四、各功能窗口的设计1系统主窗口的设计本实例创建的是多文档界面(MDI)应用,因此需要创建一个主窗口作为应用程序的主界面。该窗口的类型为mdihelp,窗口标题为“项目信息管理系统”。窗口以w_main为名字存盘。编写窗口的closequery事件脚本:long ll_returnll_return = messagebox(
21、提示信息,确认退出系统吗?,Question!,YesNo!,1)if ll_return = 2 then return 1 /不关闭窗口elsereturn 0 /关闭窗口end if这段程序的作用是,当用户关闭系统主窗口时,系统会提示用户是否确认退出,以避免用户的误操作导致系统终止运行,如下图所示。2用户登录窗口用户登录窗口是应用程序的入口,用来对用户的身份进行验证。 新建一个窗口,窗口类型为Response,窗口标题为“用户登录”。 在新窗口中添加以下控件:一个图片控件;两个静态文本控件,其Text属性分别是“用户名”和“用户密码”;两个单行编辑框控件,分别命名为sle_name和sl
22、e_pw;两个按钮用户对象uo_ok和uo_close,分别命名为cb_ok和cb_close。窗口的整体布局如下图所示: 定义全局变量:String gs_userid,gs_pwd /用户ID,用户密码Boolean gb_manager /管理者 建立实例变量:Integer ii_time=1 /登录次数 为sle_name的Modified事件编写如下脚本:sle_pw.SetFocus() 为sle_pw的Modified事件编写如下脚本:IF KeyDown(KeyEnter!) THENif this.text = then returnelseSetFocus(cb_ok)c
23、b_ok.triggerevent(clicked!)end ifend if 为cb_ok的Clicked事件编写如下脚本:String ls_name,ls_pw,ls_typels_name=sle_name.Textls_pw=sle_pw.TextIF ls_name THEN/取出用户密码和用户类别SELECT passwd,user_typeINTO :gs_pwd,:ls_typeFROM usersWHERE user_id=:ls_name;IF f_encrypt(ls_pw) gs_pwd THENIF ii_time=3 THENMessageBox(登录错误,对不起
24、,你无权使用本系统!,Exclamation!)HALT CLOSEELSEii_time+MessageBox(登录错误,请输入正确的用户名或密码,Exclamation!)END IFsle_name.SetFocus()ELSEIF ls_type=0 THEN /管理用户gb_manager=TRUEEND IFgs_userid=ls_nameOPEN(w_main)Close(Parent)END IFEND IF上面的语句主要用来实现密码的验证功能,如果密码正确,则允许进入系统,同时把用户名保存到全局变量中;如果密码错误,则提示重新输入,当三次输入错误的密码后,系统强行关闭。在这
25、段程序中使用了SQL嵌入语句“SELECT ”, 保存窗口,窗口名字为w_login。关于用户登录窗口的改进如下图所示,将用户名文本框改为下拉列表框,用户可从下拉列表框中选择用户名而不需要自己输入用户名。上述操作员登录窗口的控件列表如下:控件类型控件名说明窗口W_login响应类型窗口下拉列表框Ddlb_1用于显示操作员列表供选择单行编辑框Sle_1供用户输入口令按钮Cb_1用于输入完毕后的确认按钮Cb_2用于取消输入,推出登录图片P_1用于显示窗口左面的图片在登录窗口的Open事件中,取得操作员的用户名供登录者选择,并置入默认的操作员。脚本如下:String ls_opid /声明操作员姓名
26、变量String ls_lastid /声明上次登录操作员姓名变量/1、获取操作员信息SetPointer(HourGlass!) /把鼠标指针改为漏斗状DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA ; /定义动态游标PREPARE SQLSA FROM SELECT name FROM operators ORDER BY name ;OPEN DYNAMIC my_cursor ; /打开动态游标FETCH my_cursor INTO :ls_opid ; /从数据库中取数据Do While sqlca.sqlcode = 0 /如果取到数据ddl
27、b_1.AddItem(ls_opid) /把取得的操作员名添加到下拉列表框FETCH my_cursor INTO :ls_opid ;/取下一数据Loop /循环CLOSE my_cursor ; /关闭动态游标/2、设置初始操作员IF ddlb_1.TotalItems() 0 THEN /如果操作员列表存在列表项ls_lastid = ProfileString(example.ini,操作员信息,上次登录操作员姓名,) /从INI文件中取得上次登录的操作员IF ls_lastid = THEN /如果未取到ddlb_1.SelectItem(1) /选择下拉列表框的第一个列表项ELS
28、E /如果取得上次登录的操作员ddlb_1.SelectItem(ls_lastid, 0)/选择下拉列表框中的该操作员姓名END IFEND IF上述脚本中用到了游标技术。其作用是将SQL语句得到的多个操作员姓名逐个添加到下拉列表框之中。“确定”按钮的Clicked事件对用户选择的操作员和输入的口令进行校验,以判断是否为合法登录。如果通过校验,把操作员姓名赋值给字符串全局变量gs_operator(该变量是应用对象的全局变量)。在应用对象的Open事件中根据全局变量gs_operator来判断是否需要继续执行。Clicked的事件脚本如下:Stringls_opid /声明用户名变量Stri
29、ng ls_pass /声明操作员口令变量ls_opid = ddlb_1.Text /取得用户选择下拉列表框中的用户名IF ls_opid = THEN /如果未取到用户名MessageBox(登录提示, 请选择正确的操作员!)Return /返回END IFSELECT pass INTO :ls_pass FROM operators WHERE name = :ls_opid ;IF ls_pass sle_1.Text THENMessageBox(系统提示, 口令错误!)ReturnEND IFSetProfileString(example.ini,操作员信息,上次登录操作员姓名
30、,ddlb_1.Text) /把操作员姓名置入INI文件gs_operator = ls_opid /把操作员姓名赋值给字符串全局变量Close(Parent)“取消”按钮的Clicked事件:gs_operator = /把空字串赋值给全局变量Close(Parent) /关闭操作员登录窗口上述登录校验代码没有确定登陆的次数,应进行修改完善。此外还可以对登录口令采用加密算法进行加密,在数据库的操作员管理表中使用加密的口令,避免口令的泄密。在登录是在将数据库操作员管理表中的口令解密,与登录者输入的口令核对。3部门数据录入与维护窗口该窗口用来两种部门代码数据进行录入、删除和编辑。 继承w_bas
31、esheet建立一个新窗口。 往窗口添加5个按钮用户对象,分别为:uo_new、uo_delete、uo_refresh、uo_save和uo_close,分别命名为cb_new、cb_delete、cb_refresh、cb_save和cb_close。一个uo_dw_grid用户对象,命名为dw_department,其Dataobject属性为d_department。窗口布局如下图所示: 创建与dw_department关联的数据窗口对象d_department。该数据窗口的表现风格为Grid,数据源为department表的所有列。数据窗口的布局如下图所示: 定义窗口的实例变量:in
32、teger ii_id 编写窗口的Open事件的脚本:dw_department.SetTransObject(SQLCA)dw_department.Retrieve() 编写cb_new的Clicked事件的脚本:String ls_maxidLong ll_rowcount,ll_rowll_rowcount=dw_department.RowCount()IF ll_rowcount0 THENls_maxid=dw_department.GetItemString(ll_rowcount,dept_id)ii_id=Integer(ls_maxid)+1ELSEii_id=1END
33、IFll_row=dw_department.InsertRow(0)dw_department.ScrollToRow(ll_row)dw_department.SetItem(ll_row,dept_id,String(ii_id,00)dw_department.SetFocus()上述语句首先取得数据窗口的最大部门ID,把它加1后赋值给新增记录的dept_id字段。 编写cb_delete的Clicked事件的脚本:dw_department.Event ue_delete() 编写cb_refresh的Clicked事件的脚本:dw_department.Event ue_refre
34、sh() 编写cb_save的dw_department.Event ue_save() 保存窗口,窗口的名字为w_department。4数据备份窗口为了放置数据丢失和破坏,必须对系统数据进行定期备份。数据备份窗口用来实现数据备份功能。 新建一个Response类型的窗口,窗口的标题为“数据备份”。 往窗口添加一个静态文本控件,其Text为“备份路径”,在它后面添加一个单行编辑框控件,命名为sle_path。在sle_path的后面添加一个图像按钮,命名为pb_browse,该图像按钮的Picture Name为PowerBuilder提供的Custom050。用一个成组框把上面三个控件框起
35、来。再添加两个用户对象:uo_ok和uo_close,分别命名为cb_ok和cb_close。窗口布局如下图所示: 为了保存备份路径,以便下次打开窗口时作为默认路径显示,因此需要创建一个配置文件(INI文件)。方法如下:启动Windows记事本,在编辑区输入如下的语句:BackupPath然后以project.ini为文件名存盘,存盘时“保存类型”记住选择“所有类型文件(*.*)”,而不要将它存为.txt文件。 编写窗口Open事件的脚本:String ls_pathls_path=ProfileString(project.ini,backup,path,)sle_path.Text=ls_
36、path上述语句从配置文件中取出备份路径,并在sle_path中显示出来。 编写cb_ok的Clicked事件脚本:String ls_path,ls_runBoolean lb_fexistls_path = sle_path.textIF trim(ls_path)= OR Isnull(ls_path) THENMessageBox(提示,请输入或选择备份目录)sle_path.SetFocus()ReturnELSEIF FileExists(ls_path)=FALSE THENIF MessageBox(提示,ls_path+不存在,是否创建该目录?,Question!,YesNo
37、!,1)=1 THENInteger li_filenumIF CreateDirectory ( ls_path )1 THENMessageBox(提示,无法创建目录)Close(Parent)ReturnEND IFELSEsle_path.SetFocus()END IFEND IFEND IFSetProfileString(project.ini,backup,path,ls_path)ls_run = dbbackup -c uid=dba;pwd=sql + -y +ls_path+Close(Parent) 编写pb_browse图像的Clicked事件脚本:String l
38、s_path = c:projectdataInteger li_resultli_result = GetFolder( 选择备份文件夹, ls_path )IF li_result=1 THENsle_path.text=ls_path END IF上述语句判断输入的备份路径,如果该目录不存在,则提示创建文件夹,然后把数据备份到文件夹中。否则直接把数据备份到文件夹中。注意,这段程序中调用的备份命令dbbackup.exe是专门针对Adaptive Server Anywhere7.0数据库开发的。对其它数据库就不能使用这个命令。 保存窗口,窗口的名字为w_backup。5更改密码窗口设计该
39、窗口允许用户更改本人登录系统的密码。 新建一个Response类型的窗口,窗口的标题为“密码更改”。 往窗口添加三个静态文本控件,他们的Text属性分别为:“原密码”、“新密码”、“再次输入新密码”。在静态文本控件的后面添加三个单行编辑框控件,分别命名为:sle_oldpw、sle_newpw、sle_newpwag,用一个成组框把上述控件框住。添加两个用户对象uo_ok和uo_close,分别命名为cb_ok和cb_close。窗口的布局如下图所示: 编写sle_oldpw的Modified事件的脚本:sle_newpw.SetFocus() 编写sle_newpw的Modified事件的脚
40、本:sle_newpwag.SetFocus() 编写sle_newpwag的Modified事件的脚本:IF this.Textsle_newpw.Text THENMessageBox(错误,前后密码不一致,请重输)this.SetFocus()ELSEcb_ok.SetFocus()END IF 编写cb_ok的Clicked事件的脚本:String ls_cpwdIF f_encrypt(sle_oldpw.Text)gs_pwd THENMessageBox(错误,原密码错误,请重输)sle_oldpw.SetFocus()ELSEIF sle_newpw.Textsle_newpw
41、ag.Text THENMessageBox(错误,前后新密码不一致,请重输)sle_newpw.SetFocus()ELSEls_cpwd=f_encrypt(sle_newpw.Text)UPDATE usersSET passwd = :ls_cpwdWHERE user_id = :gs_useridUSING SQLCA;IF SQLCA.SQLNRows 0 THENCOMMIT USING SQLCA;MessageBox(提示,密码已成功更改)gs_pwd=ls_cpwdELSEROLLBACK USING SQLCA;MessageBox(错误,无法更改密码)END IFCL
42、OSE(Parent)END IFEND IF 保存窗口,窗口的名字为w_chpwd。案例二:微机租赁管理系统某电脑公司的一项业务是微机出租经营。过去采用手工管理的方式,管理比较混乱,每到月末计算租金收入以及统计微机库存情况,都要临时计算,不仅很不正规,而且也容易出错。为此,拟研究开发一个微机出租管理系统,用计算机进行微机出租管理。考虑这是一个比较小的系统,因此这里只进行简单的系统分析与设计。一、系统分析与设计 可行性分析建立微机出租管理系统从技术上看是可行的。微机出租业务比较简单,所谓管理只需要建立相应的数据库,进行简单的统计计算就可以完成。而电脑公司的人员具备了开发这样系统的能力。建立微机出租管理系统从经济上看也是可行的。电脑公司本身就有微机,不需要另行购置;系统开发没有费用;系统运行也不增加新的费用。系统运行虽然不会带来直接的经济效益,但管理水平的提高也会带来间接的效益。建立微机出租管理系统从应用方面考虑也是可行的。系统不是很复杂,管理人员很快就能熟悉;公司本身又有改善管理的愿望,系统运行后会提高企业的管理水平,因此也不会有大的阻力。 系统的环境要求与基本结构考虑电脑公司规模