QR码越来越多的出现在了人们的日常生活中,比如 电影票、电子优惠券、甚至是电子机票。

    你能想象这样一张图片包含多少信息吗?

ssss

    如今智能手机得到了普及,大多数手机也能读取QR码的信息。

    今天闲着无聊,写了一个小程序,用来生成QR码。程序很简单,没有使用到任何QR技术,不包含任何这方面的算法或者使用第三方的组件。只是简单的利用网络现有的免费资源。http://www.qrstuff.com/ 是国外的一个网站,它提供免费的QR生成服务。

    分析了一下源代码,发现只要通过 http://www.qrstuff.com/generate.generate?type=TEXT&text={0}&foreground_color=000000 这个地址就能生成指定内容的QR码 参数 text 指定为你所要的内容即可。

    程序很简单

image

    就一个类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace CreateQR
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 产生QR码的地址
        /// </summary>
        readonly string qrcreateurl = "http://www.qrstuff.com/generate.generate?type=TEXT&text={0}&foreground_color=000000";

        private void btnSave_Click(object sender, EventArgs e)
        {
            //保存数据
            SaveData(picData);
        }

        /// <summary>
        /// 保存数据
        /// </summary>
        /// <param name="data"></param>
        private void SaveData(byte[] data)
        {
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "PNG格式图片|*.png";
            saveFileDialog1.Title = "图片保存";
            saveFileDialog1.ShowDialog();
            if (saveFileDialog1.FileName != "")
            {
                if (File.Exists(saveFileDialog1.FileName))
                {
                    File.Delete(saveFileDialog1.FileName);
                }
                using (FileStream fs = File.Create(saveFileDialog1.FileName))
                {
                    fs.Write(data, 0, data.Length);
                }
            }
        }

        /// <summary>
        /// 临时图片数据
        /// </summary>
        private byte[] picData;

        private void btnCreate_Click(object sender, EventArgs e)
        {
            //下载
            DownloadData(string.Format(qrcreateurl,
                string.IsNullOrEmpty(txtQR.Text) ? "无内容" : txtQR.Text),
                (_send, _e) =>
                {
                    picData = _e.Result;
                    using (MemoryStream ms = new System.IO.MemoryStream())
                    {
                        ms.Write(picData, 0, picData.Length);
                        pictureBox.Image = Image.FromStream(ms);
                    };

                });
        }

        /// <summary>
        /// 下载数据
        /// </summary>
        /// <param name="url"></param>
        /// <param name="dceh"></param>
        private void DownloadData(string url, DownloadDataCompletedEventHandler dceh)
        {
            using (WebClient webClient = new WebClient())
            {
                webClient.DownloadDataAsync(new Uri(url));
                webClient.DownloadDataCompleted += dceh;
            };

        }


    }
}

文章最下面有全部源码以及demo 的下载地址

点我下载Demo

汤晓华 QQ 1881597 MSN tension1990@hotmail.com

2011 05 22

posted @ 2011-05-22 14:35 tandly 阅读(2078) 评论(8) 编辑

    最近公司在做一款OA的二次开发,是基于 J2EE 架构的 采用的 Spirng3 +Struts2+Hibernate3 UI 采用的EXTJS3。这款产品的框架设计的比较好,这几天正在研究。其中hibernate查询采用的通用方法,进行集中的查询字段收集、创建Criteria、查询数据。

    首先介绍一下实现思路。

    定义一个QueryFilter对象,然后在构造中接受一个HttpServletRequest对象,QueryFilter对HttpServletRequest中的 查询参数进行遍历,找到符合约定的参数时,对参数进行分析,并封装成hibernate的criteria对象,再交给service,service再交给dao,进由hibernate进行数据查询。

以下是大致的方法签名和调用

QueryFilter filter = new QueryFilter(HttpServletRequest request);
List<BookType> list = bookTypeService.getAll(filter);

过滤条件的名称必须符合如下规则:Q_firstName_S_EQ ,其中Q标识该查询参数是一个QueryFilter能识别的字符,firstName 表示待查询的属性名称(可以是外键对象的属性),S 表示为 String 类型,EQ 表示 equals ,当然 S 位置 和 EQ 位置还有其它约定的表达式。通过这种方式,在进行数据查询时,不需要进行硬编码,只需要在html代码,或者JavaScript进行 Ajax 查询时,指定符合要求的querystring 即可。

以下是extjs中查询时候的代码

return new Ext.Panel({
		id : 'BookTypeView',
		title : '档案类别列表',
		iconCls : 'menu-book-type',
		autoScroll : true,
		items : [new Ext.FormPanel({
			height : 35,
			frame : true,
			id : 'BookTypeSearchForm',
			layout : 'column',
			defaults : {
				xtype : 'label'
			},
			items : [{
				text : '请输入查询条件:'
			}, {
				text : '档案类别'
			}, {
				xtype : 'textfield',
				name : 'Q_typeName_S_LK'
			}, {
				xtype : 'button',
				text : '查询',
				iconCls : 'search',
				handler : function() {

					search();

				}
			}, {
				xtype : 'button',
				text : '取消查询条件',
				iconCls : 'btn-del',
				handler : function() {
					var searchPanel = Ext.getCmp('BookTypeSearchForm');
					var grid = Ext.getCmp('BookTypeGrid');
					searchPanel.items.get(2).setValue("");
					search();

				}
			}]
		}), this.setup()]
	});
};

    为了使我以后更懒的工作,周末花了点时间写了一个C#&Asp.Net的实现(其实我主要是做.NET平台的,Java我真的不想做)。大致上还是采用的这款OA中实现的思路。但是发现一个问题,它的QueryFilter只能够进行与查询,也就是各个查询条件是用AND相连接的,无法进行OR查询,或者 多个条件单独与或 在 与 另外一个条件与或 , 比如 (a = 1 and b = 2) or c = false ,所以我简单实现了 多组查询的功能。查询字符串的约定规则模仿Q_firstName_S_EQ  稍微做了一些改变 ,例如:Q_firstName_S_EQ_AND_0_1 , 其中 Q_firstName_S_EQ 部分是完全一致的。

AND 为条件聚合方式,可以是 AND 或者 OR ,

0 必须为数字,表示查询条件的组 , 相同的组ID将被归并成一个查询条件

1 必须为数字,表示查询条件组中成员的顺序

查询条件组 与 组成员都将按照顺序产生 HQL 语句。

可能光从字面上理解有点误会,笔者表达的也却有欠缺。

打个比方:

Q_firstName_S_LK_AND_0_1,

Q_lastName_S_LK_OR_0_2,

Q_age_I_>_AND_1_1,

其中 Q_firstName_S_LK_AND_0_1,Q_lastName_S_LK_OR_0_2 属于同一组 将产生 (firstName like :firstName and lastName like :firstName )

Q_age_I_>_AND_1_1 单独一组 将产生 (age = :age)

两组合并为一句HQL语句为(firstName like :firstName and lastName like :firstName) or (age = :age) 。

那么 and 和 or 又是按照什么规则连续的呢?

组我的规则是,同一组的查询条件的聚合类型作用于下一个查询条件,前一组的最后一个成员的聚合方式作用于下一组,又很拗口…………

对照一下

(firstName like :firstName and lastName like :firstName) or (age = :age) 。

Q_firstName_S_LK_AND_0_1,Q_lastName_S_LK_OR_0_2,Q_age_I_>_AND_1_1  ,??? 最后一个AND 呢?只要当前查询条件是最后一个,AND 或者 OR 将被忽略。很难设计啊…

以下是创建HQL的部分C#代码

 //-----------------动态创建 where 语句开始--------------------




                string lastCT = "";
                var lastGroup = queryable.LastOrDefault();
                foreach (var item in queryable)
                {
                    var last = item.LastOrDefault();
                    hqlSb.Append(" (");
                    foreach (var _item in item)
                    {

                        lastCT = _item.ConnectionType;
                        hqlSb.Append(" t.");
                        hqlSb.Append(_item.CreateHqlPart());
                        if (!last.Equals(_item))
                        {
                            hqlSb.Append(" " + lastCT + " ");
                        }
                    }

                    hqlSb.Append(") ");

                    if (lastGroup.Key != item.Key)
                    {
                        hqlSb.Append(lastCT);
                    }

                }


                //-----------------动态创建 where 语句结束--------------------

项目结构如下,东西不多

image

具体代码如下

Filter.cs

/* ***********************************************
 * 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
 * Email:tension1990@hotmail.com 
 * QQ:1881597
 * 描述 :
 * 创建时间:2011/5/15
 * 修改历史:
 * ***********************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Criterion;

namespace Tension.NHibernate.Query
{
    /// <summary>
    /// 过滤条件
    /// </summary>
    public class Filter
    {
        #region 字段属性
        public string ParamName { get; set; }
        /// <summary>
        /// 条件中的字段名称
        /// </summary>
        public string PropertyName { get; set; }

        /// <summary>
        /// 条件中的字段值
        /// </summary>
        public object PropertyValue { get; set; }

        /// <summary>
        /// HQL占位作用的字段名 区别在于 弱 是关联对象查询 则去处 . 号 如 PropertyName=Group.Name 则PlaceholderPropertyName=GroupName
        /// NHibernate 在分析HQL时 若占位符存在 . 会报异常
        /// </summary>
        public string PlaceholderPropertyName { get; set; }
        /// <summary>
        /// 字段数据类型
        /// </summary>
        public string PropertyType { get; set; }
        /// <summary>
        /// 条件类型
        /// </summary>
        public string Operation { get; set; }
        /// <summary>
        /// 条件组连接类型
        /// </summary>
        public string ConnectionType { get; set; }
        /// <summary>
        /// 条件组
        /// </summary>
        public int Group { get; set; }
        /// <summary>
        /// 组成员索引
        /// </summary>
        public int Index { get; set; }

        private int pindex = 0;

        /// <summary>
        /// 参数索引位置
        /// </summary>
        public int PIndex
        {
            get { return pindex; }
            set
            {

                PlaceholderPropertyName = PropertyName.Replace(".", "") + value;
                pindex = value;
            }
        }

        /// <summary>
        /// 参数全名
        /// </summary>
        private string paramName;


        /// <summary>
        /// 不需要添加到IQuery 的参数集合
        /// </summary>
        public bool NoAdd { get; set; }

        /// <summary>
        /// 支持的数据类型的简写
        /// </summary>
        private string[] PropertyTypes = new string[] { "S", "D", "DEC", "FT", "I", "IS", "IB", "ST", "L", "B", "ARR" };
        /// <summary>
        /// 支持的比较运算符
        /// </summary>
        private string[] Operations = new string[] { "EQ", "LT", "<", "GT", ">", "LE", "<=", "GE", ">=", "LK", "LIKE", "LFK", "LIKE%", "RHK", "%LIKE", "NULL", "NOTNULL", "IN", "BT" };

        #endregion

        #region 构造
        /// <summary>
        /// 空构造
        /// </summary>
        public Filter() { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramVal"></param>
        public Filter(string paramName, object propertyValue)
        {

            /**
             * 
             * Q_propertyName_S_EQ_AND_0_1
             * 
             * 使用  _ 分割 
             * 0 位置 Q 是判断字符串是否为查询字符串
             * 1 位置 Q_propertyName_S_EQ_AND_0_1 是字段名称
             * 2 位置 S 是字段类型
             * 
             *    该位置的其他值有:
             *   S=string D=DateTime,DEC=decimal,FT=float,I=Int32,IS=Int16,IB=Int64,ST=short,L=Long,B=bool
             * 
             * 3 位置 EQ 是条件类型 比如EQ代表等于
             * 4 位置 AND 是 AND 或者 OR 查询组的最后一个查询表达式的 AND 或者 OR 将被忽略
             * 5 位置 0 代表的是条件组
             * 6 位置 1 代表条件组中条件的顺序 
             * 
             *   查询组的组后一个查询成员的  4 位置 值在当前查询组中不起作用 
             *   若存在下一查询组 则查询组后一个查询成员的的  4 位置 值作为与下一查询组的连接符
             *      
             *   例如 
             *   Q_propertyName0_S_EQ_AND_0_1 
             *   Q_propertyName1_S_EQ_AND_1_1 
             *   Q_propertyName2_S_EQ_AND_2_1
             *   以上三个查询条件将被翻译为 (propertyName0 = :propertyName0) and (propertyName1 =  :propertyName1) and (propertyName2 =  :propertyName2)
             *   
             * 
             *   Q_propertyName0_S_EQ_AND_0_1
             *   Q_propertyName1_S_EQ_OR_1_1 
             *   Q_propertyName2_S_EQ_AND_1_2
             *   以上三个查询条件将被翻译为 (propertyName0 = :propertyName0) and (propertyName1 = :propertyName1 or propertyName2 = :propertyName2)
             *   
             *   Q_propertyName0_S_EQ_AND_0_1 
             *   Q_propertyName1_S_EQ_OR_0_2 
             *   Q_propertyName2_S_EQ_AND_1_1 
             *    Q_propertyName3_S_EQ_AND_1_2
             *   以上4个查询条件将被翻译为 (propertyName0 = :propertyName0 and propertyName1 = :propertyName1) or (propertyName2= :propertyName2  and or propertyName3= :propertyName3)     
             * 
             * 
             * 
             * 
             * */
            ParamName = paramName;

            if (paramName.IndexOf("Q_") != 0)
            {
                throw new ArgumentNullException("查询条件[paramName]不是合法的查询语句!必须以 Q_ 开头");
            }

            this.paramName = paramName;
            this.PropertyValue = propertyValue;

            //执行解析
            Analysis();

        }


        #endregion

        #region 方法
        /// <summary>
        /// 解析
        /// </summary>
        private void Analysis()
        {
            if (paramName == null)
            {
                throw new ArgumentNullException("查询条件[paramName]不能为空!");
            }

            string[] param_s = paramName.Split('_');

            if (param_s.Length < 7)
            {
                throw new ArgumentException(string.Format("\n\n    查询条件: {0} 不符合规范,请按照 如下标准:Q_propertyName0_S_EQ_AND_0_0\n", paramName));
            }


            PropertyName = param_s[1];
            //除去关联对象查询时的 . 例如 Group.Name 
            PlaceholderPropertyName = PropertyName.Replace(".", "");
            //字段类别的简写
            PropertyType = param_s[2].ToUpper();
            if (!PropertyTypes.Contains(PropertyType))
            {
                throw new ArgumentException("参数字符串中[2]位置(字段类别的简写) 必须为:" + string.Join(",", PropertyTypes));
            }


            Operation = param_s[3].ToUpper();

            if (!Operations.Contains(Operation))
            {
                throw new ArgumentException("参数字符串中[3]位置(支持的比较运算符) 必须为:" + string.Join(",", Operations));
            }

            ConnectionType = param_s[4].ToLower();

            if (ConnectionType != "and" && ConnectionType != "or")
            {
                throw new ArgumentException("参数字符串中[4]位置(查询条件的连接方式) 必须为 AND 或者 OR");
            }

            try
            {
                Group = int.Parse(param_s[5]);

            }
            catch (Exception)
            {
                throw new ArgumentException("参数字符串中[5]位置(代表所属查询组) 必须为整数数字");
            }
            try
            {
                Index = int.Parse(param_s[6]);

            }
            catch (Exception)
            {
                throw new ArgumentException("参数字符串中[6]位置(代表查询组成员排序) 必须为整数数字");
            }



            //处理like 是的 value



            if ("LK" == Operation || "LIKE" == Operation)
            {
                PropertyValue = string.Format("%{0}%", PropertyValue);
            }
            else if ("LFK" == Operation || "LIKE%" == Operation)
            {
                PropertyValue = string.Format("{0}%", PropertyValue);
            }
            else if ("RHK" == Operation || "%LIKE" == Operation)
            {
                PropertyValue = string.Format("%{0}", PropertyValue);
            }

            //处理 NULL 或者 NOTNULL 查询设置该filter 是否要添加参数到查询

            else if ("NULL" == Operation)
            {
                NoAdd = true;
            }
            else if ("NOTNULL" == Operation)
            {
                NoAdd = true;
            }

        }



        /// <summary>
        /// 产生 HQL 的 where 部分条件字符串
        /// </summary>
        /// <returns></returns>
        public string CreateHqlPart()
        {

            if ("LT" == Operation || "<" == Operation)
            {
                return string.Format("{0} < :{1} ", PropertyName, PlaceholderPropertyName);
            }
            else if ("GT" == Operation || ">" == Operation)
            {
                return string.Format("{0} > :{1} ", PropertyName, PlaceholderPropertyName);
            }
            else if ("LE" == Operation || "<=" == Operation)
            {
                return string.Format("{0} <= :{1} ", PropertyName, PlaceholderPropertyName);
            }
            else if ("GE" == Operation || ">=" == Operation)
            {
                return string.Format("{0} >= {1} ", PropertyName, PlaceholderPropertyName);
            }
            else if ("LK" == Operation || "LIKE" == Operation)
            {
                return string.Format("{0} like :{1} ", PropertyName, PlaceholderPropertyName);
            }
            else if ("LFK" == Operation || "LIKE%" == Operation)
            {
                return string.Format("{0} like :{1} ", PropertyName, PlaceholderPropertyName);
            }
            else if ("RHK" == Operation || "%LIKE" == Operation)
            {
                return string.Format("{0} like :{1} ", PropertyName, PlaceholderPropertyName);
            }
            else if ("NULL" == Operation)
            {
                return string.Format("{0} is null ", PropertyName);
            }
            else if ("NOTNULL" == Operation)
            {
                return string.Format("{0} is not null ", PropertyName);
            }
            else if ("IN" == Operation)
            {
                return string.Format("{0} in (:{1}) ", PropertyName, PlaceholderPropertyName);
            }
            else if ("BT" == Operation)
            {
                return string.Format("{0} between (:{1}) and (:{2})", PropertyName, PlaceholderPropertyName + "_0", PlaceholderPropertyName + "_1");
            }
            else
            {
                return string.Format("{0} = :{1} ", PropertyName, PlaceholderPropertyName);
            }
        }

        #endregion
    }
}

QueryFilter.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using System.Collections;

/* ***********************************************
 * 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
 * Email:tension1990@hotmail.com 
 * QQ:1881597
 * 描述 :
 * 创建时间:2011/5/15
 * 修改历史:
 * ***********************************************/
namespace Tension.NHibernate.Query
{
    /// <summary>
    /// 查询过滤器
    /// </summary>
    public class QueryFilter<T> where T : class
    {

        #region 字段属性
        /// <summary>
        /// 数据起始位置
        /// </summary>
        public int DataStart { get; set; }

        /// <summary>
        /// 每页显示的条数
        /// </summary>
        public int DataLimit { get; set; }

        ///// <summary>
        ///// 数据总数
        ///// </summary>
        //public int DataCount { get; set; }

        /// <summary>
        /// 排序字段
        /// </summary>
        public string Sort { get; set; }

        private string dir = "asc";
        /// <summary>
        /// asc desc
        /// </summary>
        public string Dir { get { return dir; } set { dir = value; } }


        /// <summary>
        /// 过滤条件集合
        /// </summary>
        private IList<Filter> filters = new List<Filter>();

        /// <summary>
        /// 过滤条件缓存
        /// </summary>
        private static Dictionary<string, string> QueryHqlCache;

        /// <summary>
        /// 当前的HQL
        /// </summary>
        public string CurrentHQL { get; set; }

        /// <summary>
        /// 计算数据条数的HQL
        /// </summary>
        public string CountHQL { get; set; }
        #endregion

        #region 构造
        /// <summary>
        /// 静态构造 
        /// </summary>
        static QueryFilter()
        {
            QueryHqlCache = new Dictionary<string, string>();
        }
        #endregion

        #region 方法
        /// <summary>
        /// 增加过滤条件 类型 Filter
        /// </summary>
        /// <param name="filter"></param>
        public void AddFilter(Filter filter)
        {
            if (filter.PropertyValue.ToString() != "NOTADD")
            {
                filter.PIndex = filters.Count + 1;
                filters.Add(filter);
            }
        }

        /// <summary>
        /// 增加过滤条件 类型 string
        /// </summary>
        /// <param name="filter"></param>
        public void AddFilter(string paramName, object obj)
        {
            AddFilter(new Filter(paramName, obj));
        }


        /// <summary>
        /// 创建查询数据条数的IQuery
        /// </summary>
        /// <param name="session"></param>
        /// <returns></returns>
        public IQuery CreateCountQuery(ISession session)
        {
            if (string.IsNullOrEmpty(CountHQL))
            {
                InitHQL();
            }
            IQuery query = session.CreateQuery(CountHQL);

            AddParameters(query);


            return query;
        }



        /// <summary>
        /// 创建IQuery对象
        /// </summary>
        /// <param name="session"></param>
        /// <returns></returns>
        public IQuery CreateQuery(ISession session)
        {
            InitHQL();

            if (!string.IsNullOrEmpty(Sort))
            {
                CurrentHQL += string.Format(" order by {0} {1}", Sort, Dir);
            }


            IQuery query = session.CreateQuery(CurrentHQL);

            if (DataLimit > 0)
            {
                query.SetMaxResults(DataLimit).
                 SetFirstResult(DataStart);
            }



            AddParameters(query);

            return query;
        }


        /// <summary>
        /// 初始化HQL 该方法同事初始化 CurrentHQL 与 CountHQL
        /// </summary>
        private void InitHQL()
        {
            CurrentHQL = BuildHql();
            CountHQL = CurrentHQL.Replace("from", "select count(*) from");
        }

        /// <summary>
        /// 向 IQuery 添加参数
        /// </summary>
        /// <param name="query"></param>
        private void AddParameters(IQuery query)
        {
            foreach (var item in filters)
            {
                if (!item.NoAdd && item.PropertyType == "ARR")
                    query.SetParameterList(item.PlaceholderPropertyName, item.PropertyValue as object[]);
                else if (!item.NoAdd)
                {
                    //query.SetParameter(item.PlaceholderPropertyName, item.PropertyValue);


                    if (item.Operation == "BT")
                    {
                        string[] valarr = item.PropertyValue.ToString().Split('_');
                        query.SetParameter(item.PlaceholderPropertyName + "_0", ValueConverter.Convert(item.PropertyType, valarr[0]));
                        query.SetParameter(item.PlaceholderPropertyName + "_1", ValueConverter.Convert(item.PropertyType, valarr[1]));
                    }
                    else
                    {
                        query.SetParameter(item.PlaceholderPropertyName, ValueConverter.Convert(item.PropertyType, item.PropertyValue));
                    }
                }
            }
        }

        /// <summary>
        /// 创建HQL
        /// </summary>
        /// <returns></returns>
        public string BuildHql()
        {
            string key = CreateQueryFilterKey();
            if (QueryHqlCache.ContainsKey(key))
            {
                return QueryHqlCache[key];
            }

            else
            {
                string hqlStr = "";
                var queryable = GetSortedFilterGroup();
                int groupCount = queryable.Count();
                StringBuilder hqlSb = new StringBuilder(string.Format("from {0} t", typeof(T).Name));

                if (groupCount != 0)
                {
                    hqlSb.Append(" where ");
                }


                //-----------------动态创建 where 语句开始--------------------




                string lastCT = "";
                var lastGroup = queryable.LastOrDefault();
                foreach (var item in queryable)
                {
                    var last = item.LastOrDefault();
                    hqlSb.Append(" (");
                    foreach (var _item in item)
                    {

                        lastCT = _item.ConnectionType;
                        hqlSb.Append(" t.");
                        hqlSb.Append(_item.CreateHqlPart());
                        if (!last.Equals(_item))
                        {
                            hqlSb.Append(" " + lastCT + " ");
                        }
                    }

                    hqlSb.Append(") ");

                    if (lastGroup.Key != item.Key)
                    {
                        hqlSb.Append(lastCT);
                    }

                }


                //-----------------动态创建 where 语句结束--------------------



                if (!QueryHqlCache.ContainsKey(key))
                {
                    hqlStr = hqlSb.ToString();
                    QueryHqlCache[key] = hqlStr;
                }
                return hqlStr;
            }



        }

        /// <summary>
        /// 创建当前查询的 key 用于缓存查询
        /// </summary>
        /// <returns></returns>
        private string CreateQueryFilterKey()
        {
            var queryable = GetSortedFilterGroup();

            StringBuilder key = new StringBuilder();

            foreach (var item in queryable)
            {
                foreach (var _item in item)
                {
                    key.Append(_item.ParamName);
                    key.Append("&");
                }
            }
            return key.ToString();
        }

        /// <summary>
        /// 获取排序并分组后的查询过滤条件
        /// </summary>
        /// <returns></returns>
        private IOrderedEnumerable<IGrouping<int, Filter>> GetSortedFilterGroup()
        {
            var queryable = filters.Select(s => s).OrderBy(d => d.Index).GroupBy(f => f.Group).OrderBy(f => f.Key);
            return queryable;
        }

        #endregion

    }
}

ValueConverter.cs

/* ***********************************************
* 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
* Email:tension1990@hotmail.com
* QQ:1881597
* 描述 :
* 创建时间:2011/5/15
* 修改历史:
* ***********************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tension.NHibernate.Query
{
    /// <summary>
    /// 值转换器
    /// </summary>
    public class ValueConverter
    {
        #region 方法
        /// <summary>
        /// 转换到对应的类型
        /// </summary>
        /// <param name="type"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static object Convert(string type, object obj)
        {
            string val = obj.ToString();
            //type : S=string D=DateTime,DEC=decimal,FT=float,I=Int32,I16=Int16,I64=Int64,ST=short,L=Long,B=bool;A=object[]
            //"S", "D", "DEC", "FT", "I", "IS", "IB", "ST", "L", "B","ARR"

            switch (type)
            {
                case "S": //string
                    return val;
                case "D": //DateTime
                    return DateTime.Parse(val);
                case "DEC"://decimal
                    return decimal.Parse(val);
                case "FT": //float
                    return float.Parse(val);
                case "I":
                    return Int32.Parse(val);
                case "IS":
                    return Int16.Parse(val);
                case "IB":
                    return Int64.Parse(val);
                case "ST":
                    return short.Parse(val);
                case "L":
                    return long.Parse(val);
                case "B":
                    if (val == "0")
                        return false;
                    if (val == "1")
                    {
                        return true;
                    }
                    return bool.Parse(val);
                case "ARR":
                    return obj as object[];
                default:
                    return type;

            }
        }
        #endregion
    }
}

WebQueryFilter.cs

/* ***********************************************
 * 作者 :tension 任何转载请务必保留此头部信息 版权所有 盗版必究
 * Email:tension1990@hotmail.com 
 * QQ:1881597
 * 描述 :
 * 创建时间:2011/5/15
 * 修改历史:
 * ***********************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Tension.NHibernate.Query
{
    /// <summary>
    /// 用于web方式的查询过滤器 实现自动注入查询条件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class WebQueryFilter<T> : QueryFilter<T> where T : class
    {


        private string sort_qs = "sort";
        private string dir_qs = "dir";
        private string start_qs = "start";
        private string limit_qs = "limit";

        #region 构造
        public WebQueryFilter()
            : base()
        {

        }

        /// <summary>
        /// 自动封装Request.Params 中符合条件的查询参数
        /// </summary>
        /// <param name="Request">HttpRequest</param>
        /// <param name="sort_qs">排序字段在 querystring 中的 名称 指 key </param>
        /// <param name="dir_qs">排序方式 querystring 中的 名称 指 key </param>
        /// <param name="start_qs">分页时数据起始位置 querystring 中的 名称 指 key </param>
        /// <param name="limit_qs">分页时每页的数据条数 querystring 中的 名称 指 key </param>
        public WebQueryFilter(HttpRequest Request, string sort_qs, string dir_qs, string start_qs, string limit_qs)
        {

        }

        /// <summary>
        /// 参数为 HttpRequest 自动封装Request.Params 中符合条件的查询参数
        /// </summary>
        /// <param name="Request"></param>
        public WebQueryFilter(HttpRequest Request)
        {
            foreach (var item in Request.Params.Keys)
            {
                if (item == null)
                {
                    continue;
                }
                string key = item.ToString();
                if (key.IndexOf("Q_") == 0)
                {

                    string[] values = Request.Params.GetValues(key);
                    if (key.Split('_')[2].ToUpper() == "ARR")
                    {
                        base.AddFilter(key, Request.Params.GetValues(key));
                    }
                    else
                    {
                        string val = Request.Params.Get(key);
                        base.AddFilter(key, val);
                    }
                }
            }

            string start = Request.Params.Get(start_qs) ?? "0";
            string limit = Request.Params.Get(limit_qs) ?? "max";

            if (limit != "max")
            {
                DataStart = int.Parse(start);
                DataLimit = int.Parse(limit);
            }

            string sort = Request.Params.Get(sort_qs);
            string dir = Request.Params.Get(dir_qs) ?? "asc";
            if (!string.IsNullOrEmpty(sort))
            {
                Sort = sort;
                Dir = dir;
            }

        }
        #endregion
    }
}

简单介绍一下各个类的功能

Filter 主要是对 一个 查询条件进行封装 ,对表达式的解析,值的转换

ValueConverter 是通过约定好的数据类型的简写进行对应的转换

QueryFilter 是将一个查询请求中 所有的 查询条件(Filter) 进行 HQL 的转换,并同时具有Nhibernate 的 IQuery 对象的创建功能,同时通过该类可以进行 多条件查询、分页、排序等操作。

WebQueryFilter 继承自 QueryFilter 主要增加了 ASP.NET 环境下 对查询结果自动封装的功能。QueryFilter 不具有此能力,适用于手动指定查询条件的情况。

通过QueryFilter,只要封装到通用的数据访问类中,大多数查询都不需要进行硬编码。

以下是我的简单的通用数据访问类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tension.NHibernate;
using Tension;
using Tension.NHibernate.Query;
using NHibernate;

namespace Service
{
    public static class Extension
    {
        public static void Query<T>(this GenericDAL<T> gd, DataPage<T> dataPage, QueryFilter<T> queryFilter) 
           where T : class
        {
            var session = Tension.NHibernate.NHibernateSessionFactory.GetSession();
            IQuery query = queryFilter.CreateQuery(session);
            IQuery count_query = queryFilter.CreateCountQuery(session);
            object o = count_query.UniqueResult();
            int count = int.Parse(o.ToString());
            dataPage.Result = query.List<T>();
            dataPage.PageIndex = (queryFilter.DataStart / (queryFilter.DataLimit == 0 
                                                                    ? 1 : queryFilter.DataLimit)) + 1;
            dataPage.PageSize = queryFilter.DataLimit;
            dataPage.DateCount = count;
            Tension.NHibernate.NHibernateSessionFactory.CloseSession();
        }
    }
}

代码有点凌乱,以上只是扩展了GenericDAL<T> 因为这部分代码已经是封装好的DLL,所以没放源代码里。

页面上条用业务层查询数据返回结果只需如下

 CustomerService Service = new CustomerService();
 DataPage<Customer> datapage = new DataPage<Customer>();
 var wqf = new WebQueryFilter<Customer>(Request);
 Service.Query<Customer>(datapage, wqf);
 Response.Write(new ExtJsGridData<Customer>() 
               { success = true, totalCount = datapage.DateCount, data = datapage.Result }.ToJson());
 
 

是不是觉得很方便?

刚刚用EXTJS 做的一个 demo

image

文章最下面有全部源码以及demo 的下载地址

点我下载Demo

汤晓华 QQ 1881597 MSN tension1990@hotmail.com

2011 05 16

posted @ 2011-05-16 22:30 tandly 阅读(1674) 评论(4) 编辑

  不久以后就要负责一个比较大的项目,有多大?反正就是挺大的。现在处于筹备阶段,我主要负责系统框架搭建,在系统缓存这一块决定采用Http运行时缓存+memcached。

  memcached 以前用过几次 不过也是小打小闹型,尚未正式大型应用过。这次也算是个难得的练手机会吧。memcached服务器打算分布在web应用服务器以及数据库服务器上。

(两台服务器有点花大手笔了 两台Dell PowerEdge R810 自定义了配置 大约单台6.5万)。

  关于Memcached的.NET 客户端的选择这一块,主要有两款候选库,Memcached.ClientLibrary(discuz .net版本企业版使用的缓存客户端) 以及 Enyim 。

这两款类库都比较好用,后者使用更加方便,只需简单的配置。我选择了Enyim。

  在测试的时候发现了一个共同的问题,假如在使用多个Memcached服务时,当其中一台服务器网络不通(其它至少存在一个可用的Memcached服务)的情况下,

Memcached.ClientLibrary 的缓存功能失效,Enyim 在缓存操作的时候实例化socket对象时没有进行连接超时的处理(Memcached.ClientLibrary处理了)。

一般都要等待10秒以上线程才能继续,线程被卡住不放了。在以往的应用中都是 memcached 与 web 共存在一台服务器上,所以没遇到过这个问题,

但是这次打算 web 服务器上开一个memcached实例,数据库服务器上开一个memcached实例,所以才关注到了这个问题。一般情况下这个问题也不会有太大影响,

但是心里总是感觉不爽。不打算使用Memcached.ClientLibrary ,所以找了 Enyim 的源代码,打算自己修改一下。

  翻看了一下源代码, Enyim 的问题主要存在于 Enyim.Caching.Memcached.PooledSocket,该类主要用于创建socket 连接 。

  以下是构造函数

internal PooledSocket(IPEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, Action<PooledSocket> cleanupCallback)

         {

              this.endpoint = endpoint;

              this.cleanupCallback = cleanupCallback;

 

              this.socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

 

              this.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, connectionTimeout == TimeSpan.MaxValue ? Timeout.Infinite : (int)connectionTimeout.TotalMilliseconds);

              this.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, receiveTimeout == TimeSpan.MaxValue ? Timeout.Infinite : (int)receiveTimeout.TotalMilliseconds);

 

              // all operations are "atomic", we do not send small chunks of data

              this.socket.NoDelay = true;

 

              this.socket.Connect(endpoint);

              this.inputStream = new BufferedStream(new BasicNetworkStream(this.socket));

     }


 

  由于Socket (我对Socket没啥研究 几乎就是文盲)对象没法设置连接超时之类的属性(这下怎么办呀),并且在源代码中可以看出 this.socket.Connect(endpoint)

的时候没有做任何处理,导致当连接有问题的服务时出现了较长时间的线程等待。我在网上找啊找,找到了类似问题的解决方案,就是使用线程池。

网上找的代码修修改改 差不多能用了,创建了 Enyim.Caching.Memcached.SocketConnector,其中有一个核心的静态方法,用来创建Socket对象,并且运行定义超时时间。

public static Socket GetConnectdSocket(IPEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, int millisecondsTimeout)

        {

            ConnectorState state = new ConnectorState();

            state.Endpoint = endpoint;

            state.ConnectionTimeout = connectionTimeout;

            state.ReceiveTimeout = receiveTimeout;

            ThreadPool.QueueUserWorkItem(new WaitCallback(SocketConnector.ConnectThreaded), state);

            if (state.Completed.WaitOne(millisecondsTimeout, false))

            {

                if (state.Socket == null)

                {

                    throw state.Exception;

                }

                return state.Socket;

            }

            state.Abort();

            throw new SocketException(0x2af9);

        }


 

然后修改PooledSocket的构造为:

internal PooledSocket(IPEndPoint endpoint, TimeSpan connectionTimeout, TimeSpan receiveTimeout, Action<PooledSocket> cleanupCallback)

        {

            this.endpoint = endpoint;

            this.cleanupCallback = cleanupCallback;

            this.socket = SocketConnector.GetConnectdSocket(endpoint, connectionTimeout, receiveTimeout, 100);

            this.inputStream = new BufferedStream(new BasicNetworkStream(this.socket));

        }


 

我将连接超时设置为100毫秒,那个恶心的问题基本算是解决了。

 

苏州    太阳狠毒

汤晓华 QQ 1881597 MSN tension1990@hotmail.com

2010 07 06

posted @ 2010-07-06 15:35 tandly 阅读(3661) 评论(32) 编辑

继 上次的随笔  一题比较刁的面试题 

大致内容------------------------------------------------------------------------------------------------------------

昨天晚上看到群里在聊面试题,回想最近几个月的面试经历,很是感慨。

10月底从昆山回到苏州。直到11月底才找到工作,跑到哪都是有没有工作经验,没有。。。好吧,回去等通知吧。

 

2009年11月19日来到苏州热线面试(苏州比较大的门户网站)

面试结束后带回去了一个题、

 

要求:

1.任何语言 任何形式(web,winform,flash,flex,silverlight)等等。。

2.实现内容

a.初始化一个面板,面板内随机分布着一些按钮  按钮上有一些随机的数字。

b.有一个按钮 名字叫“新增节点” 点击 该按钮后 可以向面板内随机添加新的 按钮。

c.任意顺序点击面板内的按钮。按顺序将所点按钮用线条连接。并且将按钮的 数值进行累加 显示到 文本框。

d.回放 功能。 有一个名叫 “回放的按钮” 点击该按钮后 将所有操作慢动作回放。

   包括增加节点 和 连接 的一切操作。完整再现。

 

这题拿回家做了3个班小时。水平不行啊。。花了很长时间在想用什么技术好。结果用了 JavaScript (jQuery)

 

在中间遇到了一些难点。

1.画线问题。一开始想到的是 vml 但是由于浏览器兼容问题。最后在网上找啊找。

使用了别人写的一个函数 用JavaScript 画线 主要思路是 利用三角函数 画出该线的每一个像素点(非常占资源)

2.记录和回放问题。如何记录下每一个操作并回放,这个问题也想了很久

记录:最后是这样的。在全局存放一个对象,该对象是一个 button 的 dom 。用来保存上一次点击的按钮对象。

当点击一个按钮时。首先将该按钮存放到一个array(存放Button对象)中,再将判断上一次是否存在点击。如果存在,则将这两个按钮连接。

当添加按钮时 首先将随机产生的按钮添加至 array 中 。

回放:当点击回放时 首先是要初始化板面中的按钮和线条等。 策略是:线条全部删除。中途添加的按钮 全部隐藏。

回放的过程实际是 一个 array 的遍历过程。

判断 array 中 Button的 状态。当Button 为显示时。调用 Button的 click 方法。否则 将Button设置为可见。

------------------------------------------------------------------------------------------------------------------------------

上回采用JavaScript实现 ,今天用sliverlight实习了该功能,发现也就如此,没啥难度。最近公司没事 开始学习sliverlight了(为了混饭吃)。

实现思路和上次基本上是一样的

主要还是一个链表,记录每一步操作的Button

其中 button的操作有两种   1.点击 2.新增加

回放时用一个定时器遍历链表 判断需要的操作 被隐藏则显示 否则执行button的click 方法 click 方法时回进行一系列的操作 如 值累加、与上一个按钮连接等操作。

 

全部代码----------------------------------------------------------------------------

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace ConnectionButton
{

    public partial class MainPage : UserControl
    {

        /// <summary>
        /// 按钮容器框的宽度
        /// </summary>
        private readonly double canvas4btnsWidth;

        /// <summary>
        /// 按钮容器框的高度
        /// </summary>
        private readonly double canvas4btnsHeight;

        /// <summary>
        /// 最大按钮值
        /// </summary>
        private readonly int maxBtnValue = 100;


        /// <summary>
        /// 最后被点击的按钮
        /// </summary>
        private XButton LastClickButton = null;

        /// <summary>
        /// 初始化时的按钮
        /// </summary>
        private IList<XButton> InitButtonsList = new List<XButton>();

        /// <summary>
        /// 增加的按钮
        /// </summary>
        private IList<XButton> AddedButtonsList = new List<XButton>();

        private List<object> MyList = new List<object>();

        bool IsPlaying = false;

        DispatcherTimer playTimer = new DispatcherTimer() { Interval = new TimeSpan(4000000) };

        int LIndex = 0;

        public MainPage()
        {
            InitializeComponent();

            canvas4btnsWidth = canvas4btns.ActualWidth;
            canvas4btnsHeight = canvas4btns.ActualHeight;

            //初始化按钮
            InitButtons();

            //定时器的Tick事件
            playTimer.Tick += (s, e) =>
            {
                if (MyList.Count == 0 || LIndex + 1 > MyList.Count)
                {
                    playTimer.Stop();
                    LIndex = 0;
                    IsPlaying = false;
                }
                else
                {
                    object item = MyList[LIndex];
                    if (item is XButton)
                    {
                        XButton btn = item as XButton;
                        if (btn.IsHide())
                        {
                            btn.Show();
                        }
                        else
                        {
                            //点击
                            ButtonClick(item);
                        }
                    }
                    LIndex++;
                }
            };
        }

        /// <summary>
        /// 产生随机数
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        private int GetRandomNumber(int min, int max)
        {
            long tick = DateTime.Now.Ticks;
            Random r = new Random(Guid.NewGuid().GetHashCode());
            if (min == -1 && max == -1)
            {
                return r.Next();
            }
            if (min == -1 && max != -1)
            {
                return r.Next(max);
            }
            return r.Next(min, max);
        }


        /// <summary>
        /// 初始化面板
        /// </summary>
        private void InitButtons()
        {
            int max = GetRandomNumber(5, 10);
            for (int i = 0; i < max; i++)
            {
                XButton btn = CreateButton();
                InitButtonsList.Add(btn);
                canvas4btns.Children.Add(btn);
            }
        }


        /// <summary>
        /// 产生随机位置的按钮
        /// </summary>
        /// <returns></returns>
        private XButton CreateButton()
        {
            double canvasLeft = GetRandomNumber(50, Convert.ToInt32(canvas4btnsWidth - 50));
            double canvasTop = GetRandomNumber(50, Convert.ToInt32(canvas4btnsHeight - 50));

            XButton btn = new XButton()
            {
                Height = 40,
                Width = 40,
                Content = GetRandomNumber(1, maxBtnValue).ToString(),
                Background = new SolidColorBrush() { Color = Colors.Blue }
            };

            btn.SetValue(Canvas.LeftProperty, canvasLeft);
            btn.SetValue(Canvas.TopProperty, canvasTop);


            btn.Click += (button, e) =>
            {
                if (!IsPlaying)
                {
                    ButtonClick(button);
                }
            };

            return btn;
        }

        /// <summary>
        /// 按钮点击
        /// </summary>
        /// <param name="button"></param>
        public void ButtonClick(object button)
        {
            XButton nowBtn = button as XButton;
            nowBtn.IsEnabled = false;
            nowBtn.Background = new SolidColorBrush() { Color = Colors.Red };

            txtCount.Text = (int.Parse(nowBtn.Content.ToString()) + int.Parse(txtCount.Text)).ToString();

            if (LastClickButton != null)
            {
                DrawLine(LastClickButton.Position(), nowBtn.Position());
            }

            //设置最后被点击的按钮
            LastClickButton = nowBtn;

            if (!LastClickButton.Clicked)
            {
                MyList.Add(LastClickButton);
                LastClickButton.Clicked = true;
            }
        }


        /// <summary>
        /// 增加节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            if (!IsPlaying)
            {
                XButton btn = CreateButton();
                AddedButtonsList.Add(btn);
                MyList.Add(btn);
                canvas4btns.Children.Add(btn);
            }

        }

        /// <summary>
        /// 画线
        /// </summary>
        /// <param name="startPoint"></param>
        /// <param name="endPoint"></param>
        private void DrawLine(Point startPoint, Point endPoint)
        {
            Line l = new Line() { X1 = startPoint.X, X2 = endPoint.X, Y1 = startPoint.Y, Y2 = endPoint.Y, StrokeThickness = 2 };
            l.Stroke = new SolidColorBrush() { Color = Color.FromArgb(255, 41, 57, 85) };
            canvas4btns.Children.Add(l);
        }



        /// <summary>
        /// 回放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRePlay_Click(object sender, RoutedEventArgs e)
        {
            if (!IsPlaying)
            {
                ///回到最初
                BackToTheBeginning();

                Paly();
            }
        }

        /// <summary>
        /// 播放
        /// </summary>
        private void Paly()
        {
            IsPlaying = true;
            playTimer.Start();
        }

        /// <summary>
        /// 回到最初
        /// </summary>
        private void BackToTheBeginning()
        {
            txtCount.Text = "0";

            LastClickButton = null;

            //将后来添加的按钮移除
            foreach (XButton btn in AddedButtonsList)
            {
                btn.Init();
                btn.Hide();
            }

            foreach (XButton btn in InitButtonsList)
            {
                btn.Init();
            }

            //移除所有连线

            var lineElements = canvas4btns.Children.Where(c => c is Line);
            foreach (Line line in lineElements)
            {
                line.Hide();
            }


            //while (canvas4btns.Children.Where(c => c is Line).Count() != 0)
            //{
            //    for (int i = 0; i < canvas4btns.Children.Count; i++)
            //    {
            //        if (canvas4btns.Children[i] is Line)
            //        {
            //            canvas4btns.Children.RemoveAt(i);
            //            break;
            //        }
            //    }
            //}


        }

    }


    /// <summary>
    /// 扩展类
    /// </summary>
    public static class Extension
    {
        /// <summary>
        /// 获取按钮的位置 仅相对于Canvas布局
        /// </summary>
        /// <param name="btn"></param>
        /// <returns></returns>
        public static Point Position(this XButton btn)
        {
            return new Point()
            {
                X = Convert.ToDouble(btn.GetValue(Canvas.LeftProperty)) + btn.ActualWidth / 2,
                Y = Convert.ToDouble(btn.GetValue(Canvas.TopProperty)) + btn.ActualHeight / 2,
            };
        }

        public static void Init(this XButton btn)
        {
            btn.BeBlue();
            btn.Visibility = Visibility.Visible;
            btn.IsEnabled = true;
        }

        public static int Value(this XButton btn)
        {
            return int.Parse(btn.Content.ToString());
        }

        public static void BeRed(this XButton btn)
        {
            btn.Background = new SolidColorBrush() { Color = Colors.Red };
        }

        public static void BeBlue(this XButton btn)
        {
            btn.Background = new SolidColorBrush() { Color = Colors.Blue };
        }

        public static bool IsHide(this XButton btn)
        {
            return btn.Visibility == Visibility.Collapsed;
        }

        public static void Show(this XButton btn)
        {
            btn.Visibility = Visibility.Visible;
        }

        public static void Hide(this XButton btn)
        {
            btn.Visibility = Visibility.Collapsed;
        }

        public static void Hide(this Line line)
        {
            line.Visibility = Visibility.Collapsed;
        }

        public static void Click(this XButton btn)
        {
            btn.Visibility = Visibility.Collapsed;
        }
    }

    public class XButton : Button
    {
        public bool Clicked { get; set; }
    }
}

效果图----------------------------------------------------------------------------------------------------------------

 

 

够简单吧。。。。

去年10月到现在时间也不短了,还把这道面试题找出来,看来我还是对那次面试耿耿于怀啊。。。此处不留爷,自有留爷处。

那家公司从家道那边要1个多小时,幸亏没去,不然就亏大了。

 

全部代码下载 /tandly/ConnectionButton.rar

苏州    很恶心的雨

汤晓华 QQ 1881597 MSN tension1990@hotmail.com

2010 04 14

posted @ 2010-04-14 19:48 tandly 阅读(1784) 评论(10) 编辑

 

 

jQuery的模式窗口插件网上有很多,但都有大大小小的问题。始终不能满足我的需求。

前几天在园子里看到  [原创]仿QQ校友DIV模拟窗口 这篇文章

今天闲来无事,把文章中插件的 html 和 css 拿了过来 自己也写了一个插件。

很久没写插件了,就当温习了。写的代码真是太丑了。。

------------------------------------------------------------------------------

先来点效果图

 

 

---------------------------------------------------------------------------------

代码

 

代码
/**
*jQuery弹出层插件
*
*汤晓华 tension
*
*2010/02/27
http://www.cnblogs.com/tandly
*
*本插件html代码以及css部分来自
http://www.cnblogs.com/fishbin/archive/2010/03/21/1690759.html
*
*
*/


(function($) {
$.fn.box
= function(o) {
o
= $.extend(
{
title:
"意见反馈",
trigger:
"",
parent:
"none",
width:
-1990,
height:
-1990,
removeBtn:
false,
buttons: [],
// buttons: [{ title: "确认", cssClass: "jBox-confirm", click: function(obj) {

// }
// }, { title: "取消", cssClass: "jBox-confirm", click: function(obj) {

// } }],
ok: function() { },
cancel: function() { },
close: function() { }
}, o
|| {});

$(
this).attr("box_content", "true");

var width
= o.width;
var height
= o.height;



//弹出框的父容器
var parent;
var thisD
= $(this);
if (o.parent == "none") {
parent
= $($("div")[0]);

if (parent == null || parent.attr("box_content") == "true") {
parent
= $("body");
}
}
else {
parent
= $(o.parent);
}


/*以下是固定的HTML代码*/

var jBoxHolder
= $('<div id="jBoxHolder"></div>');
var mask
= $('<div class="mask" style="width:0px;height:0px;display: none;"></div>');
mask.appendTo(jBoxHolder);
var jBoxWraper
= $('<div class="jBox-wraper" style="z-index: 1100; width: ' + width + 'px; visibility: hidden;"></div>');
var jBox
= $('<div id="jBoxID" class="jBox"></div>');
var jBoxHandler
= $('<div class="jBox-handler"></div>');
var jBoxHandlerTitle
= $('<h3>' + o.title + '</h3>');
var jBoxHandlerClose
= $('<input type="button" class="jBox-close" title="关闭"/>');
var jBoxContent
= $('<div class="jBox-content" style="height: ' + height + 'px; overflow: hidden"></div>');
var jBoxStatus
= $('<div class="jBox-status"></div>');

var jBoxConfirm
= $('<input type="button" class="jBox-confirm" title="确认" value="确认"/>');
var jBoxCancel
= $(' <input type="button" class="jBox-confirm" title="取消" value="取消"/>');


jBoxWraper.close
= function() {
jBoxWraper.css(
"visibility", "hidden");
mask.hide();
}

jBoxWraper.open
= function() {
jBoxWraper.css(
"visibility", "visible");
jBoxWraper.cover();
mask.show();
}

//追加标题和关闭按钮到 jBoxHandlerTitle '<div class="jBox-handler"></div>
jBoxHandlerTitle.appendTo(jBoxHandler);

jBoxHandlerClose.click(function() {
jBoxWraper.close();
o.close(
this, jBoxWraper);
});

jBoxHandlerClose.appendTo(jBoxHandler);

//头部追加到 jBox <div id="jBoxID" class="jBox"></div>
jBoxHandler.appendTo(jBox);

//当前对象 $(this) 设置为显示并追加到 jBox <div id="jBoxID" class="jBox"></div>
$(this).css("display", "block").appendTo(jBoxContent);

//内容追加到 jBox <div id="jBoxID" class="jBox"></div>
jBoxContent.appendTo(jBox);


if (!o.removeBtn) {

jBoxConfirm.click(function() {
o.ok(
this, jBoxWraper);
});


jBoxCancel.click(function() {
var flag
= o.cancel(this, jBoxWraper);
flag
= (typeof flag) == 'undefined' ? true : flag

if (flag) {
jBoxWraper.close();
}
});


//按钮追加到jBoxStatus '<div class="jBox-status"></div>
jBoxConfirm.appendTo(jBoxStatus);
jBoxCancel.appendTo(jBoxStatus);
}

for (var i = 0; i < o.buttons.length; i++) {
var btn
= o.buttons[i];
var mybtn
= $(' <input type="button" class="' + btn.cssClass + '" id="myBtn_' + i + '" title="' + btn.title + '" value="' + btn.title + '"/>');
mybtn.appendTo(jBoxStatus);
mybtn.click(function() {
var id
= $(this).attr("id").split('_')[1];
o.buttons[id].click(mybtn, jBoxWraper);
});

}

//底部状态栏目追加到 jBox <div id="jBoxID" class="jBox"></div>
jBoxStatus.appendTo(jBox);

//jBox追加到 jBoxWraper
jBox.appendTo(jBoxWraper);

jBoxWraper.appendTo(jBoxHolder);

parent.append(jBoxHolder);

var left
= $(window).width() / 2 - jBoxWraper.width() / 2;
var top
= $(window).height() / 2 - jBoxWraper.height() / 2;

jBoxWraper.css({ left: left, top: top });


jBoxWraper.cover
= function() {
var doc
= $(document);
var w
= doc.width();
var h
= doc.height();
mask.css({ width: w, height: h });
}



jBoxWraper.resize
= function() {


var doc
= $(document);
left
= $(window).width() / 2 - jBoxWraper.width() / 2;
top
= $(window).height() / 2 - jBoxWraper.height() / 2;

left
+= doc.scrollLeft();
top
+= +doc.scrollTop();

// jBoxWraper.css({ left: left, top: top });

jBoxWraper.animate({ left: left, top: top },
300)

jBoxWraper.cover();
}



$(window).resize(function() {
jBoxWraper.resize();
});


var onFooEndFunc
= function(fn) {
var delay
= 100; // 根据实际情况可调整延时时间
var executionTimer;
return function() {
if (!!executionTimer) {
clearTimeout(executionTimer);
}
//这里延时执行你的函数
executionTimer = setTimeout(function() {
fn();
}, delay);
};
};

var myfn
= function() {
$(window).resize();
}

window.onscroll
= onFooEndFunc(myfn);

$(o.trigger).click(function() {
jBoxWraper.open();
});
};
})(jQuery);




 

 

 

 DEMO

 http://files.cnblogs.com/tandly/jquery.box.rar

苏州    多云

汤晓华 QQ 1881597 MSN tension1990@hotmail.com

2010 03 27

posted @ 2010-03-27 21:17 tandly 阅读(2897) 评论(3) 编辑
摘要: 很久没写文章了,不是懒得写,是写不出。。 最近由于工作关系,重新回顾了ASP.NET MVC 的 1.0 版本。2.0版本还没有研究。由于MVC框架发展不久,还有很多不足的地方。其中关于路由规则配置这一块问题比较大。首先路由规则是在全局配置问价 Global.asax 的 Application_Start()事件中注册的。默认硬编码的方式使得以后可维护程度大大降低。MVC 1.0 似乎没有提供很...阅读全文
posted @ 2010-03-10 10:46 tandly 阅读(2431) 评论(12) 编辑
摘要: 昨天晚上看到群里在聊面试题,回想最近几个月的面试经历,很是感慨。10月底从昆山回到苏州。直到11月底才找到工作,跑到哪都是有没有工作经验,没有。。。好吧,回去等通知吧。2009年11月19日来到苏州热线面试(苏州比较大的门户网站)面试结束后带回去了一个题、要求:1.任何语言 任何形式(web,winform,flash,flex,silverlight)等等。。2.实现内容a.初始化一个面板,面板...阅读全文
posted @ 2010-01-08 21:01 tandly 阅读(2693) 评论(21) 编辑
摘要: 与其讲是分页控件 不如说是一个分页类。在网上搜集的CSS样式 一共24中经典样式供大家选择。1.digg2.yahoo3.yahoo24.meneame5.flickr6.sabrosus7.scott8.quotes9.black10.black211.black-red12.grayr13.yellow14.jogger15.starcraft216.tres17.megas51218.tec...阅读全文
posted @ 2010-01-04 20:19 tandly 阅读(2575) 评论(20) 编辑
摘要: 个人对Spring 在java平台下的运用比较熟悉。并且已经是一年前了。重拾Spring,但选择的是 Spring.Net 。Java 平台下 Spring+Hibernate 是公认的黄金组合。.NET 平台下 Spring.Net+NHibernate 也是企业架构最有前途的组合之一。早前使用Hibernate 比较烦人的就是 编写实体关系映射的 XML 描述文件。后来在Hibernate 3...阅读全文
posted @ 2009-12-31 21:37 tandly 阅读(2198) 评论(10) 编辑
摘要: 闲来无事,探讨一下正则表达式验证数据类型的效率问题。提到数据类型的验证,相信大多数朋友都会采用正则表达式。之前我也是采用的正则验证的。而现在,我个人推荐在进行 int、 double、 decimal、等数据进行验证时,最好采用 它们的TryParse方法。这里只对 int 和 double 的字符串进行了验证效率的测试。先看一下我的测试项目,其中用到了 老赵的 CodeTimerDoubleRe...阅读全文
posted @ 2009-12-19 09:37 tandly 阅读(2238) 评论(23) 编辑