🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
###一、起步 ####目录结构 项目主要的文件夹有: framework—可能用到的框架、库全都在这里 img—存放图片,所有人均将图片存放到这里 module_xxx—存放每个人的代码 public_code—存放通用的代码、样式、页面 GlobalModule.cs—拦截器,用来拦截请求和处理一些状态,不用关心 index.html—系统的引导页 sqlhelper.cs—数据库的类,里面的连接字符串需要改成自己的 ![](https://box.kancloud.cn/35f152696d99d45ee875da6517a8780d_388x383.png) ####代码结构 1、刘添齐和王胜 css文件夹用来存放样式,Master是模板页,index.aspx是包含模板页的aspx(新建的时候需要留意),dll文件夹用来存放数据库代码(css文件夹用来存放样式,js夹文件用来存放js代码,server文件夹用来存放服务端代码(.ashx文件),dll文件夹用来存放数据库代码(用户和管理员全都用一个dll文件夹),index.aspx是普通的aspx页(不是包含模板页的aspx),admin文件夹的目录结构和外面的一样,用来存放管理员代码。 )。admin文件夹的结构和外面的一样,用来存放管理员的代码。在新建包含模板页的aspx时要注意选择外面的Master还是admin文件夹里面的Master。 ![](https://box.kancloud.cn/b2c9bfb2d5b789b05f61a2e2eff4a804_238x175.png) 2、赵开朗 css文件夹用来存放样式,js夹文件用来存放js代码,server文件夹用来存放服务端代码(.ashx文件),dll文件夹用来存放数据库代码(用户和管理员全都用一个dll文件夹),index.aspx是普通的aspx页(不是包含模板页的aspx),admin文件夹的目录结构和外面的一样,用来存放管理员代码。 ![](https://box.kancloud.cn/dab5c631521991d7dabf6aa3675a5283_227x212.png) ###二、状态约定 ####账户(银行卡)状态 state: 0:正常 1:挂失 2:紧急挂失 isDeleted: 0:正常 1:已删除 accountType: 1:借记卡 2:信用卡 ####业务开通状态 state: 0:未开通业务 1:开通业务 ####管理员状态 type: 0:普通管理员 1:超级管理员 state: 0:正常 1:拉黑 isDeleted: 0:正常 1:已删除 ####用户状态 sex: 0:男 1:女 isDeleted 0:正常 1:已删除 ###三、数据库编写 ####规定 数据库的代码存放到各自的dll文件夹中,用到哪些表就新建一个同名的类,不允许使用别人模块里面的dll文件,如果两个人都用到了userInfo表,那么两个人的dll文件夹里面都有userInfo类。 ![](https://box.kancloud.cn/804a9d5f09580c35d8561318c0242ed5_244x289.png) 每个类里面封装数据库的方法,都是public static,命名方式要见名知其意。 ![](https://box.kancloud.cn/216438389dd24bad106f708cab921db8_558x353.png) ####返回类型 使用select语句则需要使用DataSet类型,update、delete、insert均使用int类型。 ####示例 scmd.CommandText之前的代码都是一样的,直接copy就行,scmd.CommandText为sql语句,@是参数化查询,用于防止sql注入,SqlParameter里面的两个参数和函数的形参以及sql语句里面的@必须一样,如果函数有两个形参,那么就要有两个scmd.Parameter.Add 1、返回DataSet类型 ![](https://box.kancloud.cn/8d96a8c6d7b68b10442efa138254e450_783x304.png) 2、返回int类型 ![](https://box.kancloud.cn/83da0a1dfdf363a468b02964f00594ad_887x281.png) ####如何使用数据库返回的结果 在王胜、刘添齐的aspx.cs文件,赵开朗的ashx文件中: ~~~ int id=1;string password="123"; int result = module_qc.dll.admin.ModifyPassword(id, password); if(result>0)//说明update成功 { //正常业务逻辑 } else { //错误处理的逻辑 } ~~~ ~~~ int id=1; DataSet ds=module_qc.dll.admin.GetAdminInfo(int id); DataTable dt=ds.Tables[0];//取到结果集的table if(dt.Rows.Count>0)//结果集的行数大于0,说明有数据 { for(int i=0;i<dt.Rows.Count;i++) { System.Diagnostics.Debug.WriteLine(dt.Rows[i]["userName"]); //取第i行的userName字段的值并打印到控制台 } } else { //select语句没有查询到数据 } ~~~ ####注意 只要操作含有isDeleted字段的表,sql语句里面都要加上"and isDeleted=0"。 ###格外注意事项 为了保证数据的安全性和可用性,需要加强代码的严谨性。比如:当管理员通过了用户的银行卡销户申请(也就是把数据库的银行卡isDeleted置为1),那么用户接下来不能对这张卡做任何操作。再比如:当超级管理员删除了一个管理员,那么管理员无论是刷新页面还是做操作都会被告知“您已被删除”,并跳转到登录页面。 ####拦截器 拦截器已经帮你们处理了一些操作,用户被删除、管理员被删除或拉黑,这些都会自动给出提示信息进行错误操作,但是银行卡的删除和挂失并没有且无法写到拦截器里面帮我们自动处理。因此,对于银行卡的操作要先判断是否被删除,是否被冻结,然后才是正常的业务逻辑,判断是否被删除、冻结的sql方法都存放在了sqlhelper里面,直接调用方法即可。 ####银行卡删除和冻结的区别 银行卡一旦被删除,用户不能对这张卡做任何操作,银行卡被冻结,用户只能进行只读操作(比如能查看银行卡的信息,但是不能修改信息)。 ###操作Session ####王胜、刘添齐 在aspx.cs文件中直接通过Session["key"]去读取Session,Session["key"]=value去设置Session,在读取Session的时候要先判断Session和要读取的数据是否存在。 ~~~ if(Session!=null&&Session["id"]!=null) { int id=Convert.ToInt32(Session["id"]); } ~~~ ####赵开朗 ashx文件中需要先实现Session的接口(在IHttpHandler后面加额外的代码,如下) ~~~ public class admin_adminInfo_modifyPassword : IHttpHandler,System.Web.SessionState.IRequiresSessionState ~~~ 通过HttpContext.Current.Session对Session进行操作,一样的要先判断Session和要读取的数据是否存在 ~~~ if(HttpContext.Current.Session!=null&&HttpContext.Current.Session["id"]!=null) { int id=Convert.ToInt32(HttpContext.Current.Session["id"]); } ~~~ ####项目中可能用到的Session 各个角色的主键id:id, 用户的名字:userName, 管理员的名字:adminName, 超级管理员的名字:adminSName ####类型转换 从数据库中取出的数据(dt.Rows[i]["字段名"])以及从Session中取到的值都是object类型,可以通过类型转换将它们转换成我们期望的类型。 常用的类型转换:xxx.ToString(),Convert.ToInt32(xxx) ###常用的代码 ####发送短信 ~~~ //在最上面using Application.public_code” 在函数体中: string phone="18829211660"; string content="你的内容" string sms_url = "http://utf8.sms.webchinese.cn/?Uid=sunnychuan&Key=b4155b8baaab64d74d70&smsMob=" + phone + "&smsText=" + content; string sms_code = phoneCode.GetHtmlFromUrl(sms_url); if(sms_code==1){//短信发送成功} else{//说明发送失败了,可能是手机号不存在或者系统错误} ~~~ ####接收前端的图片并保存到本地 ~~~ HttpPostedFile file=前端发送过来的文件; string fileName = Path.GetFileName(file.FileName); string hz = Path.GetExtension(file.FileName); string newName="/img/qc_" + System.Guid.NewGuid().ToString()+hz;//重命名文件避免名字冲突,前面的"/img/qc_"是规定,用于区别四个人操作的图片,如果刘添齐想保存图片那么就改成"/img/ltq_"。 file.SaveAs(context.Request.MapPath(newName));//保存到项目的img文件夹下 int result=module_qc.dll.AddImg(newName);//将图片的路径存放到数据库中。 ~~~ ###赵开朗需要留意 ####异常处理 拦截器会拦截所有的ajax请求,以下的代码必须要写,这是规定 ~~~ 管理员所发出的所有请求: if(res.code==200){//正常操作} else if(res.code==401||res.code==402){alert(res.msg);window.location.href="/public_code/admin/login.html";} else if(res.code==500){alert(res.msg)} 用户所发出的所有请求: if(res.code==200){} else if(res.code==401){alert(res.msg);window.location.reload();} else if(res.code==500){alert(res.msg)} ~~~ 可能你也有自己的逻辑,比添加新闻失败,删除失败等等,在ashx中返回code 300,前端去判断code,这个code 300需要你自己在后端写 ~~~ //后端 JObject obj=new JObject(); if(result>0) { obj.Add("code",200); obj.Add("data",null); context.Response.Write(obj); } else { obj.Add("code",300); obj.Add("msg","你的错误提示信息"); context.Response.Write(obj); } ~~~ ~~~ if(res.code==200){} else if(res.code==300){你自己的错误处理逻辑} else if(res.code==401){alert(res.msg);window.location.reload();} else if(res.code==500){alert(res.msg)} ~~~ code 200与data,code 300与msg ####token 所有的ajax请求都要将token发送给后端,后端不用管这个token,代码都是在拦截器里面的。 对于管理员来说,只有登录了才能做各种管理的操作,在所有的请求中将token发送给后端 ~~~ $.ajax({ data:{token:window.userInfo.token} }) ~~~ 对于用户来说,赵开朗的用户模块都是登录和不登录均可,当用户未登录的时候,userInfo.token是不存在的,因此 ~~~ if(window.userInfo.isLogin==true){ $.ajax({//用户登录了,把token发送给后端 data:{token:window.userInfo.token} }) } else{ $.ajax({//用户没登录,不用管token data:{} }) } ~~~ ####后端 赵开朗的每个ashx文件都负责前端的一个ajax请求,所有ashx文件都要实现Session接口,哪怕你后端没有用到Session也要写 ~~~ public class admin_adminInfo_modifyPassword : IHttpHandler,System.Web.SessionState.IRequiresSessionState ~~~ ###通用样式 ####主题颜色 用户:#0095d9 管理员:#ff494e ####button 用户的button ~~~ <button class="btn btn-default">黑字白背景色</button> <button class="btn btn-default blue-btn">白字蓝背景色</button> <button class="btn btn-default red-btn">白字红背景色</button> ~~~