首页logo
  •  

jonllen

金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。

个人档案

jonllen
心情闪存 | 给他留言
妮称:jonllen
来自:中国. 湖南. 湘潭
简述:金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。
博客日历

asp项目 — 报价订购系统

分类:Asp.Net

其实我以前在学校里面并没有学过asp的,以前在学校里面学的java的东西最多,其次是.net的课程,不过我一直对.net很感兴趣,好象不只是因为java比较难.net比较人性化些,就感觉它好易用.用.net也做过几个项目了,但是还没有用asp做过,对它还是有点想法.

好象听别人说,asp是asp.net的前身哦,全称为Active Server Page动态页面,服务器端解析也是用IIS,但是它不需要有Microsoft .NET Framework就能直接运行的,在这里我先列举asp和.net的一些不同之处.asp部署简单,没有进行预编译,上传网站即是源代码,这样就有一个安全隐患,网站源文件容易被盗,好象asp页面代码也能加密的,但是比较弱能轻易的就被破解到的.而asp.net网站的话可以把网站预编译,上传为dll文件,这样就安全多了.asp代码不是很严谨,变量可以不申明直接使用,属与弱变量类型.而.net的话是非常面向对象的,如类的继承、多态、重写等.asp写代码调试都比较麻烦,只有少量的智能提示输入,而.net有一个强大的IDE编程环境(VS),达到了很人性化的设置.

上这个asp项目的时候其实心里没底,因为这个项目是原来已经做好成型的,不知道以前别人做得怎么样的,也没有接触过,后来发现它确实是个烂摊子,数据库表结构设计得不合理,代码写得很混乱.没得办法,这次这个报价系统新改版老总很重视,所以只能硬着头皮做了.先看一下我们报价系统登陆成功后的截图:

asp报价系统

以上图片为新报价系统登陆成功后的新界面,它实现和新增了如下新功能:

  1. 增加了IM即时通讯系统,它是一个用JSP开发的Web版的即时通讯,主要用来公司内部人员和客户进行即时沟通.并且和报价系统内用户同步,登陆报价系统则登陆自动登陆上IM,注销则IM下线.如上图IM即使通讯为页面里一个position为absolute布局的可拖拽DIV层,也可以隐藏或显示.
  2. 网站前台和后台和并.以前公司内部人员要登陆http://gl.hhit.com.cn进行订单等管理,而外面客户则是登陆http://bd.hhit.com.cn,现在将统一为http://bd.hhit.com.cn登陆.由于这个报价系统是一个比较特殊的系统,公司很多客户都是通过这个报价系统进行订购下订单的,而且都还有打款但是不是在报价系统里通过支付宝或银行接口进行的,都是在现实中合作认识的值得信赖的客户事先联系好再打款的,报价系统充当着一个展示产品并可下订单订购的重要平台,是直接和金钱打交道的,我们报价系统对不同地区的不同客户给的价格还不一样.
  3. 增加订单议价的功能,借助IM及时通讯,公司内部人员和客户能进行及时的通讯,而且下订单每个产品可以填一个议价,即客户在订购这件产品的时候可以'讨价还价'.订单的流程如下:
    1. ①第一步: 客户通过IM或电话事先联系好通过报价系统下单(可以填议价);
    2. ②第二步: 公司内勤业务(各个产品助理)审核,确认议价和库存,确认是否新去采购或'炒货'(开意向采购单);
    3. ③第三步: 公司信控审核,相当与对客户信用额度的确认,如果非现金交易则需确认客户的帐款(是否有拖欠帐款,如果无则可在信用额度下欠帐款);
    4. ④第四步:财务确认,再次确认用户帐款,提交到ERP内入库,通知物流发货(打印ERP发货单等);
    其中每一步对订单的操作将会被记录,提交到下一步处理的时候都写订单备注可以让内部人员看到,如果有一步没有确认订单将会被打回.
  4. 增加'选项卡'功能,这个是说在一个页面里面打开多个网页,它们可以自由的切换或关闭,比如上图所示是打开了笔记本和LCD显示器的产品浏览页面二个选项卡(首页默认打开),当前是选择浏览笔记本的'选项卡'.

·IM及时通讯

IM及时通讯系统并不是我们开发的,公司把这个项目外包到一个软件公司用JSP开发的.其实我们公司有个同事一直在做Flex开发的,那时候没有上系统前还以为会把IM让我们自己去开发,我们还去到网上找一些Flex的IM开源的项目测试啊等,谁知道最后老总竟把它外包给别人去开发,这里先BS一下.那边开发IM的给我们这里一个接口,一个URL地址,我们这边用一个iframe把他们的页面嵌在我们页面里.当然URL地址肯定要是安全的,我们传给他们那边有如下几个参数:

  • encode:这个是主要编码的字符串,是来识别验证用户的合法性,我们约定好它组成规则为 用户唯一编号+md5密码+key密匙+tempCode一个随机数 以某种方式组合起来.
  • synId:同步ID.这个实为用户ID,只不过这个用户ID是我们这个报价系统内的用户ID,而他们在开发那个IM系统里面就叫同步ID.
  • tempCode:看名字就知道是一个临时的编码,一般就是为当前的时间了.
  • projectId:工程编号,他们那边说要的,这个都为1不变的.

我们这边按照如上要求配置参数发送URL,他们那边也按照此规则进行验证,并在指定时间内有效,实现安全通讯.安全倒是实现了,但是还有一个最大的问题就是数据库用户同步的问题,而我们这个报价系统里就有几千个用户了,而且一直还在增加,怎不能我这里一个个加进去吧?而且以后我们这边用户的资料修改了怎么办?还好他们开发用的数据库也是sqlserver,而且都放在同一个数据库服务器里面,这样我们这边两条sql语句进行跨库同步用户.

/*
注:删除清空数据前应先备份,虽然后来会自动增加上
truncate table [hh_im].[dbo].[SYS_USER_ROLE]
truncate table [hh_im].[dbo].[sys_users]
*/

/*对新增的用户和对应角色同步*/
INSERT INTO [hh_im].[dbo].[sys_users]
([accounts]
,[username]
,[password]
,[Synchronous_Id])
select n.userID,n.userCompanySort
+'('+n.userTrueName+')',n.userpassword,cast(substring(n.user_inner_code,len(n.user_inner_code)-3,4) as numeric) from [HH_Price].[dbo].[tbl_user] n
left outer join [hh_im].[dbo].[sys_users] o on o.Synchronous_Id
=cast(substring(n.user_inner_code,len(n.user_inner_code)-3,4) as numeric)
where o.Synchronous_Id is null

insert into [hh_im].[dbo].[SYS_USER_ROLE]
([SYS_USER_ROLE_USERID],[SYS_USER_ROLE_ROLEID])
select (select [userid] from [hh_im].[dbo].[sys_users]
where [Synchronous_Id]=cast(substring(n.user_inner_code,len(n.user_inner_code)-3,4) as numeric)),cast(n.userTypSN as numeric) from [HH_Price].[dbo].[tbl_user] n
left outer join [hh_im].[dbo].[SYS_USER_ROLE] o on o.SYS_USER_ROLE_USERID
= (select [userid] from [hh_im].[dbo].[sys_users] where [Synchronous_Id]=cast(substring(n.user_inner_code,len(n.user_inner_code)-3,4) as numeric))
where o.SYS_USER_ROLE_USERID is null

/*对修改的用户和对应角色同步*/
update o
set [accounts]=n.userID
,[username]
=n.userCompanySort+'('+n.userTrueName+')'
,[password]
=n.userpassword
from [HH_Price].[dbo].[tbl_user] n
inner join [hh_im].[dbo].[sys_users] o on o.Synchronous_Id
=cast(substring(n.user_inner_code,len(n.user_inner_code)-3,4) as numeric)

update o
set SYS_USER_ROLE_USERID=(select [userid] from [hh_im].[dbo].[sys_users] where [Synchronous_Id]=cast(substring(n.user_inner_code,len(n.user_inner_code)-3,4) as numeric)),
SYS_USER_ROLE_ROLEID
=cast(n.userTypSN as numeric)
from [HH_Price].[dbo].[tbl_user] n
inner join [hh_im].[dbo].[SYS_USER_ROLE] o on o.SYS_USER_ROLE_USERID
= (select [userid] from [hh_im].[dbo].[sys_users] where [Synchronous_Id]=cast(substring(n.user_inner_code,len(n.user_inner_code)-3,4) as numeric))

以上所涉及到的数据库有hh_im和HH_Price及它们所对应表sys_users、sys_user_role和tbl_user、tbl_user的userTypSN列(表示角色类型,主要分为内外部用户)的增加和修改的同步,和他们IM系统的表结构不同,我们系统的角色是一对一的关系,角色类型为用户表的一个列字段,而他们那里设计的时候是用户和角色多对多的关系,所以我们再同步的时候都是以tbl_user为准的操作,在同步新增加的用户的时候是将tbl_user(我们报价系统的)left outer join到sys_users(IM系统用户表)条件是sys_users. Synchronous_Id为空,Synchronous_Id实为我们报价系统的用户ID,通过使用left outer join在加上不为空的条件,即把在tbl_user我们报价系统里的用户在他们sys_users表里不存在的插入到他们sys_users表里,对用户的角色亦是如此,只是他们那里的角色是用的用户角色关联表,他们那边用户角色关联表插入的是新增用户的自动生成编号和角色编号,加个查询条件转个弯一样的也能同步过去.同理,修改用户和用户的角色也能照样能同步,以上sql语句能多次执行,因为只改变同步不相同的行,而不会重复的新增加,如果执行用户和对应的角色影响的记录条数相同的话基本上就没错了,在执行一次应该所影响的记录条数都为0,因为上一次把所有不同的全部都给同步了.把这些sql语句做成一个计划任务,再在我们系统里几个修改用户资料和新加用户的地方多加条sql更新到他们im数据库里去,OK,2个不同数据库的内用户同步搞定!

·订单处理

订单这块是用Flex做的,它生成一个静态页面.我们查看源文件里面可以看到一些object的html标记,它的src就是指向一个swf的文件,它的body里面为noscript标记内写好的一个完整的object标签flash,而head里还有script在页面load的时候又动态生成一个flash,为什么要是这样写呢?原来noscript标记是在浏览器被禁止执行javascript仍然能显示出flash,而当允许执行脚本的时候用javascript动态生成的flash在ie内flash不要单击激活.flash处理订单的界面如下图:

Flash处理订单

Flex生成的Flash就是这样了,呵呵,是不是感觉有点丑?我也觉得有点,没有办法这个没得Flash美工,都是几个程序员搞的,就别说页面美化了,连排版还都是想得我们够脑壳疼的,才发现设计页面排版也有一门很深的学问.

其实订单的处理并不算很复杂,只是中正现实的需求是复杂的.我们公司内部人员能看到订单的人员有很多,主要是分为内勤业务、信控员和调度员这三种角色(一般一个用户只拥有一个角色),不同的角色看到的订单不同,对订单的操作亦不同.

  1. 内勤业务:它是产品助理的工作,主要是对客户下单的产品的确认,以及库存的控制.但是我们的产品不是没有库存就不能进行下单,其实产品是这样的,公司做的产品分为主营和非主营,所谓主营产品字面上的意思的主要销售的产品,实为产品的独家或主要的代理商,即我们进货的上家就是产品生产厂家,如果该产品没有货了,那就不能下单.非主营产品是指不是独家代理商的产品,这样的产品是不受库存控制的,因为这样的产品可先去其他代理商去'抄货',就是我们没这样产品但是我们到其他代理商那里去拿货再买给你(往往价格就会贵一点),这就叫抄货.据说公司现在炒货比自己做的产品还要多,利益熟多熟少我就不是很清楚了.
  2. 一个订单可有多件产品,一个产品可能有多个产品助理.一个产品助理可能同时为多个产品的产品助理.一个产品助理确认通过那订单内那件产品就审核通过,所有产品通过那个订单才通过进入下一步审核.流程基本上就是这样的.这要求产品助理能及时进行处理订单,我们老总是要求产品助理时时守在电脑面前的.而且还规定超过多久没有处理订单就要扣钱.我们还做了一个发短信的程序,如果订单内那件产品超过多久没有处理的话就发段信息到产品助理的手机上,呵呵,当他们看到短信的时候就要扣工资了.扣的是那件产品的所有产品助理的工资.
  3. 程序上,使用Flex开发,服务器端是asp,怎么没有WebServer那怎么办呢?凉拌!其实在Flex里面使用它自动生成引用的WebService的组件并不怎么好用,不单只生成一些无用的东西,而且还有一些Bug,如有时候返回的数据丢失等.直接自己写mx:HTTPService类,它能发送一个http请求并返回,实现WebService类似的功能.对于返回的结果我们可以使用Json来处理,在asp里面我们可以轻松的将adodb.recordset结果集转换为Json对象.代码如下:
    function GetJSON(rs)
    dim returnStr
    dim i
    dim ors
    '将记录集生成JSON字符串
    if not rs.eof then
    returnStr
    = "["
    while not rs.eof
    ors
    = "{"
    for i = 0 to Rs.Fields.Count - 1
    ors
    = ors & chr(34) & rs.Fields(i).Name & chr(34) & ":"
    ors
    = ors & chr(34) & jsonReplace(rs.Fields(i).Value) & chr(34) & ","
    next
    ors
    = left(ors, len(ors) - 1)
    ors
    =ors & "},"
    returnStr
    = returnStr & ors
    Rs.MoveNext
    wend
    returnStr
    = left(returnStr, len(returnStr) - 1)
    returnStr
    = returnStr & "]"
    else
    returnStr
    = "[]"
    end if
    GetJSON
    = returnStr
    end function
    而在Flex端, 有as的Json类,能把它轻易的转换为对象.并把它绑定到DataGrid上呈现出来.其他的操作亦如此,Flex相当与客户端为表示层,而asp则为业务逻辑层,是为具体功能的实现,两者使用Flex传输数据进行通讯,真的比较完美!

·选项卡功能

这一块功能的其实是需要客户体验它的实用性的.以前这个报价系统的主页面是一个frameset框架,它最大的优点是局部刷新.但是这个frameset框架也有很多缺点,整个主页面只能有frameset及FRAME子标签,不允许有其他的标签,连body标签都没有的.这样的一个页面控制起来是比较麻烦的.只能单独控制FRAME里面src里的页面,报价系统里要嵌一个IM及时通讯,而且要能在整个页面里自由拖拽而不是在FRAME里单独某个页面,那改如何实现呢?没得办法只有改掉以前frameset框架,再重新做一个主页,那样便没有什么约束随你怎么放了,而且也好控制多了.在新做的一个页面里右边还是同样多的菜单链接,但是它不是被套在FRAME里面,它就是一个DIV了,当高度过长的时候也有滚动条.但是这个链接都执行那里呢?新打开一个窗体?不!如果我还是要实现以前frameset那些功能的话那要怎么做?有朋友应该会马上想到在中间放一个iframe,然后所有的链接都指向该iframe,思路基本上是这样的!但是我们平时管理产品有很多分类,有时候将要对产品进行频繁的操作,要是能同时打开多个产品的页面但是不是每一个都是打开一个新的浏览器窗体或是替换之前的页面,那样会不会方便一些呢?这时候选项卡就应运而生了.先看张选项卡操作的解图吧.

JS选项卡

选项卡看见了吧,上面首页、笔记本、CPU、价格管理等都是选项卡了.它们是可以自由的切换和关闭的.选项卡就是由一个DIV包裹着的,它的宽度是为100%高度不固定.当前只能选择浏览一个选项卡的页面,切换或关闭一个选项卡是无刷新的.另外选项卡的大小为最大页面可用大小.并且在页面改变大小onresize的时候也跟着改变,我们也兼容了不同分辨率的显示器,分辨率大的那好说,可是小的显示起来就不怎么好看了,例如我们公司还有同事在用14寸的显示器,1024*768的分辨率调不了,因为显卡跟不上了.在他电脑上看的字很大一个,我们能抛弃他们吗?不行,我们得觉得这个问题把它做得更好.

订购报价商务平台

如上图,将浏览器缩小到此大小仍能正常的浏览该网页的.要维持这个页面滚动条状态javascript是少不了的.要动态改变它的宽和高,刚开始写的时候写的有点晕,包括浏览器缩放大小的时候事件不触发,且各种浏览器它的宽高度值会不一样.所以到现在好象有时候还会有点Bug.一般我做网页的时候用IE6做测试,因为根据51la等流量统计等IE6仍是用得最多的浏览器.你不能因为IE7好用而且对一些新样式min-Width等支持容易控制,没什么那么Bug,而在ie6用个div层遮不住select就骂ie6以ie7为标准了(一般在ie6中行就在ie7中行,而在ie7行的不一定在ie6中行).再者是用firefox2.0的浏览器测试,这个版本不高不低,应该也算是ff里的主流了.用ff浏览器主要对web标准的测试.

程序上,选项卡的功能也基本上就是js,说到js,就少不了jquery这个方便实用的好东西.在本项目中除开用了jquery库,还用了它一套ui插件(dialog弹窗).它对浏览器的兼容算是做的不错的,个人是比较佩服的是jquery它的筛选,其次它的Ajax也不错.jquery大部分函数都是返回this本身对象,这个使得我们操作某个dom对象一行搞定所有的功能.其实选项卡实现起来真的比较简单,只要你在写js的时候搞清楚它整个思路,代码是行如流水能有条不紊的写出来.不过写前应该明白:选项卡主要是点击页面链接(主要为左边菜单)时候创建的,每一个选项卡有一个唯一ID控制,由于要打开多个选项卡并且无刷新的自由的切换,所以每一个选项卡应该对应一个iframe,只不过只有一个是显示出来的.切换点击选项卡的过程即是设置对应iframe显示的过程.选项卡和对应iframe必须关联起来,如<a id='test' href='test.asp'>test页面</a>的选项卡id为nav_test对应的iframe的id为item_test(我项目内的命名规则).根据链接就能产生一个选项卡页面.总体实现的思路如下:

  1. 在页面ready(窗体load)里通过jquery筛选找到所有要创建为选项卡的链接,并绑定click事件.
  2. 在click事件里,获取到链接(a标签)的id作为选项卡的id(应该是不包含nav_和item_的)、innerText为选项卡的标题、href为选项卡和对应iframe的地址.
  3. 判断选项卡是否已经打开(id为nav_id或item_id元素是否存在),如果不存在则先隐藏所有所有选项卡再创建选项卡的导航条(需设置它的文本和关闭、点击选中对应的事件)和iframe元素(需用js设置它的宽高度为当前页面最大可用宽高度),并设置为当前所选(导航条为选中样式ifame显示出来其他的都隐藏).
  4. 如果已经打开,则找到设置为当前所选.
  5. click事件的最后为return false,防止打开新窗体.

我想这思路算是比较清晰了的吧,如果你还不明白那可能就是我表述不清了.这里请你不要问我要源代码,如果你对它有兴趣的话,自己动手做一个吧,很简单的,说不定你又能从中学到一些东西呢. 项目就先写到这里:)

标签:Asp.Net
  • posted@ 2009-01-03 00:28
  • update@ 2010-02-11 17:36:54
  • 阅读(10755)
  • 评论(0)

相关文章

评论
暂无任何评论。
发表评论
*必填
回复通知我
*必填

博文推荐