转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24022165

今天给大家带来CSDN的完结篇,即增加文章的查看和文章中图片的保存~

今天的目标:

首先是对控件使用的考虑。既然是网络上的文章。可能首先想到的就是webview,这里直接把页面加载到webview中是肯定不行的,首先得把页面上的数据解析,然后可能须要一个html的模版。然后把数据填充到模版,再将模版用于webview的展示。

想了想,还是不是非常方面,由于不确定文章中的段落、图片的数量和位置。所以终于照着网络上流传的版本号使用List实现。

思路:把页面上的数据解析成 标题、摘要、段落(*)、图片(*),自定以一个对象,解析完毕后生成一个List。当然顺序一定要和原文的一直。

然后针对标题、摘要、段落、图片各做一个List的item的布局,终于显示。

好了。先简单看下csdn文章页的html:

我们在原先的代表上,加入对这样html页面的解析:

首先是封装的对象:

  1. package com.zhy.bean;
  2.  
  3. import java.util.List;
  4.  
  5. public class NewsDto
  6. {
  7. private List<News> newses;
  8. private String nextPageUrl ;
  9. public List<News> getNewses()
  10. {
  11. return newses;
  12. }
  13. public void setNewses(List<News> newses)
  14. {
  15. this.newses = newses;
  16. }
  17. public String getNextPageUrl()
  18. {
  19. return nextPageUrl;
  20. }
  21. public void setNextPageUrl(String nextPageUrl)
  22. {
  23. this.nextPageUrl = nextPageUrl;
  24. }
  25.  
  26. }
  1. package com.zhy.bean;
  2.  
  3. public class News
  4. {
  5.  
  6. public static interface NewsType
  7. {
  8. public static final int TITLE = 1;
  9. public static final int SUMMARY = 2;
  10. public static final int CONTENT = 3;
  11. public static final int IMG = 4;
  12. public static final int BOLD_TITLE = 5;
  13. }
  14.  
  15. /**
  16. * 标题
  17. */
  18. private String title;
  19. /**
  20. * 摘要
  21. */
  22. private String summary;
  23. /**
  24. * 内容
  25. */
  26. private String content;
  27.  
  28. /**
  29. * 图片链接
  30. */
  31. private String imageLink;
  32.  
  33. /**
  34. * 类型
  35. */
  36. private int type;
  37.  
  38. public String getTitle()
  39. {
  40. return title;
  41. }
  42.  
  43. public void setTitle(String title)
  44. {
  45. this.title = title;
  46. }
  47.  
  48. public String getSummary()
  49. {
  50. return summary;
  51. }
  52.  
  53. public void setSummary(String summary)
  54. {
  55. this.summary = summary;
  56. this.type = NewsType.SUMMARY;
  57. }
  58.  
  59. public String getContent()
  60. {
  61. return content;
  62. }
  63.  
  64. public void setContent(String content)
  65. {
  66. this.content = content;
  67. }
  68.  
  69. public String getImageLink()
  70. {
  71. return imageLink;
  72. }
  73.  
  74. public void setImageLink(String imageLink)
  75. {
  76. this.imageLink = imageLink;
  77. this.type = NewsType.IMG;
  78.  
  79. }
  80.  
  81. public int getType()
  82. {
  83. return type;
  84. }
  85.  
  86. public void setType(int type)
  87. {
  88. this.type = type;
  89. }
  90.  
  91. @Override
  92. public String toString()
  93. {
  94. return "News [title=" + title + ", summary=" + summary + ", content=" + content + ", imageLink=" + imageLink
  95. + ", type=" + type + "]";
  96. }
  97.  
  98. }

加入了一个新的业务方法,把html字符串转化为List对象:

  1. /**
  2. * 依据文章的url返回一个NewsDto对象
  3. *
  4. * @return
  5. * @throws CommonException
  6. */
  7. public NewsDto getNews(String urlStr) throws CommonException
  8. {
  9. NewsDto newsDto = new NewsDto();
  10. List<News> newses = new ArrayList<News>();
  11. String htmlStr = DataUtil.doGet(urlStr);
  12. Document doc = Jsoup.parse(htmlStr);
  13.  
  14. // 获得文章中的第一个detail
  15. Element detailEle = doc.select(".left .detail").get(0);
  16. // 标题
  17. Element titleEle = detailEle.select("h1.title").get(0);
  18. News news = new News();
  19. news.setTitle(titleEle.text());
  20. news.setType(NewsType.TITLE);
  21. newses.add(news);
  22. // 摘要
  23. Element summaryEle = detailEle.select("div.summary").get(0);
  24. news = new News();
  25. news.setSummary(summaryEle.text());
  26. newses.add(news);
  27. // 内容
  28. Element contentEle = detailEle.select("div.con.news_content").get(0);
  29. Elements childrenEle = contentEle.children();
  30.  
  31. for (Element child : childrenEle)
  32. {
  33. Elements imgEles = child.getElementsByTag("img");
  34. // 图片
  35. if (imgEles.size() > 0)
  36. {
  37. for (Element imgEle : imgEles)
  38. {
  39. if (imgEle.attr("src").equals(""))
  40. continue;
  41. news = new News();
  42. news.setImageLink(imgEle.attr("src"));
  43. newses.add(news);
  44. }
  45. }
  46. // 移除图片
  47. imgEles.remove();
  48.  
  49. if (child.text().equals(""))
  50. continue;
  51.  
  52. news = new News();
  53. news.setType(NewsType.CONTENT);
  54.  
  55. try
  56. {
  57. if(child.children().size()==1)
  58. {
  59. Element cc = child.child(0);
  60. if(cc.tagName().equals("b"))
  61. {
  62. news.setType(NewsType.BOLD_TITLE);
  63. }
  64. }
  65.  
  66. } catch (IndexOutOfBoundsException e)
  67. {
  68. e.printStackTrace();
  69. }
  70. news.setContent(child.outerHtml());
  71. newses.add(news);
  72. }
  73. newsDto.setNewses(newses);
  74. return newsDto;
  75. }

測试代码:

  1. @org.junit.Test
  2. public void test02()
  3. {
  4. NewsItemBiz biz = new NewsItemBiz();
  5. try
  6. {
  7. NewsDto newsDto = biz.getNews("http://www.csdn.net/article/2014-04-17/2819363-all-about-ddos");
  8.  
  9. List<News> newses = newsDto.getNewses();
  10. for(News news : newses)
  11. {
  12. System.out.println(news);
  13.  
  14. }
  15.  
  16. System.out.println("-----");
  17. System.out.println(newsDto.getNextPageUrl());;
  18. } catch (CommonException e)
  19. {
  20. // TODO Auto-generated catch block
  21. e.printStackTrace();
  22. }
  23. }

然后我们能够拿到这种结果数据:

好了,如今准备把解析完毕的数据用到我们的app上。

上一教程已经完毕了Xlist的显示。上拉与下拉。如今给它加入OnItemClickListener:

  1. mXListView.setOnItemClickListener(new OnItemClickListener()
  2. {
  3. @Override
  4. public void onItemClick(AdapterView<?
  5.  
  6. > parent, View view, int position, long id)
  7. {
  8. NewsItem newsItem = mDatas.get(position-1);
  9. Intent intent = new Intent(getActivity(), NewsContentActivity.class);
  10. intent.putExtra("url", newsItem.getLink());
  11. startActivity(intent);
  12. }
  13.  
  14. });

到达显示内容的Activity页面:

  1. package com.zhy.csdndemo;
  2.  
  3. import java.util.List;
  4.  
  5. import me.maxwin.view.IXListViewLoadMore;
  6. import me.maxwin.view.XListView;
  7. import android.app.Activity;
  8. import android.content.Intent;
  9. import android.os.AsyncTask;
  10. import android.os.Bundle;
  11. import android.os.Looper;
  12. import android.view.View;
  13. import android.widget.AdapterView;
  14. import android.widget.Toast;
  15. import android.widget.AdapterView.OnItemClickListener;
  16. import android.widget.ProgressBar;
  17.  
  18. import com.zhy.bean.CommonException;
  19. import com.zhy.bean.News;
  20. import com.zhy.biz.NewsItemBiz;
  21. import com.zhy.csdndemo.adapter.NewContentAdapter;
  22.  
  23. public class NewsContentActivity extends Activity implements IXListViewLoadMore
  24. {
  25.  
  26. private XListView mListView;
  27.  
  28. /**
  29. * 该页面的url
  30. */
  31. private String url;
  32. private NewsItemBiz mNewsItemBiz;
  33. private List<News> mDatas;
  34.  
  35. private ProgressBar mProgressBar;
  36. private NewContentAdapter mAdapter;
  37.  
  38. @Override
  39. protected void onCreate(Bundle savedInstanceState)
  40. {
  41. super.onCreate(savedInstanceState);
  42. setContentView(R.layout.news_content);
  43.  
  44. mNewsItemBiz = new NewsItemBiz();
  45.  
  46. Bundle extras = getIntent().getExtras();
  47. url = extras.getString("url");
  48.  
  49. mAdapter = new NewContentAdapter(this);
  50.  
  51. mListView = (XListView) findViewById(R.id.id_listview);
  52. mProgressBar = (ProgressBar) findViewById(R.id.id_newsContentPro);
  53.  
  54. mListView.setAdapter(mAdapter);
  55. mListView.disablePullRefreash();
  56. mListView.setPullLoadEnable(this);
  57.  
  58. mListView.setOnItemClickListener(new OnItemClickListener()
  59. {
  60. @Override
  61. public void onItemClick(AdapterView<?> parent, View view, int position, long id)
  62. {
  63.  
  64. News news = mDatas.get(position - 1);
  65. String imageLink = news.getImageLink();
  66. //Toast.makeText(NewContentActivity.this, imageLink, 1).show();
  67. Intent intent = new Intent(NewsContentActivity.this,ImageShowActivity.class);
  68. intent.putExtra("url", imageLink);
  69. startActivity(intent);
  70. }
  71. });
  72.  
  73. mProgressBar.setVisibility(View.VISIBLE);
  74. new LoadDataTask().execute();
  75.  
  76. }
  77.  
  78. @Override
  79. public void onLoadMore()
  80. {
  81.  
  82. }
  83.  
  84. class LoadDataTask extends AsyncTask<Void, Void, Void>
  85. {
  86.  
  87. @Override
  88. protected Void doInBackground(Void... params)
  89. {
  90. try
  91. {
  92. mDatas = mNewsItemBiz.getNews(url).getNewses();
  93. } catch (CommonException e)
  94. {
  95. Looper.prepare();
  96. Toast.makeText(getApplicationContext(), e.getMessage(), 1).show();
  97. Looper.loop();
  98. }
  99.  
  100. return null;
  101. }
  102.  
  103. @Override
  104. protected void onPostExecute(Void result)
  105. {
  106. if(mDatas == null)
  107. return ;
  108. mAdapter.addList(mDatas);
  109. mAdapter.notifyDataSetChanged();
  110. mProgressBar.setVisibility(View.GONE);
  111. }
  112.  
  113. }
  114.  
  115. /**
  116. * 点击返回button
  117. * @param view
  118. */
  119. public void back(View view)
  120. {
  121. finish();
  122. }
  123.  
  124. }

接下来看这个Activity中ListView的Adapter

  1. package com.zhy.csdndemo.adapter;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import android.content.Context;
  7. import android.graphics.Bitmap;
  8. import android.text.Html;
  9. import android.util.Log;
  10. import android.view.LayoutInflater;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.widget.BaseAdapter;
  14. import android.widget.ImageView;
  15. import android.widget.TextView;
  16.  
  17. import com.nostra13.universalimageloader.core.DisplayImageOptions;
  18. import com.nostra13.universalimageloader.core.ImageLoader;
  19. import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
  20. import com.nostra13.universalimageloader.core.assist.ImageScaleType;
  21. import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
  22. import com.zhy.bean.News;
  23. import com.zhy.bean.News.NewsType;
  24. import com.zhy.csdndemo.R;
  25.  
  26. public class NewContentAdapter extends BaseAdapter
  27. {
  28. private LayoutInflater mInflater;
  29. private List<News> mDatas = new ArrayList<News>();
  30.  
  31. private ImageLoader imageLoader = ImageLoader.getInstance();
  32. private DisplayImageOptions options;
  33.  
  34. public NewContentAdapter(Context context)
  35. {
  36. mInflater = LayoutInflater.from(context);
  37.  
  38. imageLoader.init(ImageLoaderConfiguration.createDefault(context));
  39. options = new DisplayImageOptions.Builder().showStubImage(R.drawable.images)
  40. .showImageForEmptyUri(R.drawable.images).showImageOnFail(R.drawable.images).cacheInMemory()
  41. .cacheOnDisc().imageScaleType(ImageScaleType.EXACTLY).bitmapConfig(Bitmap.Config.RGB_565)
  42. .displayer(new FadeInBitmapDisplayer(300)).build();
  43. }
  44.  
  45. public void addList(List<News> datas)
  46. {
  47. mDatas.addAll(datas);
  48. }
  49.  
  50. @Override
  51. public int getCount()
  52. {
  53. return mDatas.size();
  54. }
  55.  
  56. @Override
  57. public Object getItem(int position)
  58. {
  59. return mDatas.get(position);
  60. }
  61.  
  62. @Override
  63. public long getItemId(int position)
  64. {
  65. return position;
  66. }
  67.  
  68. @Override
  69. public int getItemViewType(int position)
  70. {
  71. switch (mDatas.get(position).getType())
  72. {
  73. case NewsType.TITLE:
  74. return 0;
  75. case NewsType.SUMMARY:
  76. return 1;
  77. case NewsType.CONTENT:
  78. return 2;
  79. case NewsType.IMG:
  80. return 3;
  81. case NewsType.BOLD_TITLE:
  82. return 4;
  83. }
  84. return -1;
  85. }
  86.  
  87. @Override
  88. public int getViewTypeCount()
  89. {
  90. return 5;
  91. }
  92.  
  93. @Override
  94. public boolean isEnabled(int position)
  95. {
  96. switch (mDatas.get(position).getType())
  97. {
  98. case NewsType.IMG:
  99. return true;
  100. default:
  101. return false;
  102. }
  103. }
  104.  
  105. @Override
  106. public View getView(int position, View convertView, ViewGroup parent)
  107. {
  108. News news = mDatas.get(position); // 获取当前项数据
  109.  
  110. Log.e("xxx", news.toString());
  111.  
  112. ViewHolder holder = null;
  113. if (null == convertView)
  114. {
  115. holder = new ViewHolder();
  116. switch (news.getType())
  117. {
  118. case NewsType.TITLE:
  119. convertView = mInflater.inflate(R.layout.news_content_title_item, null);
  120. holder.mTextView = (TextView) convertView.findViewById(R.id.text);
  121. break;
  122. case NewsType.SUMMARY:
  123. convertView = mInflater.inflate(R.layout.news_content_summary_item, null);
  124. holder.mTextView = (TextView) convertView.findViewById(R.id.text);
  125. break;
  126. case NewsType.CONTENT:
  127. convertView = mInflater.inflate(R.layout.news_content_item, null);
  128. holder.mTextView = (TextView) convertView.findViewById(R.id.text);
  129. break;
  130. case NewsType.IMG:
  131. convertView = mInflater.inflate(R.layout.news_content_img_item, null);
  132. holder.mImageView = (ImageView) convertView.findViewById(R.id.imageView);
  133. break;
  134. case NewsType.BOLD_TITLE:
  135. convertView = mInflater.inflate(R.layout.news_content_bold_title_item, null);
  136. holder.mTextView = (TextView) convertView.findViewById(R.id.text);
  137. break;
  138. }
  139. convertView.setTag(holder);
  140. } else
  141. {
  142. holder = (ViewHolder) convertView.getTag();
  143. }
  144.  
  145. if (null != news)
  146. {
  147. switch (news.getType())
  148. {
  149. case NewsType.IMG:
  150. imageLoader.displayImage(news.getImageLink(), holder.mImageView, options);
  151. break;
  152. case NewsType.TITLE:
  153. holder.mTextView.setText(news.getTitle());
  154. break;
  155. case NewsType.SUMMARY:
  156. holder.mTextView.setText(news.getSummary());
  157. break;
  158. case NewsType.CONTENT:
  159. holder.mTextView.setText("\u3000\u3000"+Html.fromHtml(news.getContent()));
  160. break;
  161. case NewsType.BOLD_TITLE:
  162. holder.mTextView.setText("\u3000\u3000"+Html.fromHtml(news.getContent()));
  163. default:
  164.  
  165. // holder.mTextView.setText(Html.fromHtml(item.getContent(),
  166. // null, new MyTagHandler()));
  167. // holder.content.setText(Html.fromHtml("<ul><bold>加粗</bold>sdfsdf<ul>",
  168. // null, new MyTagHandler()));
  169. break;
  170. }
  171. }
  172. return convertView;
  173. }
  174.  
  175. private final class ViewHolder
  176. {
  177. TextView mTextView;
  178. ImageView mImageView;
  179. }
  180. }

我们复写了getViewTypeCount , getItemViewType 。isEnabled 由于我们的item的样式不止一种。且为显示图片的那个Item让它能够点击。

最后就是图片展示的Activity:

  1. package com.zhy.csdndemo;
  2.  
  3. import android.app.Activity;
  4. import android.graphics.Bitmap;
  5. import android.os.AsyncTask;
  6. import android.os.Bundle;
  7. import android.view.View;
  8. import android.widget.ProgressBar;
  9. import android.widget.Toast;
  10.  
  11. import com.polites.android.GestureImageView;
  12. import com.zhy.csdndemo.util.FileUtil;
  13. import com.zhy.csdndemo.util.Http;
  14.  
  15. public class ImageShowActivity extends Activity
  16. {
  17.  
  18. private String url;
  19. private ProgressBar mLoading;
  20. private GestureImageView mGestureImageView;
  21. private Bitmap mBitmap;
  22.  
  23. @Override
  24. protected void onCreate(Bundle savedInstanceState)
  25. {
  26. super.onCreate(savedInstanceState);
  27. setContentView(R.layout.activity_image_page);
  28.  
  29. // 拿到图片的链接
  30. url = getIntent().getExtras().getString("url");
  31. mLoading = (ProgressBar) findViewById(R.id.loading);
  32. mGestureImageView = (GestureImageView) findViewById(R.id.image);
  33.  
  34. new DownloadImgTask().execute();
  35.  
  36. }
  37.  
  38. /**
  39. * 点击返回button
  40. *
  41. * @param view
  42. */
  43. public void back(View view)
  44. {
  45. finish();
  46. }
  47.  
  48. /**
  49. * 点击下载button
  50. *
  51. * @param view
  52. */
  53. public void downloadImg(View view)
  54. {
  55. mGestureImageView.setDrawingCacheEnabled(true);
  56. if (FileUtil.writeSDcard(url, mGestureImageView.getDrawingCache()))
  57. {
  58. Toast.makeText(getApplicationContext(), "保存成功", Toast.LENGTH_SHORT).show();
  59. } else
  60. {
  61. Toast.makeText(getApplicationContext(), "保存失败", Toast.LENGTH_SHORT).show();
  62. }
  63. mGestureImageView.setDrawingCacheEnabled(false);
  64. }
  65.  
  66. class DownloadImgTask extends AsyncTask<Void, Void, Void>
  67. {
  68. @Override
  69. protected Void doInBackground(Void... params)
  70. {
  71. mBitmap = Http.HttpGetBmp(url);
  72. return null;
  73. }
  74.  
  75. @Override
  76. protected void onPostExecute(Void result)
  77. {
  78. mGestureImageView.setImageBitmap(mBitmap);
  79. mLoading.setVisibility(View.GONE);
  80. super.onPostExecute(result);
  81. }
  82.  
  83. }
  84. }

好了,省略了一些辅助类的方法和布局文件。

以下看下效果。

好了,上传文件限制2M。没办法录太多。

源代码点击此处下载

实现app上对csdn的文章查看,以及文章中图片的保存 (制作csdn app 完结篇)的更多相关文章

  1. [iOS基础控件 - 5.2] 查看大图、缩放图片代码(UIScrollView制作)

    原图: 900 x 1305      拖曳滚动:   缩放:           主要代码: // // ViewController.m // ImageZoom // // Created by ...

  2. 实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23698511 今天继续对我们的csdn客户端未完成的功能进行实现,本篇博客接着客 ...

  3. 客户端上显示csdn上的各类别下的的文章列表 (制作csdn app 三)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23597229 今天将在Android 使用Fragment,ViewPagerI ...

  4. 抓取csdn上的各类别的文章 (制作csdn app 二)

    转载请表明出处:http://blog.csdn.net/lmj623565791/article/details/23532797 这篇博客接着上一篇(Android 使用Fragment,View ...

  5. 巨高兴,偶的文章 “如何在服务器上配置ODBC来访问本机DB2for Windows服务器”被推荐至CSDN博客首页

    非常高兴,偶的文章 "如何在服务器上配置ODBC来访问本机DB2for Windows服务器"被推荐至CSDN博客首页,截图留念.                  文章被推荐在C ...

  6. “杀死” App 上的疑难崩溃

    在移动应用性能方面,崩溃带来的影响是最为严重的,程序崩了可以打断用户正在进行的操作体验,造成关键业务中断.用户留存率下降.品牌口碑变差.生命周期价值下降等影响.很多公司将崩溃率作为优先级最高的技术指标 ...

  7. 关于app上页面和js的调试

    不久前折腾了一晚上关于app上的页面和js的调试: 首先得准备几个比较比较常用的工具: 1.chrome(这个都没有你还干啥fe呀) 2.Fiddler(抓包神器,基本也是必备咯) 3.sublime ...

  8. Python+爬虫+xlwings发现CSDN个人博客热门文章

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 最近几天老猿博客的访问量出现了比较大的增长,从常规的1000-3000之间波动的范围一下子翻了将近一倍,粉丝增长从日均10-40人也增长了差不多一倍 ...

  9. APP上传

    原文网址: http://blog.csdn.net/ayangcool 前言:作为一名IOS开发者,把开发出来的App上传到App Store是必须的.下面就来详细介绍下具体流程. 1.打开苹果开发 ...

随机推荐

  1. 四大主流云平台对比--CloudStack, Eucalyptus, vCloud Director和OpenStack。

    我迟早可能都要进入的领域,提前温习... 还有KVM,ESXI,API,XEN之间的术语和关系,也要心中有数.. ~~~~~~~~~~~~~~~~~~~ 云计算在如今的IT界一直是一个最热门的话题,鉴 ...

  2. php smarty 配置四个存放目录

    require("Smarty.class.php"); $smarty = new Smarty(); $smarty -> template_dir = "./ ...

  3. 【无聊放个模板系列】HDU 1269 (SCC)

    #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #inc ...

  4. 汇编中,BP,SP有何区别?分别怎么使用?

    bp寄存器,跟其它什么BX,AX一样的用法, SP是用在栈上的,配合SS使用,像SS:SP SS上放段地址,SP上放偏移地址. 寻址时,像[bp],相当于SS:[bp] 就是说它默认使用SS 像BX默 ...

  5. USB (Universal Serial Bus)

    USB歷史簡介 USB規格演變 標準 USB 2.0 介面 實體層 訊號傳輸 傳輸速率 網路層 USB 通訊模型 Endpoints 傳輸型態 USB 資料連結 Transaction Frame P ...

  6. Android 各个版本WebView

    转载请注明出处   http://blog.csdn.net/typename/ powered by miechal zhao : miechalzhao@gmail.com 前言: 根据Googl ...

  7. LinearLayout按下(pressed)或获取焦点(focused)时背景设置不同颜色或图片

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id=&qu ...

  8. NoClassDefFoundError: javassist/util/proxy/MethodFilter

    Caused by: java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter    at org.hibernate.byt ...

  9. 使用OLEDB读取不同版本Excel数据的连接字符串设置

    摘要: 用OLEDB通过设置连接字符串可以像读取sqlserver一样将excel中的数据读取出来,但是excel2003和excel2007/2010的连接字符串是不同的/// summary // ...

  10. sql server 修改表的默认值, 需要先删除约束条件

    ---------增加是否发布订单 if not exists(select 1 from syscolumns where name='iIsRelease' and id=OBJECT_ID('M ...