Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
天刷到了一個這樣的短視頻,我尋思我是不是也可以寫一個類似的上課點名程序,想法經不起等待,說寫就寫~
私信小編01即可獲取大量Python學習資源
Tkinter 是 python 內置的 TK GUI 工具集。TK 是 Tcl 語言的原生 GUI 庫。作為 python 的圖形設計工具,它所使用的 Tcl 語言環境已經完全嵌入到了 python 解釋器中。
我們使用Tkinter開發GUI界面。
PIL(Python Image Library)庫是Python語言的第三方庫,需要通過pip工具安裝。安裝PIL庫的方法如下,需要注意,安裝庫的名字是pillow。
PIL庫支持圖像儲存、顯示和處理,他能夠處理幾乎所有圖片格式,可以完成對圖像的縮放、剪裁、疊加以及向圖像添加線條、圖像和文字等操作。
使用PIL中的Image,ImageTk處理、引入一張圖片,可以使用下面代碼安裝一下。
pip install pillow
雙擊打開后,進入軟件主界面,所有功能一目了然。程序會自動識別軟件目錄下的names.txt,將里面的名字導入。
選擇順序點名后,點擊開始,屏幕上就開始滾動出現人名,人名出現的概率是相同的,點擊停止,人名就停止滾動,點名結束。
點擊隨機點名,程序就會進行隨機點名,人名出現的概率是隨機的。
可以自己手動選擇人名單,前提是人名單格式為txt,且每個名字占一行。
用Pyqt5也寫了一個版本,實現邏輯與TK版本相同,界面可能更好看了一些,但是文件大了許多,大家可以在后面總結部分自取。
import random
import re
import time
import threading
from tkinter import *
from tkinter import ttk
from base64 import b64decode
from PIL import Image,ImageTk
from tkinter import messagebox
from tkinter.filedialog import askopenfilename
""""
2021-11-10點名/抽獎程序
主要亮點:
1.兩種模式:
①順序點名
②隨機點名
2.自動識別人名單
3.支持手動導入人名單
4.人名單導入校驗
5.人名顯示位置自動矯正
6.最多顯示五個大字
"""
imgs=['./point_name.png']
class APP:
def __init__(self):
self.root = Tk()
self.running_flag=False #開始標志
self.time_span=0.05 #名字顯示間隔
self.root.title('Point_name-V1.0')
width = 680
height = 350
left = (self.root.winfo_screenwidth() - width) / 2
top = (self.root.winfo_screenheight() - height) / 2
self.root.geometry("%dx%d+%d+%d" % (width, height, left, top))
self.root.resizable(0,0)
self.create_widget()
self.set_widget()
self.place_widget()
self.root.mainloop()
def create_widget(self):
self.label_show_name_var=StringVar()
self.label_show_name=ttk.Label(self.root,textvariable=self.label_show_name_var,font=('Arial', 100,"bold"),foreground = '#1E90FF')
self.btn_start=ttk.Button(self.root,text="開始",)
self.btn_load_names=ttk.Button(self.root,text="手動加載人名單",)
self.lf1=ttk.LabelFrame(self.root,text="點名方式")
self.radioBtn_var=IntVar()
self.radioBtn_var.set(1)
self.radioBtn_sequence=ttk.Radiobutton(self.lf1,text="順序點名",variable=self.radioBtn_var, value=1)
self.radioBtn_random=ttk.Radiobutton(self.lf1,text="隨機點名",variable=self.radioBtn_var, value=2)
self.label_show_name_num=ttk.Label(self.root,font=('Arial', 20),foreground = '#FF7F50')
paned = PanedWindow(self.root)
self.img = imgs
img_=b'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'
the_img = b64decode(img_)#將圖片硬編碼到GUI
paned.image = ImageTk.PhotoImage(data=the_img)
self._img = Label(self.root, image=paned.image,background='black')
def set_widget(self):
default_name_="會是誰?"
self.label_show_name_var.set(default_name_)
self.label_show_name_adjust(default_name_)
self.btn_start.config(command=lambda :self.thread_it(self.start_point_name))
self.btn_load_names.config(command=self.load_names)
init_names=self.load_names_txt("./names.txt")
self.root.protocol('WM_DELETE_WINDOW',self.quit_window)
self.root.bind('<Escape>',self.quit_window)
if init_names:
self.default_names=init_names #1.文件存在但是無內容。2.文件不存在
self.label_show_name_num.config(text=f"一共加載了{len(self.default_names)}個姓名")
else:
self.btn_start.config(state=DISABLED)
self.label_show_name_num.config(text=f"請先手動導入人名單!")
def place_widget(self):
self.lf1.place(x=300,y=160,width=250,height=50)
self.radioBtn_sequence.place(x=20,y=0)
self.radioBtn_random.place(x=150,y=0)
self.btn_start.place(x=300,y=220,width=100,height=30)
self.btn_load_names.place(x=450,y=220,width=100,height=30)
self._img.place(x=90, y=165, height=120, width=180)
self.label_show_name_num.place(x=300,y=260)
def label_show_name_adjust(self,the_name):
if len (the_name)==1:
self.label_show_name.place(x=280, y=10)
elif len(the_name) == 2:
self.label_show_name.place(x=180, y=10)
elif len(the_name) == 3:
self.label_show_name.place(x=120, y=10)
elif len(the_name) == 4:
self.label_show_name.place(x=80, y=10)
else:
self.label_show_name.place(x=0, y=10)
def start_point_name(self):
"""
啟動之前進行判斷,獲取點名模式
:return:
"""
if len(self.default_names)==1:
messagebox.showinfo("提示",'人名單就一個人,不用選了!')
self.label_show_name_var.set(self.default_names[0])
self.label_show_name_adjust(self.default_names[0])
return
if self.btn_start["text"]=="開始":
self.btn_load_names.config(state=DISABLED)
self.running_flag=True
if isinstance(self.default_names,list):
self.btn_start.config(text="就你了")
if self.radioBtn_var.get()==1:
mode="sequence"
elif self.radioBtn_var.get()==2:
mode="random"
else:
pass
self.thread_it(self.point_name_begin(mode))
else:
messagebox.showwarning("警告","請先導入人名單!")
else:
self.running_flag=False
self.btn_load_names.config(state=NORMAL)
self.btn_start.config(text="開始")
def point_name_begin(self,mode):
"""
開始點名,點名主函數
:param mode:
:return:
"""
if mode == "sequence":
if self.running_flag:
self.always_ergodic()
elif mode=="random":
while True:
if self.running_flag:
random_choice_name=random.choice(self.default_names)
self.label_show_name_var.set(random_choice_name)
self.label_show_name_adjust(random_choice_name)
time.sleep(self.time_span)
else:
break
def always_ergodic(self):
"""
一直遍歷此列表,使用死循環會造成線程阻塞
:return:
"""
for i in self.default_names:
if self.running_flag:
self.label_show_name_var.set(i)
self.label_show_name_adjust(i)
time.sleep(self.time_span)
if i==self.default_names[-1]:
self.always_ergodic()
else:
break
def load_names(self):
"""
手動加載txt格式人名單
:return:
"""
filename = askopenfilename(
filetypes = [('文本文件', '.TXT'), ],
title = "選擇一個文本文件",
initialdir="./"
)
if filename:
names=self.load_names_txt(filename)
if names:
self.default_names=names
no_Chinese_name_num=len([n for n in names if not self.load_name_check(n)])
if no_Chinese_name_num==0:
pass
else:
messagebox.showwarning("請注意",f'導入名單有{no_Chinese_name_num}個不是中文名字')
self.label_show_name_num.config(text=f"一共加載了{len(self.default_names)}個姓名")
default_name_ = "會是誰?"
self.label_show_name_var.set(default_name_)
self.label_show_name_adjust(default_name_)
self.btn_start.config(state=NORMAL)
else:
messagebox.showwarning("警告","導入失敗,請檢查!")
def load_names_txt(self,txt_file):
"""
讀取txt格式的人名單
:param txt_file:
:return:
"""
try:
with open(txt_file,'r',encoding="utf-8")as f:
names=[name.strip() for name in f.readlines()]
if len(names)==0:
return False
else:
return names
except:
return False
def load_name_check(self,name):
"""
對txt文本中的人名進行校驗
中文漢字->True
非中文漢字->False
:param name:
:return:
"""
regex = r'[\u4e00-\u9fa5]+'
if re.match(regex,name):
return True
else:
return False
def thread_it(self,func,*args):
t=threading.Thread(target=func,args=args)
t.setDaemon(True)
t.start()
def quit_window(self,*args):
"""
程序退出觸發此函數
:param args:
:return:
"""
ret=messagebox.askyesno('退出','確定要退出?')
if ret:
self.root.destroy()
if __name__ == '__main__':
a=APP()
本次使用Tkinter開發了一款上課點名程序,此程序可以用于點名、抽獎…代碼不到200行,程序簡單又實用,主要有以下六個亮點:
1.兩種模式:
2.自動識別人名單
3.支持手動導入人名單
4.人名單導入校驗
5.人名顯示位置自動矯正
6.最多顯示五個大字
據庫測試,似乎是被人遺忘的數據庫職業,但依然是不錯的選擇。底下是我在某站找的招聘啟事,就連螞蟻金服都在積極尋找數據庫測試人:
要說我經歷的項目,大大小小也有幾十個,從 C/S, B/S, 再到 B/C/S, M/S. 無論怎么變化,總也離不開 UI/DB 這種框架。
以前 C/S,B/S,自己動手寫寫沒問題,就拿很早的 C/S 架構來說,C 代表了客戶端,S 代表了服務器。客戶端可以使用 vb, vfp, delphi, c#, java 來寫,邏輯都放在數據庫服務器上,具體來說,就是封裝在存儲過程里。
而 B/S 時代,客戶端換成了 Browser,也就是瀏覽器,而 S 端還是數據庫服務器。那么 B/S 時代,語言從強編譯性語言,逐步向弱編譯傾斜。Javascript 和 JQuery 就在這個時候應運而生。
如果說 C/S,B/S 時代還有全棧程序員,現在如此復雜的時代,要做到真正全棧,就特別不容易。僅從測試來說,需要的功底一下子就變得豐富至極。
鑒于前端變化太快,我很明智地選擇了 S 端,即數據庫服務器。數據庫的測試,相對前端來說,穩定得多。
一些不同的聲音
大部分反對給數據庫做測試的理由,來自兩大類:
一是沒有時間。在開發和調優上花費的時間夠多了,為什么還要去寫大量的測試用例。
二是測試案例復雜。針對業務復雜的測試,對數據質量要求很高,一個沒有設置好地區,折扣,渠道的訂單,測試出來的結果肯定不令人滿意,那么做好一份質量高的測試數據,本身就需要花費很長時間和精力,對于團隊資源是種低收成的回報。
有個搞笑的段子,大家聽聽:
我們從來不做數據庫測試,要做就在生產環境做
可,認真看過這張圖的朋友,大概是笑不出來的。
在各個階段做測試,出現Bug后,修復所花的代價是天壤之別。
但做好測試,可以收獲下面這些益處,至于要不要做,完全取決于當前你的團隊:
早發現,早治療在數據庫開發領域,手工測試和一次性腳本測試,是最常用的。
但不利于找出是否有破壞性的功能缺陷因為新加的特性而引入。有了自動化的測試工具,任何時候針對任何數據庫版本,都可隨時完成測試。
往往尋找一個bug的產生,需要耗費8-16小時,甚至更多,僅僅是因為某個開發嵌入了一個新模塊的代碼,針對數據庫開發來說,沒有特別好的debug工具,只能靠人肉眼去逐行掃描代碼,最終才能定位到某個可疑的地方。
減少重構風險網上有個玩笑,中年(35歲)程序員如何才能保住自己的飯碗?將SQL寫的越長越好,越少人看得懂越好。碰到這樣的祖傳代碼,很多新人都是要問候原作者的直系親屬的。我上次說5000行代碼的維護,就已經有讀者受不了了。
那么怎么規避這種毫無設計感的代碼呢?還是測試。假如一開始,一個用戶需求就是一套測試用例,那么放心的去重構吧,愛怎么重構就怎么構,完了跑下測試就行。但如果沒有測試,你敢動這大幾千行的代碼么,即使你拍著胸脯說,你敢,你老板敢么?
保障團隊協作如果說程序員比較宅,不喜歡旅游,可以天天上線解決代碼問題,那么誰還能不生個病呢。如果生病的時候,你負責的代碼出問題了,誰來解決呢?全組都要等一個人才能繼續往下工作,這種風險也太大了。
如果有了測試策略,一個人斷了線,另一個人接上,接著往下碼。只要大家都是同一個平臺,接手完全沒有問題。這對數據庫開發就更有利了。無論是sql server, oracle,mysql, 只要測試用例都在,我們的目標就是編寫出通過測試用例的代碼,至于T-SQL, PL/SQL的轉換,文檔查查,一點問題沒有。
那么數據庫怎么做測試呢,特別是看到上千行的存儲過程,一大堆的 ETL 程序?作為開發,完成功能的實現就萬事大吉,但作為測試,既沒有實現功能的大快人心,還必須提心吊膽為最后的質量把關,弄不好,老板認為測試不具備生產力,還要壓低你的薪水,徹底悲劇了你。
既然測試這么難,那么我們怎么保障自己測試的質量呢?下面說說我的一些個人看法。
就跟看書一樣,如果拿起一本書從頭看到尾(曾經我也是這樣么像教科書一樣看計算機的圖書),那么我敢打賭,一本800頁的數據結構,99.99%的人,看到300頁的時候,絕對放棄了,頂多再往后多翻 5 頁,即305頁。然后不停的翻翻后面,數數還有多少 頁沒看,還需要花多少時間,不用問為什么我知道,你懂得。
那么我從什么時候開始不這么看書了呢?從看完《CLR Via C#》開始.本書777頁,我花了近 5 個多月,每個禮拜天就躲在家里看,看不下去了,就喝杯星巴克,繼續看,邊看邊畫。最終一頁不落,全部看完。有些地方還看了不止5遍。還有本手冊,《Oracle Concepts》,大概看了不少于 6 遍,邊看邊畫,每個晚上8點準時看,一直到看不動為止。
那么為什么看完這兩本之后,再也不相信從頭到尾的看書方式了呢?因為好的書,配上好的結構,你看任何 一章,都是可以不需要前面章節的知識,依舊可以讀的很愉快。如果讀不懂,通過想象力和搜索引擎,反而能解決當下最重要的問題。
因此,讀書最重要的是明白自己想要什么。測試也一樣,必須根據測試內容,而制定測試計劃。如果要測試并發壓力,就不能用單元測試;要測試新功能,就不能執行回歸測試。
那么,數據庫測試主要有哪些分類呢?
有的同學會覺得數據庫測試很簡單,先 R(retrieve) 一下,在CUD(Create Update Delete) 一波,最后在 R 以下,如果滿足結果就算測試通過。
畫個圖介紹下,不就是這樣么:
其實,正確的測試應該做到這樣:
將測試封裝在一個存儲過程里。
單元測試:單元測試的目的,就是取最小單元的程序,比如一個存儲過程,用測試數據來測試它是否完成了我們需要完成的功能。
那我們就來好好研究,數據庫性能測試的評測方法。也就是怎么去設計一套評測數據庫性能的軟件。我的數據庫性能好不好,必須由我說了算。
這套軟件的特點必須是:
1)分布式:模擬從不同設備訪問數據庫,以達到真實的用戶訪問。
2)實時監控:如果性能弱的時候沒有及時抓住,那么很可能呢下次帶來更大麻煩的時候,我們依然手足無措。所以在測試階段就必須一擊即中。
說實話,這篇論文對于我來說,很有收獲。
設計數據庫測試軟件,不是一朝一夕的事情,它是一個體系,值得作為職業。
錄
第一章 諸論
第一節 開發工具的選用及介紹
第二節 ASP技術訪問WEB數據庫
第二章 系統分析與總體設計
第一節 系統功能描述
第二節 系統功能模塊劃分
第三節 系統流程分析
第三章 數據庫結構設計與實現
第一節 創建數據庫
第二節 數據庫邏輯結構設計
第三節 創建表的腳本文件
第四章 目錄結構與通用模塊
第一節 目錄結構
第二節 通用模塊
第五章 系統主界面與登錄程序設計
第一節 設計主界面
第二節 登錄程序設計
第三節 設計管理界面
第六章 新聞類別管理模塊設計
第一節 設計新聞類別管理界面
第二節 添加新聞類別
第三節 修改新聞類別
第四節 刪除新聞類別
第七章 新聞發布管理模塊設計
第一節 添加新聞
第二節 修改新聞
第三節 刪除新聞
第四節 新聞查詢管理
第八章 調試與安裝
第一節 安裝IIS
第二節 ASP硬件要求
結束語
參 考 文 獻
后 記
摘要
【摘要】我們從建站的實際情況出發,經過對有關網站新聞發布事項的一番考察和分析,確立了新聞發布系統的具體實現功能。并闡述系統的結構設計和功能設計,實現新聞的分類顯示,最近新聞的提示,新聞滾動功能等。經過授權的用戶可以通過Web瀏覽器,以人機交互式的客戶端程序實現對學校新聞的發布、管理、實時的進行行為統計和記錄。本系統是學校網站的一個子系統,具有很好的外部接口,能夠很好的配合站點的其它子系統服務于網站的新聞發布.該系統是一個基于新聞發布和內容管理的全站管理系統;基于B/S模式WEBMIS系統,本系統可以將雜亂無章的信息(包括文字、圖片和影音)經過組織,合理而且有序地呈現在大家面前。簡單的說,新聞發布系統就是充當一個網絡新聞媒介的功能。
主要實現對新聞的分類,審核,發布,模擬了一般新聞媒介的發布的過程
【Abstract】 we embark from the station construction actual situation,pass through to a related website news issue item inspection and theanalysis, has established the news issue system concrete realizationfunction. And the elaboration system structural design and thefunctional design, realize the news classification to demonstratethat, the recent news prompt, the news rolls the function and so on.After the authorized user may through the Web browser, by theman-machine interactive customer end procedure realization to theschool news issue, the management, real-time carry on the behaviorstatistics and the record. This system is a school website sub-system, has the very good exterior connection, can the very goodcoordinate stand other subsystems serve the website news issue This system is based on the news issue and the content managemententire station management system management system; Based on B/S thepattern WEBMIS system, this system may the chaotic information(including writing, picture and video and music) the processorganization, reasonably has the foreword to present in front ofeverybody. Simple saying, the news issued the system is acts as a NetNews medium the function, the main realization to the newsclassification, the verification, the issue, has simulated the commonnews medium news issue process
前言
在Internet飛速發展的今天,互聯網成為人們快速獲取、發布和傳遞信息的重要渠道,它在人們政治、經濟、生活等各個方面發揮著重要的作用。Internet上發布信息主要是通過網站來實現的,獲取信息也是要在Internet“海洋”中按照一定的檢索方式將所需要的信息從網站上下載下來。因此網站建設在Internet應用上的地位顯而易見,它已成為政府、企事業單位信息化建設中的重要組成部分,從而倍受人們的重視。
由于時間有限,加之信息系統開發經驗的缺少和編程能力的有限,所以本系統難免存在各種各樣的缺點。敬請指導老師能夠提出批評和寶貴意見,也希望各位讀者提出寶貴意見并進行指正,謝謝!
1. ASP的優勢:Active Server Pages:“動態服務器網頁”,一般簡稱為“ASP”,ASP之所以能受到大家的重視與使用的原因,主要在于所產生的執行結果都是標準的HTML格式,而且這些程序是在網絡服務端中執行,使用一般的瀏覽器(如IE 或Netscape)都可以正確地獲得ASP的“執行”結果,并且將這ASP執行的結果直接在瀏覽器中“瀏覽”,不像VBScript或 JavaScript是在客戶端(Client)的瀏覽器上執行,若使用VBScript來設計程序,客戶端(Client)在IE瀏覽器中可以顯示程序執行的結果,可是,客戶端(Client)若使用Netscape瀏覽器就無法顯示VBScript的執行結果。
2.ASP的特點:任何開發工具皆可發展ASP。只要使用一般的文書編輯程序,如Windows記事本,就可以編輯。當然,其他網頁發展工具,例如,FrontPage Express、 FrontPage等也都可以;不過還是建議你用記事本來寫,既省錢又方便,若是使用那些所見即所得的網頁編輯來寫ASP,可能會發生一些意想不到的離奇狀態。
3.通吃各家瀏覽由于ASP程序是在網絡服務器端中執行,執行結果所產生的HTML文件適用于不同的瀏覽器。
4.語言相容性高:ASP與所有的ActiveX Script語言都相容,除了可結合HTML,VBScript、Java Script、Active X服務器組件來設計外,并可經由“plug-In(外掛組件模組)的方式,使用其他廠商(Third Party)所提供的語言。
隱密安全性高。如果我們在瀏覽器中直接查看網頁的原始代碼,就只能看到HTML文件,原始的ASP程序代碼是看不到的!這是因杰ASP程序先于網站服務(Web Server)端執行后,將結果轉換成標準HTML文件,再傳送到客戶端(Client)的瀏覽器上,因此,我們所辛苦撰寫的ASP程序并不會輕易地被看見進而被盜用。
5.易于操控數據庫:ASP可以輕易地通過ODBC(Open Database Connectivity)驅動程序連接各種不同的數據庫,例如:Acess、Foxpro、dBase、Oracle等等,另外,ASP亦可將“文本文件”或是”Excel” 文件當成數據庫用。
6.面向對象學習容易:ASP具備有面向對象(Object-Oriented)功能,學習容易,ASP提供了五種方便能力強大的內建對象:Request、Response、Sever、Application以及Session,同時,若使用ASP內建的“Application”對象或”Session”對象所撰寫出來的ASP程序可以在多個網頁之間暫時保存必要的信息。
ASP的六大內部對象Request、Response、Server、Session、Application、ObjectContext 從客戶端取得信息將信息送給客戶端提供一些Web服務器工具儲存在一個Session內的用戶信息,該信息僅可被該用戶訪問在一個ASP-Application中讓不同的客戶端共享信息可以用來配合Microsoft Transaction 服務器進行分布式事務處理。
所以我選擇了ASP結合Frontpage架構網站。在此期間本人將使用Macromedia Dreamweaver MX 2004進行ASP頁面的編碼,并使用IIS6.0對頁面進行調試。
一.訪問WEB數據庫的多種方案
目前在WINDOWS環境下有多種訪問WEB數據庫的技術,主要有:
(1).公共網關接口CGI(Common Gateway Interface)
CGI是較早實現的技術。適用于多種服務器平臺,如UNIX、WINDOWS等,但CGI的開發成本高、維護困難、功能有限、不具備事務處理功能、占用服務器資源較多。
(2). INTERNET數據庫連接器IDC(Internet Database Connector)。
IDC集成在ISAPI(Internet Server API)中,充分利用了DLL技術,易擴充,但編程較CGI更為復雜,只適用于小型數據庫系統。
(3). 先進數據庫連接器ADC(Advance Database Connector)
ADC提供了ActiveX Control來訪問數據庫,它的主要特點是數據查詢由用戶端瀏覽器執行,因而需將服務器端數據庫中的部分記錄下載到用戶端,系統開銷較大、響應慢,只適用于特別頻繁的數據庫查詢操作。
(4). JAVA/JDBC語言編程
JAVA語言是一種面向對象、易移植、多線程控制的語言,可通過JDBC去連接數據庫。用JAVA/JDBC編寫的軟件可移植性強,適用于多種操作系統,但其執行效率和執行速度還不理想,目前無法建立高效、高速的應用。
(5). 動態服務器頁面ASP(Active Server Page)
ASP是微軟公司最新推出的WEB應用開發技術,著重于處理動態網頁和WEB數據庫的開發,編程靈活、簡潔,具有較高的性能,是目前訪問WEB數據庫的最佳選擇。
二.ASP簡介
1.ASP訪問數據庫的原理
ASP是服務器端的腳本執行環境,可用來產生和執行動態的高性能的WEB服務器程序。
當用戶使用瀏覽器請求ASP主頁時,WEB服務器響應,調用ASP引擎來執行ASP文件,并解釋其中的腳本語言(JScript 或VBScript),通過ODBC連接數據庫,由數據庫訪問組件ADO(ActiveX Data Objects)完成數據庫操作,最后ASP生成包含有數據查詢結果的HTML主頁返回用戶端顯示。
由于ASP在服務器端運行,運行結果以HTML主頁形式返回用戶瀏覽器,因而ASP源程序不會泄密,增加了系統的安全保密性。此外,ASP是面向對象的腳本環境,用戶可自行增加ActiveX組件來擴充其功能,拓展應用范圍。
2.ASP頁面的結構:
ASP的程序代碼簡單、通用,文件名由.asp結尾,ASP文件通常由四部分構成:
(1) 標準的HTML標記:所有的HTML標記均可使用。
(2) ASP語法命令:位于<% %> 標簽內的ASP代碼。
(3) 服務器端的include語句:可用#include語句調入其它ASP代碼,增強了編程的靈活性。
(4) 腳本語言:ASP自帶JScript和VBScript兩種腳本語言,增加了ASP的編程功能,用戶也可安裝其它腳本語言,如Perl、Rexx等。
3.ASP的運行環境
目前ASP可運行在三種環境下。
(1) WINDOWS NT server 4.0運行IIS 3.0(Internet Information Server)以上。
(2) WINDOWS NT workstation 4.0運行Peer Web Server 3.0以上。
(3) WINDOWS 95/98運行PWS(Personal Web Server)。
其中以NT server上的IIS功能最強,提供了對ASP的全面支持,是創建高速、穩定的ASP主頁的最佳選擇。
4.ASP的內建對象
ASP提供了六個內建對象,供用戶直接調用:
(1) Application對象:負責管理所有會話信息,可用來在指定的應用程序的所有用戶之間共享信息。
(2) Session對象:存貯特定用戶的會話信息,只被該用戶訪問,當用戶在不同WEB頁面跳轉時,Session中的變量在用戶整個會話過程中一直保存。Session對象需cookie支持。
(3) Request對象:從用戶端取得信息傳遞給服務器,是ASP讀取用戶輸入的主要方法。
(4) Response對象:服務器將輸出內容發送到用戶端。
(5) Server對象:提供對服務器有關方法和屬性的訪問。
(6) Object Context對象:IIS 4.0新增的對象,用來進行事務處理。此項功能需得到MTS(Microsoft Transcation Server)管理的支持。
5. ASP的主要內置組件:
(1) Ad Rotator組件:用來按指定計劃在同一頁上自動輪換顯示廣告,用于WWW上日益重要的廣告服務。
(2) Browser Capabilities組件:確定訪問WEB站點的用戶瀏覽器的功能數據,包括類型、性能、版本等。
(3) Database Access組件:提供ADO (ActiveX Data Objects)來訪問支持ODBC的數據庫。
(4) File Access組件:提供對服務器端文件的讀寫功能。
(5) Content Linking組件:生成WEB頁內容列表,并將各頁順序連接,用于制作導航條。
此外,還可安裝Myinfo、Counters、Content Rotator、Page Count等組件,用戶也可自行編制Actiive組件,以提高系統的實用性。
6. Database Access組件ADO
WWW上很重要的應用是訪問WEB數據庫,用ASP訪問WEB數據庫時,必須使用ADO組件,ADO是ASP內置的ActiveX服務器組件(ActiveX Server Component),通過在WEB服務器上設置ODBC和OLEDB可連接多種數據庫:如SYBASE、ORACLE、INFORMIX、SQL SERVER、ACCESS、VFP等,是對目前微軟所支持的數據庫進行操作的最有效和最簡單直接的方法。
ADO組件主要提供了以下七個對象和四個集合來訪問數據庫。
(1) Connection對象:建立與后臺數據庫的連接。
(2) Command對象:執行SQL指令,訪問數據庫。
(3) Parameters對象和Parameters集合:為Command對象提供數據和參數。
(4) RecordSet對象:存放訪問數據庫后的數據信息,是最經常使用的對象。
(5) Field對象和Field集合:提供對RecordSet中當前記錄的各個字段進行訪問的功能。
(6) Property對象和Properties集合:提供有關信息,供Connection、Command、RecordSet、Field對象使用。
(7) Error對象和Errors集合:提供訪問數據庫時的錯誤信息。
很多網站都提供新聞欄目,例如搜狐、新浪等著名網站的新聞專欄。許多企業和個人網站也需要定期發布一些關于企業或網站的新聞。因為網絡中新聞發布的頻率非常高,如果使用靜態網頁作為新聞頁面,則維護工作將非常繁瑣,管理員每天需要制作大量的網頁,從而浪費很多時間和精力。使用新聞發布及管理系統可以使新聞發布和管理變得很輕松,管理員只需設置標題、內容和圖片等新聞就可以了,系統將自動生成對應的網頁。本文將對新聞發布及管理系統進行系統分析與總體設計。
新聞發布及管理系統包括新聞類別管理、新聞發布管理、圖片處理、新聞查詢、網友評論和用戶管理等模塊。具體描述如下:
1.新聞類別管理:
(1)新聞類別的錄入,包括類別編號和類別名稱等信息;
(2)新聞類別的修改;
(3)新聞類別的刪除;
(4)新聞類別的查詢。
2.新聞發布管理:
(1)基本新聞信息的錄入,包括新聞標題、新聞內容和所屬類別等;
(2)基本新聞信息的修改;
(3)基本新聞信息的刪除;
3.圖片處理模塊:
(1)選擇圖片文件;
(2)上傳圖片文件;
(3)存儲圖片新聞;
(4)修改新聞圖片;
(5)刪除新聞圖片;
(6)在網頁中瀏覽新聞圖片。
4.新聞查詢模塊:
(1)按照新聞類別分頁顯示新聞; -
(2)按照日期分頁顯示新聞。
5.網友留言模塊:
(1)網友對某條新聞發表評論;
(2)管理員可以刪除新聞評論。
6.系統用戶管理功能:
(1)系統用戶信息的錄入,包括用戶名和密碼等信息;
(2)系統用戶信息的修改;
(3)系統用戶信息的刪除。
從功能描述的內容可以看到,本實例可以實現6個完整的功能。我們根據這些功能,設計出系統的功能模塊,如圖1所示。
圖1 新聞發布及管理系統功能模塊示意圖
新聞發布及管理系統的功能模塊之間的關系如圖2所示。
圖2 新聞發布及管理系統的功能模塊關系圖
在本系統中,用戶管理模塊的功能比較簡單。在系統初始化時,有一個默認的“系統管理員”用戶Admin,由程序設計人員手動地添加到數據庫中。Admin用戶可以創建用戶、修改和刪除用戶;普通用戶則只能修改自己的用戶名和密碼。
用戶管理功能模塊的關系如圖3所示。
圖3 用戶管理功能模塊的關系圖
為了使讀者進一步了解本實例系統的設計,本小節將對系統進行流程分析。多用戶系統的工作流程都是從用戶登錄模塊開始,對用戶的身份進行認證。身份認證可以分為以下兩個過程:
(1)確認用戶是否是有效的系統用戶。
(2)確定用戶的類型。
第1個過程決定用戶能否進入系統。第2個過程根據用戶的類型決定用戶的操作權限,從而決定用戶的工作界面。
本系統分為前臺系統和后臺系統兩個部分。前臺系統不需要進行身份認證,任何人都可以通過瀏覽器閱讀已經發布的新聞、發表網友評論。
后臺系統的流程分析如圖4所示。Admin用戶擁有所有的權限,普通用戶只能對自己發布的新聞進行管理,包括修改新聞內容、刪除新聞和刪除網友評論。
圖4 后臺系統的流程分析
這一章將介紹系統的數據庫表結構和創建表的腳本。
首先創建一個數據庫news,用來保存本系統的所有數據。創建數據庫的腳本代碼如下:
CREATE DATABASE news
GO
可以在SQL查詢分析器中執行該語句,創建數據庫。
本系統定義的數據庫中包含以下4個表:新聞類別表:Category、新聞基本信息表:News、網友評論信息表:Discuss和用戶信息表:users。
下面分別介紹這些表的結構。
1.新聞類別表Category
新聞類別表Category用來保存新聞類別數據,結構如表1所示。
表1 表Category的結構
編號 | 字段名稱 | 數據結構 | 說明 |
1 | CateId | int | 新聞類別編號 |
2 | CateName | varchar (50) | 新聞類別名稱 |
在設計數據庫結構時,很多表都需要設計一個整型字段作為標識列,這幾乎已經成為慣例,例如表Category中的CateId字段。所謂標識列,就是可以惟一標識一行記錄的列,在表中不會存在兩條標識列相同的記錄。如果其他表需要引用表Category中的數據,則在表中添加一個CateId字段就可以了。有的程序設計人員習慣于直接使用名稱字段作為標識列,例如表Category中的CateName字段。這樣,如果修改CateName字段的值,就需要同時修改其他所有表的相應字段的值,從而造成不必要的麻煩。在系統中,CateId字段對于用戶來說是透明的,用戶感覺不到它的存在,也無法對其進行修改。
2.基本新聞表News
基本新聞表News用來保存網上新聞的基本信息,結構如表2所示。
表2表News的結構
編號 | 字段名稱 | 數據結構 | 說明 |
1 | Id | int | 新聞編號 |
2 | Title | varchar(100) | 新聞標題 |
3 | Content | text | 新聞內容 |
4 | PostTime | datetime | 提交時間 |
5 | Poster | varchar(50) | 提交人 |
6 | CateId | int | 新聞類別編號 |
7 | Attpic | bit | 是否有圖片標記(0沒有;1有) |
8 | Readcount | int | 閱讀次數 |
在SQL Server 2000中,可以使用char、varchar和text等3種數據類型存儲非Unicode字符數據。char和varchar只能存儲最多8000個字符,其中char用于存儲固定長度的字符數據,varchar用于存儲可變長度的字符數據。如果需要存儲的數據很大,則可以使用text數據類型,例如表News中的Content字符,因為新聞內容的數據量通常會超過8000個字符。text數據類型也是可變長度的,最多可為2147483647個字符。
3.網友評論信息表Discuss
網友評論信息表Discuss用來保存網友對新聞的評論信息,結構如表3所示。
表3 表Discuss的結構
編號 | 字段名稱 | 數據結構 | 說明 |
1 | id | int | 評論編號 |
2 | UserId | varchar(20) | 評論人名稱 |
3 | Posttime | sinaildatetime | 提交時間 |
4 | Content | varchar(4000) | 評論內容 |
5 | Newsld | int | 新聞編號 |
在SQL Server 2000中,可以使用datetime和smalldatetime兩種數據類型存儲日期時間數據。datetime數據類型用于存儲從1753年1月1日到9999年12月31日的日期和時間數據,精確到3.33ms;smalldatetime數據類型用于存儲從1900年1月1日到2079年6月6日的日期和時間數據,精確到分鐘。有些程序員習慣于使用datetime數據類型存儲日期時間數據,其實在精確度要求不高的情況下,使用smalldatetime數據類型是足夠了。
4..用戶信息表Users
用戶信息表Users用來保存用戶的基本信息,結構如表8.4所示。
編號 | 字段名稱 | 數據結構 | 說明 |
1 | UserId | int | 用戶ID號 。 |
2 | UserName | varchar(50) | 用戶名 |
3 | UserPwd | varcahr(50) | 密碼 |
4 | Ename | varchar(50) | 用戶姓名 |
5 | varchar(50) | 電子郵箱 |
本節將介紹創建表的腳本文件,可以在“查詢分析器”中執行這些腳本,在數據庫news中創建表。
1.創建表Category
創建表category的腳本文件為Category.sql,它的代碼如下:
USE news
GO
CREATE TABLE Category
(
CateId Int IDENTITY PRIMARY KEY,
CateName Varchar(50) NOT NULL
)
GO
在使用CREATE TABLE指令創建表時,應該注意使用PRIMARY KEY關鍵字定義表的主鍵。表中每一行的主鍵都有惟一值,可以使用主鍵惟一地標識一行數據。
2.創建表News
創建表News的腳本文件為News.sql,它的代碼如下:
USE news
GO
CREATE TABLE News
(
Id Int IDENTITY PRIMARY KEY,
Title Varchar(100) NOT NULL,
Content Text,
PostTime Datetime,
Poster Varchar(50),
CateId Int,
Attpic Int DEFAULT 0,
ReadCount Int DEFAULT 0
)
GO
在使用CREATE TABLE指令創建表時,應該注意使用NOT NULL關鍵字定義表的未空字段。使用NOT NULL定義的字段將不允許為空,這樣就可以避免表中出現無效的數據,影響系統運行。例如,表News中的Title字段將不能為空,否則在新聞列表中將出現一個空行。
在使用CREATE TABLE指令創建表時,使用DEFAULT關鍵字可以字義字段的默認值,例如表News中,Attpic和ReadCount字段的默認值為0。
3.創建表Discuss
創建表Discuss的腳本文件為Discuss.sql,它的代碼如下:
USE news
GO
CREATE TABLE Discuss
(
Id Int IDENTITY PRIMARY KEY,
UserId Varchar(20),
Posttime Smalldatetime,
Content Varchar(4000),
NewsId Int
)
GO
在使用CREATE TABLE指令創建表時,通常可以使用IDENTITY關鍵字與PRIMARY KEY關鍵字相結合,創建標識字段。每次增加新記錄時,標識字段自動遞增。程序員在編寫程序的過程申,無需考慮標識字段的值。
4.創建表Users
創建表Users的腳本文件為Users.sql,它的代碼如下:
USE news
GO
CREATE TABLE Users
( UserId Int Primary Key IDENTITY,
UserName Varchar(50) NOT NULL,
UserPwd Varchar(50) NOT NULL,
Ename Varchar(50),
Email Varchar(50)
)
GO
INSERT INTO Users (UserName, UserPwd, Ename, Email) VALUES('Admin', '111111', '', '')
GO
在創建表users的同時,將默認的用戶Admin插入到表中,默認的密碼為“llllll”。
在執行這些腳本之前,請確定數據庫news已經存在,否則會產生錯誤。如果要創建的表已經存在,則需要先將表刪除。
在運行實例時,需要將web目錄復制到IIS/PWS的根目錄下,例如
目錄下包含下面兩個子目錄:
images用于存儲上傳的新聞圖片;
pic用于存儲網頁中的圖片文件;
其他ASP和HTM文件都保存在web目錄下。
本實例中包含一些通用模塊,這些模塊以文件的形式保存,可以在其他文件中使用#include語句包含這些模塊,使用其中定義的功能。
1.ConnDB.asp
ConnDB.asp的功能是實現到數據庫的連接,因為在很多網頁中都有連接數據庫的操作,所以把它保存在文件ConnDB.asp中,這樣可以避免重復編程。ConnDB.asp的代碼如下:
<%
dim Conn
dim ConnStr
set Conn=server.createobject("adodb.connection")ConnStr="driver={SQL Server};server=(local);UID=sa;PWD=yourpassword;Database=news"
Conn.Open ConnStr
%>
在文件中引用此文件作為頭文件就可以訪問數據庫,代碼如下:
<!--#include File="ConnDB.asp"-->
2.IsAdmin.asp
因為本實例中有些功能只有Admin用戶才有權限使用,所以在進入這些網頁之前,需要判斷用戶是否是Admin。IsAdmin.asp的功能是判斷當前用戶是否是Admin,如果不是,則中斷執行;如果是,則不執行任何操作,直接進入包含它的網頁。
IsAdmin.asp的代碼如下:
<%
If Session("UserName") <> "Admin" Then
Response.Write("不是Admin用戶,沒有此權限")
Response.End
End If
%>
在文件中引用此文件作為頭文件,代碼如下:
<!--#include File="IsAdmin.asp"-->
3.IsAuthor.asp
在修改和刪除新聞時,除了Admin用戶擁有所有權限外,其他用戶只能修改自己創建的新聞。所以在修改和刪除新聞時,需要判斷當前用戶是否是Admin或指定新聞的作者。
IsAuthor.asp可以實現此功能,代碼如下:
<%
If Session("UserName") <> "Admin" Then
NewsId = Request("Id")
'根據新聞編號讀取新聞信息
set rsNews = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM News WHERE Id=" & Trim(NewsId)
set rsNews=Conn.Execute(sql)
Set Rs=conn.Execute(sql)
If rsNews.EOF Then
Response.Write "指定新聞不存在"
Response.End
Else
'判斷用戶權限,是否可以維護新聞,管理員可以編輯所有新聞,編輯者只能修改自己的新聞
If rsNews("Poster") <> Session("UserName") Then
Response.Write "不是Admin或新聞的作者,無權修改!"
Response.End
End If
End If
End If
%>
如果當前用戶是Admin,則IsAuthor.asp不做任何操作;否則,程序將根據參數Id讀取新聞信息,并將Poster字段的值與當前用戶名進行比較。在兩種情況下,IsAuthor.asp將阻止程序繼續執行:
(1)指定新聞不存在;
(2)當前用戶不是指定新聞的作者。
使用Response.End可以結束網頁的輸出。
在文件中引用此文件作為頭文件,代碼如下:
<!--#include File=" IsAuthor.asp"-->
4.template.asp
在添加和修改新聞內容時,需要對字體、字號、顏色和排列位置等屬性進行設置。Template.asp可以實現這些功能。
Template.asp的設計界面如圖5所示。
圖5 Template.asp的設計界面
在使用template.asp時,設置指定的選項,將會在新聞內容中生成相應的HTML代碼。例如,選中正文abc,然后選擇“楷體”、“1號字”,將生成如下代碼:
<font[space]face=楷體_GB2312><font[space]size=1>abc</font></font>
[space]是自定義的符號,因為空格在轉換成HTML格式時,將被替換為“ ;”,所以這里使用[space]表示空格。在顯示新聞內容時,程序將會自動將[space]轉換為空格。
因為template.asp的代碼較多,這里僅以字體控制的代碼為例說明。相關代碼如下:
字體 <SELECT onChange="var c=this.options[this.selectedIndex].value; if(selection.createRange().text!='')
{selection.createRange().text='<font[space]face='+c+'>'+selection.createRange().text+'</font>'}else
{myform.txtcontent.value = '<font[space]face='+c+'>'+myform.txtcontent.value+'</font>'}" name=font style='FONT-SIZE: 9pt'>
<OPTION selected value=宋體>宋體</OPTION>
<OPTION value=楷體_GB2312>楷體</OPTION>
<OPTION value=新宋體>新宋體</OPTION>
<OPTION value=黑體>黑體</OPTION>
<OPTION value=隸書>隸書</OPTION>
<OPTION value="Andale Mono">Andale Mono</OPTION>
<OPTION value=Arial>Arial</OPTION>
<OPTION value="Arial Black">Arial Black</OPTION>
<OPTION value="Book Antiqua">Book Antiqua</OPTION>
<OPTION value="Century Gothic">Century Gothic</OPTION>
<OPTION value="Comic Sans MS">Comic Sans MS</OPTION>
<OPTION value="Courier New">Courier New</OPTION>
<OPTION value=Georgia>Georgia</OPTION>
<OPTION value=Impact>Impact</OPTION>
<OPTION value=Tahoma>Tahoma</OPTION>
<OPTION value="Times New Roman">Times New Roman</OPTION>
<OPTION value="Trebuchet MS">Trebuchet MS</OPTION>
<OPTION value="Script MT Bold">Script MT Bold</OPTION>
<OPTION value=Stencil>Stencil</OPTION>
<OPTION value=Verdana>Verdana</OPTION>
<OPTION value="Lucida Console">Lucida Console</OPTION></SELECT>
在下拉菜單中,定義了系統支持的字體名稱,下拉菜單的值與字體名稱相同。
當下拉菜單的選擇發生變化時,將觸發onChange事件,程序中直接定義了對應的JavaScript代碼。This表示字體下拉菜單,this.selectedlndex表示當前選擇的菜單項目索引,This.options[this.selectedlndex].value則表示選擇下拉菜單的值,程序將其保存變量C中。
Selection.createRangeO.text表示當前選擇字符的內容,如果它不為空,則將其替換為如下代碼:
selection.createRange().text='<font[space]face='+c+'>'+selection.createRange().text+'</font>'
也就是在它的兩側添加字體標識<font>和</font>。
如果沒有選擇字符,則在輸入新聞內容的文本域中直接加入字體標識,用戶可以在<font>和</font>之問添加相應的文字,代碼如下:
myform.txtcontent.value='<font[space]face='+c+'>'+myform.txtcontent.value+'</font>
在添加和修改新聞內容的網頁中,必須將表單定義為myform,輸入新聞內容的滾動文本框定義為txtcontent,否則此功能將無法實現。
本主界面為default.asp,它的功能是顯示新聞類別和每個類別中的10條新聞,并提供進入管理界面(index.asp)的鏈接。
錄入新聞類別和新聞內容后,default.asp的界面如圖5-6所示。
圖5-6 default.asp的界面
下面介紹default.asp的主要代碼。
1.顯示新聞類別鏈接
default.asp將新聞按照分類顯示,每個新聞類別只顯示最新的10條新聞。如果新聞類別
較多,則網頁會被拉長,給用戶閱讀帶來不便。為了解決這個問題,本實例使用書簽來定義新
聞類別的位置,書簽格式為#a<類別編號>。例如,類別編號為1的新聞類別的書簽名稱為#al。下面的代碼將在網頁中生成所有新聞類別的鏈接,每個鏈接都指相應新聞類別的書簽。這樣,用戶就可以通過單擊鏈接直達新聞類別了。
<%
'=====顯示所有新聞類別供點擊,點擊不同類別顯示該類別的新聞=====
'按順序讀取所有新聞類別,保存在記錄集rsCate中
sql = "SELECT * FROM Category ORDER BY CateId"
Set rsCate = conn.Execute(sql)
'顯示所有新聞類別鏈接
Do While Not rsCate.EOF
stitle = rsCate("CateName")
cid = rsCate("CateId")
'每個新聞類別標題被定義為一個書簽,名為 #a類別編號
%>
<a href="#a<%=cid%>"><font style='TEXT-DECORATION: none;color:black'><%=stitle%></font></a> |
<%
rsCate.MoveNext
Loop
%>
如果網頁中顯示的內容較多,通常需要通過定義書簽的方法使用戶快速到達指定的位置。書簽是網頁中被標記的位置或被標記的選中文本。在FrontPage中選擇“插入”/“書簽”菜單項,可以在指定位置插入書簽。在本例中,因為書簽位置是動態變化的,所以需要使用代碼定義,方法如下:
<a name=書簽名></a>
2.“新聞管理”鏈接
系統管理員Admin或其他用戶可以通過“新聞管理”鏈接進入新聞管理頁面index.asp
<a href="index.asp"><font color=red style='TEXT-DECORATION: none'>新聞管理</font></a>
3.顯示各新聞類別中的最新新聞
default.asp的主要內容是顯示新聞類別中的最新10條新聞,并將3天內的新聞使用new圖片標記。當然,如果新聞的內容經常更新,則可以將3天改為1天。
這部分代碼如下:
<%
'=====顯示所有新聞類別供點擊,點擊不同類別顯示該類別的新聞=====
'按順序讀取所有新聞類別,保存在記錄集rsCate中
sql = "SELECT * FROM Category ORDER BY CateId"
Set rsCate = conn.Execute(sql)
'顯示所有新聞類別鏈接
Do While Not rsCate.EOF
stitle = rsCate("CateName")
cid = rsCate("CateId")
'每個新聞類別標題被定義為一個書簽,名為 #a類別編號
%>
<a href="#a<%=cid%>"><font style='TEXT-DECORATION: none;color:black'><%=stitle%></font></a> |
<%
rsCate.MoveNext
Loop
%>
<a href='search.asp'><font color=red>新聞查詢</font></a>
| <a href="index.asp"><font color=red style='TEXT-DECORATION: none'>新聞管理</font></a>
</div>
<table align="center" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td width="*" valign="TOP">
<%
'將指針移至開始位置,分別顯示每個分類中的新聞
If rsCate.BOF = False Then
rsCate.MoveFirst
End If
'依次顯示每個新聞類別中最新的10條新聞
DO WHILE Not rsCate.EOF
stitle = rsCate("CateName")
cid = rsCate("CateId")
'變量cnt用來記錄
cnt = 0
'生成表格
Response.Write "<table width='100%' cellspacing=1 cellpadding=2><tr>"
'顯示新聞類別,并設置書簽
Response.Write "<td bgcolor=#ceceff><a name=""a"&cid&"""></a> == "
'顯示新聞類別標題
Response.Write stitle + " ==</td></tr>"
'生成另一個表格,用于顯示新聞標題
Response.Write"<table width='100%' border=0 cellspacing=0 cellpadding=0>"
'按提交時間的降序顯示新聞標題
sql = "SELECT * FROM News WHERE CateId=" & cid & " ORDER BY Posttime DESC"
rs.Open sql, conn, 1, 1
DO WHILE Not rs.EOF
'計數
cnt = cnt + 1
'只顯示10條新聞
If cnt < 11 Then
Dim ndate
ndate = DateAdd("d",-3,date())
'顯示新聞標題及鏈接,查看新聞的腳本文件為NewsView.asp
Response.Write "<tr><td width='50%'><a onClick='return newwin(this.href);' href='NewsView.asp?id=" + cstr(rs("id")) + "'>" + rs("Title") +""
'如果新聞中有圖片,則在標題中顯示(附圖)
If rs("Attpic") Then Response.Write "(附圖)" End If
Response.Write "</a>"
'3天內新聞標記new圖片
If datediff("d", rs("Posttime"), ndate+time()) <= 0 Then
Response.Write "<img SRC='pic/new.gif' ALT='最新的新聞!' border=0></td>"
End If
'顯示新聞提交的時間
Response.Write "<td width='20%'>(" + CStr(rs("Posttime")) + ")</td></tr>"
End If
rs.MoveNext
Loop
Response.Write"</table>"
'設置返回頂部鏈接,跳轉到書簽#top
Response.Write "<p align=right><a href=""#top"">返回頂部</a> "
'生成“更多新聞”鏈接,查看指定類別所有新聞的腳本為Category.asp
Response.Write "<a target='_self' href='Category.asp?flag=" + CStr(cid) + "'>更多新聞...</a></p>"
Response.Write "</td></tr></table></td></table>"
rs.Close
rsCate.MoveNext
loop
%>
因為在第l步中已經將各新聞類別的標題讀取到記錄集rsCate中,所以只需要使用執行rsCate.MoveFirst語句將指針復位就可以了。使用DO WHIIlE循環語句依次處理每個新聞類別,讀取此類別中的所有新聞信息到記錄集rs中,并在表格中顯示新聞標題。請參照注釋理解。
在對系統進行管理之前,需要通過系統的身份認證。本站中使用chkpwd.asp進行身份驗證。對于需要登陸才能察看的網頁可以在網頁的最前端加上如下代碼:
<!--#include file=”chkpwd.asp”-->
這樣為登陸的用戶將看到如下界面:
管理界面的功能是對新聞類別和新聞提供管理界面,只有有權限的用戶才能進入管理界面。本節將介紹管理界面index.asp的實現方法。
錄入新聞類別和新聞內容后,index.asp的界面如圖5-7所示。
下面介紹index.asp的主要代碼。
(1)包含文件
在index.asp的開始部分添加下面的代碼,這樣在打開網頁時,程序會自動連接到數據庫,并進行身份驗證。
<!--#include file="ConnDB.asp"-->
<!--#include file="ChkPwd.asp"-->
(2)顯示新聞類別鏈接
index.asp將新聞按照分類顯示,每個新聞類別只顯示最新的20條新聞。顯示新聞類別的代碼如下:
<%
Dim rs,rsCate
Set rs = Server.CreateObject("ADODB.RecordSet")
set rsCate = Server.CreateObject("ADODB.RecordSet")
'定義變量
Dim iflag,sql_where
'參數flag表示指定的新聞類別
iflag = Request.QueryString("flag")
'設置SQL語句,讀取所有的新聞類別到rs.Cate
sql = "SELECT * FROM Category ORDER BY CateId"
Set rsCate = conn.Execute(sql)
'顯示新聞類別鏈接,注意根據類別編號設置參數flag
DO WHILE Not rsCate.EOF
stitle = rsCate("CateName")
cid = rsCate("CateId")
%>| <a href='index.asp?flag=<%=cid%>'><font style='TEXT-DECORATION: none;color:black'><%=stitle%></font></a>
<%
rsCate.MoveNext
Loop
%>
在調用index.asp時,參數flag表示新聞類別。如果flag=0,則顯示全部新聞,否則顯示指定類別的新聞。
(3)顯示管理鏈接
在index.asp中,將根據用戶類型顯示管理鏈接,包括“更改密碼”、“類別管理”、“用戶管理”和“退出登錄”,只有Admin用戶才能看到“類別管理”和“用戶管理”鏈接。顯示管理鏈接的代碼如下:
<%
'如果為管理員則顯示類別管理和用戶管理
If Session("UserName") = "Admin" Then
Response.Write " <a href='Cate_Admin.asp'><font color=red>類別管理</font></a>"
Response.Write " <a href='UserList.asp'><font color=red>用戶管理</font></a>"
sql_where = ""
Else
'如果不是系統管理員,則只能管理自己提交的新聞,所以在這里設置WHERE子句的條件
sql_where = " Poster='" & Session("UserName") & "'"
End If
%>
Session(”UserName”)中保存著當前登錄用戶的用戶名。當Session(”UserName”)=”Admin”時,才能顯示“類別管理”和“用戶管理”超級鏈接。
從程序中可以看到,各項管理功能對應的頁面如下:
(1)更改密碼PwdChange.asp;
(2)類別管理Cate—Admin.asp;
(3)用戶管理UserList.asp;
(4)退出登錄logout.asp。
變量sql_where用來記錄查詢條件。如果當前用戶是Admin,則sql_where=“”,即顯示所有新聞;否則設置查詢條件為“Poster=“”&Session(“UserName”)&“””,即只能管理自己創建的新聞。
(4)分頁顯示新聞信息
下面將根據指定的新聞類別和頁碼顯示新聞標題列表,代碼如下:
<%
'根據參數iflag和sql_where變量設置SQL語句,讀取新聞數據
If iflag = "" Then
If sql_where = "" Then
sql = "SELECT * FROM News ORDER BY Posttime DESC"
Else
sql = "SELECT * FROM News WHERE " & sql_where & " ORDER BY Posttime DESC"
End If
Else
If sql_where = "" then
sql = "SELECT * FROM News WHERE CateId=" & iflag & " ORDER BY Posttime DESC"
Else
sql = "SELECT * FROM News WHERE CateId=" & iflag & " And " & sql_where & " ORDER BY Posttime DESC"
End If
End If
rs.Open sql,conn,1,1
'如果記錄集rs為空,則顯示“目錄還沒有記錄”
If rs.EOF Then
Response.Write "<tr><td colspan=4 align=center>目前還沒有記錄。</td></tr></table>"
Else
'設置分頁顯示,每頁顯示20條新聞記錄
rs.PageSize = 20
'讀取參數page,表示當前的頁碼,使用CLng將其轉換為長整型
Page = CLng(Request("Page"))
'處理不合法的頁碼
If Page < 1 Then Page = 1
If Page > rs.PageCount Then Page = rs.PageCount
'設置當前頁碼為Page
rs.AbsolutePage = Page
'循環顯示當前頁的記錄
For i = 1 to rs.PageSize
'如果到達記錄集結尾,則跳出循環
if rs.EOF then Exit For
%>
<tr><td><a href="newsView.asp?id=<%=rs("id")%>" onClick="return newwin(this.href)"><%=rs("title")%></a>
<%If rs("attpic")=true then Response.write "(附圖)" End If%></td>
<td align="center"><%=rs("posttime")%></td>
<td align="center"><a href="newsedit.asp?id=<%=rs("id")%>" onClick="return newwin(this.href)">修 改</a></td>
<td align="center"><input type="checkbox" name="News" id="<%=rs("id")%>" style="font-size: 9pt" value="ON"></td>
</tr>
<%
rs.MoveNext()
Next
%>
</table>
<% '顯示分頁頁碼
If rs.pagecount>1 then
Response.Write "<table border='0'><tr><td><b>分頁:</b></td>"
For i = 1 To rs.PageCount
Response.Write "<td><a href='index.asp?flag=" & iflag & "&page=" & i & "'>"
Response.Write "[<b>" & i & "</b>]</a></td>"
Next
Response.Write "</tr></table>"
End If
End If
%>
這部分代碼的關鍵部分是根據新聞類別和用戶類型生成sELECT語句,查詢指定的新聞記錄。在調試程序時,可以使用下面的語句顯示sELECT語句的內容。
Response.write sql
新聞類別管理模塊可以實現以下功能:
(1)添加新的新聞類別記錄;
(2)修改新聞類別記錄;
(3)刪除新聞類別記錄。
只有Admin用戶才有權限進入新聞類別管理模塊,在index.asp中,單擊“類別管理”超級鏈接,可以打開類別管理頁面cate_Admin.asp。
打開新聞類別管理界面,如圖6-9所示。
圖6-9 新聞類別管理界面
下面將介紹Cate_Admin.asp中與界面顯示相關的部分代碼。
1.顯示新聞類別信息
為了便于用戶管理新聞類別,Cate_Admin.asp以表格的形式顯示新聞類別名稱,并在后面顯示修改鏈接和刪除復選框,代碼如下:
<p align='center'><font style="FONT-SIZE: 12pt"><b>新 聞 類 別 管 理</b></font></p>
<center>
<table border="0" cellspacing="0" width="90%">
<tr>
<td align=right>
<a href="index.asp"><font color="red">新聞管理</font></a>
<a href="User_admin.asp"><font color="red">用戶管理</font></a>
</td>
</tr>
</table>
<table border="1" cellspacing="0" width="90%" bgcolor="#F0F8FF" bordercolorlight="#4DA6FF" bordercolordark="#ECF5FF">
<tr>
<td width="60%" align="center" bgcolor="#FEEC85"><strong>類 別</strong></td>
<td width="20%" align="center" bgcolor="#FEEC85"><strong>修 改</strong></td>
<td width="20%" align="center" bgcolor="#FEEC85"><strong>選 擇</strong></td>
</tr>
<%
Set rs = Server.CreateObject("ADODB.RecordSet")
'讀取所有的新聞類別數據到記錄集rs中
sql = "SELECT * FROM Category ORDER BY CateId"
rs.Open sql, conn, 1, 1
If rs.EOF Then
'如果記錄集為空,則顯示“目前還沒有記錄”
Response.Write "<tr><td colspan=3 align=center><font style='COLOR:Red'>目前還沒有記錄。</font></td></tr></table>"
Else
'在表格中顯示新聞類別名稱
DO WHILE Not rs.EOF
%>
<tr>
<td><%=rs("CateName")%></td>
<td align="center"><a href="Cate_Admin.asp?Oper=update&cid=<%=rs("CateId")%>&name=<%=rs("C
ateName")%>">修 改</a></td>
<td align="center"><input type="checkbox" name="Cate" id="<%=rs("CateId")%>"></td>
</tr>
<%
rs.MoveNext()
LOOP
%>
</table>
可以看到,修改新聞類別的頁面也是Cate_Admin.asp。參數Oper的值為update,表示當前操作為修改新聞類別;參數cid表示要修改的新聞類別編號;參數name表示要修改的新聞類別名稱。新聞類別后面的復選框名為Cate,它的id值與對應新聞類別的編號相同。
通常刪除功能也可以通過超級超級鏈接來實現,就像本例中的‘‘修改’’
超級鏈接。但是一次只能刪除一條記錄。本實例介紹一種更方便的方法,即通
過復選框選擇要刪除的記錄,然后單擊cc刪除,,按鈕,這樣可以同時刪除多
條記錄。
2.顯示功能按鈕
如果存在新聞類別記錄,則在表格下面顯示“全選”、“清空”和“刪除”
按鈕,這些按鈕是為刪除新聞類別記錄服務的,代碼如下:
'如果記錄數大于0,則顯示全選、清空和刪除等按鈕
If rs.RecordCount>0 then
%>
<input type="button" value="全 選" onclick="sltAll()">
<input type="button" value="清 空" onclick="sltNull()">
<input type="submit" value="刪 除" name="tijiao" onclick="SelectChk()">
<%End If%>
rs.RecordCount返回當前記錄集的記錄數量。
3.顯示添加或修改新聞類別的表單
在功能按鈕的下面,將顯示添加或修改新聞類別的表單。當flag=update
時,將顯示修改新聞類別的表單;否則顯示添加新聞類別的表單,代碼如下:
<%
'如果當前狀態為修改,則顯示修改的表單,否則顯示添加的表單
If Soperate = "update" Then
sTitle = Request.QueryString("name")
%>
<form name="UFrom" method="post" action="Cate_Admin.asp?cid=<%=Operid%>&Oper=edit">
<div align="center">
<input type="hidden" name="sOrgTitle" value="<%=sTitle%>">
<font color="#FFFFFF"><b><font color="#000000">類別名稱</font></b></font>
<input type="text" name="txttitle" size="20" value="<%=sTitle%>">
<input type="submit" name="Submit" value=" 修 改 ">
</div>
</form>
<%Else%>
<form name="AForm" method="post" action="Cate_Admin.asp?Oper=add">
<div align="center">
<font color="#FFFFFF"><b><font color="#000000">類別名稱</font></b></font>
<input type="text" name="txttitle" size="20">
<input type="submit" name="Submit" value=" 添 加 ">
</div>
</form>
<%End If%>
添加和修改新聞類別的腳本都是Cate_Admin.asp,只是參數不同。當參數0per等于edit
時,程序將處理修改的新聞類別數據;當參數Oper等于add時,程序將處理添加的新聞類別
數據。
在執行Cate_Admin.asp時,如果參數Oper不等于update,頁面的下方將顯示添加數據的表單Aform。在文本域txttitle中輸入新聞類別的名稱,然后單擊“添加’,按鈕,將調用Cate_Admin.asp,參數Oper等于add,表示插入新記錄。
下面將介紹相關的代碼。
在執行Cate_Admin.asp時,可以在url中包含參數,程序將根據參數Oper的值決定進行的操作,與添加數據相關的代碼如下:
<%
'處理添加、修改和刪除操作
dim Soperate
Soperate = Request.QueryString("oper")
Operid = Request.QueryString("cid")
'刪除
If Soperate="delete" Then
sql = "SELECT * FROM News WHERE CateId In (" & CStr(Operid) & ")"
Set rs = Conn.Execute(sql)
If rs.EOF Then
sqldelt = "DELETE FROM Category WHERE CateId In(" & CStr(Operid) & ")"
Conn.Execute(sqldelt)
Response.Write "新聞類別已經成功刪除!"
Else
Response.Write "新聞類別中包含新聞,不能刪除"
End If
'添加
ElseIf Soperate = "add" then
CateName = Request("txttitle")
'判斷是否已經存在此類別名稱
sql = "SELECT * FROM Category WHERE CateName='" & CateName & "'"
Set rs = Conn.Execute(sql)
'如果沒有此類別名稱,則創建新記錄
If Rs.EOF Then
sql = "INSERT INTO Category(CateName) VALUES('" & CateName & "')"
Conn.Execute(sql)
Response.Write"新聞類別已經成功添加!"
Else
Response.Write "已經存在此類別名稱!"
End If
Set rs = Nothing
ElseIf Soperate = "edit" Then
CateName = Request("txttitle")
'如果新類別名稱與舊名稱不同,則判斷是否存在此類別名稱
sql = "SELECT * FROM Category WHERE CateName = '" & CateName & "' And CateId=" & Operid
Set rs = conn.Execute(sql)
If Rs.EOF Then '如果原類別編號和新類別名稱不存在,則表示類別名稱發生變化
Set rs = Nothing
'此時判斷是否存在此類別名稱
sql = "SELECT * FROM Category WHERE CateName='" & CateName & "'"
Set rs = Conn.Execute(sql)
If Rs.EOF Then '新類別不存在
conn.Execute("UPDATE Category SET CateName='" & CateName & "' WHERE CateId=" & Operid)
Response.Write "新聞類別已經成功修改!"
Else
Response.Write "已經存在此類別名稱"
End if
End If
End If
%>
注意,在插入新聞類別之前,應該判斷此新聞類別是否已經存在。這樣可以避免出現重復的新聞類別。
在Cate_Admin.asp中,單擊新聞類別后面的“修改’,超級鏈接,將再次執行Cate_Admin.asp,
參數Oper等于update。此時,頁面的下方將顯示修改數據的表單Uform。在文本域txttitle中輸入新聞類別的名稱,然后單擊“修改”按鈕,將調用Cate_Admin.asp,參數Oper等于edit,表示修改記錄。下面將介紹相關的代碼。在執行Cate_Admin.asp時,可以在url中包含參數,程序將根據參數Oper的值決定進行的操作。
注意,在修改新聞類別之前,應該判斷新的新聞類別是否已經存在。這樣可以避免出現重復的新聞類別。
在刪除新聞類別之前,需要選中相應的復選框。下面介紹幾個與選擇復選框相關的javaScript函數。
1.選擇全部復選框
在Care_Admin.asp中,定義“全選”按鈕的代碼如下:
<input type="button" value="全 選" onclick="sltAll()">
當單擊“全選”按鈕時,將執行sltAll()函數,代碼如下:
function sltAll()
{
var nn = self.document.all.item("Cate");
for(j=0;j<nn.length;j++)
{
self.document.all.item("Cate",j).checked = true;
}
}
self對象指當前頁面,self.document.a11.item("Cate")返回當前頁面中Cate復選框的數量。程序通過for循環語句將所有的Cate復選框值設置為true。
2.全部清除選擇
在Cate_Admin.asp中,定義“清空”按鈕的代碼如下:
<input type="button" value="清 空" onclick="sltNull()">
當單擊“清空”按鈕時,將執行sltNull()函數,代碼如下:
function sltNull()
{
var nn = self.document.all.item("Cate");
for(j=0;j<nn.length;j++)
{
self.document.all.item("Cate",j).checked = false;
}
}
3.生成并提交刪除編號列表
在Cate_Admin.asp中,定義“刪除”按鈕的代碼如下:
<input type="submit" value="刪 除" name="tijiao" onclick="SelectChk()">
當單擊“刪除”按鈕時,將執行SelectChk()函數,代碼如下:
function SelectChk()
{
var s = false; //用來記錄是否存在被選中的復選框
var Cateid, n=0;
var strid, strurl;
var nn = self.document.all.item("Cate"); //返回復選框Cate的數量
for (j=0; j<nn.length; j++) {
if (self.document.all.item("Cate",j).checked) {
n = n + 1;
s = true;
Cateid = self.document.all.item("Cate",j).id+""; //轉換為字符串
//生成要刪除新聞類別編號的列表
if(n==1) {
strid = Cateid;
}
else {
strid = strid + "," + Cateid;
}
}
}
strurl = "Cate_Admin.asp?Oper=delete&cid=" + strid;
if(!s) {
alert("請選擇要刪除的新聞類別!");
return false;
}
if (confirm("你確定要刪除這些新聞類別嗎?")) {
form1.action = strurl;
form1.submit();
}
}
程序對每個復選框進行判斷,如果復選框被選中,則將復選框的id值轉換為字符串,并追加到變量strid中。因為復選框的id值與對應的新聞類別編號相同,所以最后strid中保存的是以逗號為分隔符的待刪除的新聞類別編號。以strid的值為參數執行Cate_Admin.asp,參數Oper等于delete,就可以刪除選中記錄了。
在刪除新聞類別之前,應該判斷此新聞類別中是否包含新聞,如果有新聞,則不能刪除,否則會產生沒有新聞類別的垃圾新聞。
系統用戶都可以發布新聞,新聞發布管理模塊包含以下功能:
(1)發布新新聞;
(2)修改新聞;
(3)刪除新聞。
在index.asp中,“添加新聞”按鈕的定義代碼如下:
<input type="button" value="添加新聞" onclick="newwin('NewsAdd.asp')" name=add>
當單擊“添加新聞”按鈕時,將觸發onclick事件,并調newwin
('NewsAdd.asp')函數,即在彈出的新窗口中執行News.Add.asp。
NewsAdd.asp的運行界面如圖7-10所示。
圖7-10 NewsAdd.asp的運行界面
將新聞類別添加到下拉菜單中,代碼如下:
<%
Set rs = Server.CreateObject("ADODB.RecordSet")
'將新聞類別裝入下拉菜單中
sql = "SELECT * FROM Category ORDER BY CateId"
Set rsCate = Conn.Execute(sql)
DO WHILE Not rsCate.EOF
stitle = rsCate("CateName")
cid = rsCate("CateId")
%>
<option value="<%=cid%>"><%=stitle%></option>
<%
rsCate.movenext
LOOP
%>
下拉菜單名為Cate,值為新聞類別編號,顯示的內容是新聞類別名稱。編輯新聞內容表單的定義代碼如下:
<form action="newsSave.asp" method="POST" name="myform" align="center" onsubmit="return ValidationPassed">
可以看到,表單名為myfom,表單提交后,將由newsSave.asp處理表單數據。在提交表單數據之前,程序將對ValidationPassed變量進行判斷,只有當ValidationPassed=True時,才執行提交操作。變量ValidationPassed的值將在對數據有效性進行驗證時被賦值。在.NewsAdd.asp中,定義“確定”按鈕的代碼如下:
<input type="submit" value=" 確 定 " name="B1" onclick="return form_onsubmit(this.form)">
在單擊“確定”按鈕時,將執行form_onsubmit(this.form),進行數據有效性驗證,代碼如下:
function form_onsubmit(obj)
{
ValidationPassed = true;
if(obj.Cate.selectedIndex <0) {
alert("請選擇新聞類別")
ValidationPassed = false;
return ValidationPassed;
}
if(obj.title.value == "") {
alert("請填寫新聞標題");
ValidationPassed = false;
return ValidationPassed;
}
if(obj.txtcontent.value == "") {
alert("請填寫新聞內容!");
ValidationPassed = false;
return ValidationPassed;
}
}
這是一段JavaScript代碼,參數obj接受this.form的值,表示表單myfom。程序將分別對新聞類別、新聞標題和新聞內容進行判斷,這些信息是必須填寫的。如果沒有填寫前面提到的信息,將彈出相關的對話框,ValidationPassed=false,這樣表單數據將無法提交。
在NewsAdd.asp頁面的相關位置使用#include命令包括template.asp,將可以顯示控制模板。
下面介紹newSave.asp的部分代碼。在newSave.asp中,有一個函數ChangeStr(),它的功能是替換新聞正文中的功能字符串,目的是使其能夠成為HTML網頁的一部分,在瀏覽網頁時被正常顯示。被替換的功能字符串包括以下內容:
[upload] 上傳新聞 圖片標記, 需要將其替換為 “<div[space]align=center><img[space]src=images/”,其中[space]是空格標記,需要在顯示新聞正文時轉換:
[/upload] 與[upload]匹配使用,標記上傳新聞圖片的結束。需要將其替換為 “[space]border=0[space]width=300></img></div>”;空格(””) 空格將被替換為“ ;”;chr(13) 回車符將被替換為<BR>。
函數ChangeStr()的代碼如下:
Function ChangeChr(str)
ChangeChr = Replace( str, "[upload]", "<div[space]align=center><img[space]src=images/")
ChangeChr=Replace( ChangeChr, "[/upload]", "[space]border=0[space]width=300></img></div>")
ChangeChr = Replace( ChangeChr, " ", " ")
ChangeChr = Replace( ChangeChr, chr(13), "<br>")
End Function
新聞正文需要保存在數據庫中,當從數據庫中讀取新聞正文的內容在網頁中顯示時,空格將被自動過濾掉,這樣<imgsrc=images/>將無法被正確顯示。為了避免這種情況發生,這里將空格表示為[space],并存入數據庫,在讀取數據時再將其轉換為空格。
下面程序將接收從NewsAdd.asp傳遞來的數據,并將它們轉換為能夠保存到數據庫中的格式,代碼如下:
Dim title '新聞標題
Dim content '新聞內容
Dim category '新聞類別
Dim sql 'sql語句字符串
Dim rs '記錄集變量
title = Request("title")
title = Replace(title,"'","‘")
attpic = Request("attpic")
rqtContent = ChangeChr(request("txtcontent")) '替換函數
rqtContent = Replace(rqtContent,"'","‘")
因為在sql語句中,單引號(')是特殊字符,所以需要將新聞標題和正文中
的單引號替換為全角單引號(‘),并使用ChangeChr()函數對新聞正文進行轉換。
接下來程序將保存新聞數據,代碼如下:
Set rs = Server.CreateObject("ADODB.RecordSet")
'定義sql語句,為插入新聞記錄定義記錄集
sql="SELECT * FROM News"
rs.Open sql, Conn, 1, 3
'使用AddNew和Update插入新記錄
rs.AddNew
rs("CateId") = CInt(Request("Cate"))
rs("Title") = title
rs("Content") = rqtContent
rs("Posttime") = now()
rs("Poster") = Session("UserName")
rs("ReadCount") = 0
If attpic <> "" Then
rs("attpic") = attpic
End If
rs.Update
'釋放資源,顯示提示信息
set rs = nothing
Response.Write "<h2>添加成功!</h2>"
本節前面介紹插入新數據時,都是采用定義INSERT語句的方法。這里使
用一種新方法,在記錄集中使用rs.AddNew插入新記錄,然后依次對rs中各字段賦值,最后使用rs.Update方法保存記錄。
在index.asp中,每條新聞記錄的后面都有一個修改超級鏈接。單擊此鏈接,將打開NewsEdit.asp,對指定新聞進行編輯。參數id表示新聞編號。
本節將介紹如何使用NewsEdit.asp修改新聞內容。在NewsEdit.asp的開始部分,將使用下面的代碼包含相關文件,從而連接到數據庫,并判斷用戶的編輯權限。
<!--#include file="ConnDB.asp"-->
<!--#include file="isAuthor.asp"-->
在Newsedit.asp中程序將首先根據參數 ID的值讀取新聞數據,代碼如下:
Set rsNews = Server.CreateObject("ADODB.RecordSet")
Set rsCate = Server.CreateObject("ADODB.RecordSet")
'讀取指定新聞數據
Set rsNews = Conn.Execute("SELECT * FROM News WHERE id = " & Request.QueryString("id"))
因為新聞正文數據在存儲前進行過替換處理,所以這里需要將數據還原,代碼如下:
If Not rsNews.EOF Then
'對新聞內容進行替換
txtcontent = rsNews("content")
txtcontent = replace(txtcontent, "<br>", chr(13))
txtcontent = replace(txtcontent, " ", " ")
rqtContent = replace(txtcontent, "''", "'")
替換數據的目的是使它能夠在表單的滾動文本域txtcontent中正確顯示。代碼中省略的部分包括生成新聞類別下拉菜單,以及根據新聞數據對表單中的各組件賦值。
在NewsEdit.asp中,定義了一個隱藏域,代碼如下:
<input type="hidden" name="id" value="<%=rsNews("id")%>">
它的作用是記錄當前編輯新聞的編號。
編輯新聞信息表單的定義代碼如下:
<form action="newsUpdate.asp" method="POST" name="myform" align="center" onsubmit="return ValidationPassed">
與userAdd.asp相似,在提交新聞信息時,需要首先執行form_onsubmit函數,對用戶輸入數據的有效性進行驗證。
數據提交后,將由。newsupdate.asp進行處理,它的主要代碼如下:
<%
'對新聞正文進行替換的函數
Function ChangeChr(str)
ChangeChr = Replace( str, "[upload]", "<div[space]align=center><img[space]src=images/")
ChangeChr=Replace( ChangeChr, "[/upload]", "[space]border=0[space]width=300></img></div>")
ChangeChr = Replace( ChangeChr, " ", " ")
ChangeChr = Replace( ChangeChr, chr(13), "<br>")
End Function
rqtContent = ChangeChr(request("txtcontent")) '替換函數
rqtContent = Replace(rqtContent,"'","‘")
'替換新聞標題中的半角單引號
Dim title
title = Request.Form("title")
title = replace(title,"'","‘")
'設置附圖標記
If Request.Form("attpic")<>"" Then
attpic = 1
Else
attpic = 0
End If
'設置UPDATE語句,更新新聞信息
sql = "UPDATE News SET Posttime='" & now() &"', Attpic=" & attpic & ", Title = '" & title _
& "', CateID = " & CInt(Request("Cate")) & "," & "Content='" & rqtContent & "' WHERE Id=" & CInt(Request("Id"))
conn.Execute(sql)
Response.Write "<h2>修改成功!</h2>"
%>
程序首先定義了替換函數ChangeChr(),然后接收從NewsEdit.asp中傳遞來的新聞數據,最后定義了update語句,根據接收到的數據更新新聞信息。
NewsEdit.asp的顯示界面與NewsAdd.asp相似,處理過程也有相同之處,請讀者參照理解。
在刪除新聞之前,需要選中相應的復選框。這與刪除新聞類別時的操作相似,所以在index.asp中,也定義了操作復選框的函數,包括選擇全部復選框的sltAll()清除全部選擇的sltNull()和生成并提交刪除編號列表的SelectChk()等。
處理刪除新聞操作的腳本為NewsDelt.asp,參數id表示要刪除的新聞編號。NewsDelt.asp的主要代碼如下:
<%
Dim ids
ids = Request.QueryString("id")
sql = "DELETE FROM News WHERE Id IN (" & ids & ")"
conn.Execute(sql)
%>
<script language="JavaScript">
alert("成功刪除!");
location.href = "index.asp";
</script>
在DELETE語句中使用WHERE…in…字句的功能是刪除新聞編號列表IDS中出現的所有的新聞。
如果系統中新聞數量比較多,那么只按照分類察看新聞顯然是不夠的。為了方便網友使用,本站中設計了新聞管理功能。
新聞查詢管理頁面的腳本是search.asp,運行界面如圖所示
可以看到,新聞查詢可以分為下面幾種情況:
(1)按發布日期查詢。
(2)查詢新聞標題和新聞內容中包括的文字。
在search.asp中,用于編輯查詢條件的表單為Form1,它的定義代碼如下:
<form name="form1" method="POST" action="searchResult.asp">
當表單數據提交時,將執行searchResult.asp。為了驗證用戶錄入數據的有效性,在search.asp中定義了一些函數,下面介紹這些函內容。
1.IsEmpty()函數
IsEmpty()函數的功能是判斷字符串是否為空,代碼如下:
function isEmpty (str) {
if ((str==null)||(str.length==0)) return true;
else return(false);
}
參數str表示要判斷的字符串,如果它為空或長度為0則返回true,否則返回false。
2.IsDigital()函數
IsDigital()函數的功能是判斷字符串是否是數字類型,代碼如下:
function isDigit(s)
{
var patrn=/^[0-9]{1,20}$/;
if (!patrn.exec(s)) return false
return true
}
參數s表示要判斷的字符串。變量patrn是一個正則表達式,正則表達式是由普通字符以及特殊字符組成的文字模式。該模式描述在查找文字主體時待匹配的一個或多個字符串。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。正則表達式中的Execute方法對指定的字符串執行正則表達式搜索。/^表示正則表達式的開始,$/表示正則表達式的結束,[0.9]表示以0~9的數字為開始和結束,{1,20}表示長度為1~20。
3.IsInt()函數
IsInt()函數的功能是判斷指定的字符串是否是整型數據,代碼如下:
function isInt (theStr) {
var flag = true;
if (isEmpty(theStr)) { flag=false; }
else
{ for (var i=0; i<theStr.length; i++) {
if (isDigit(theStr.substring(i,i+1)) == false) {
flag = false; break;
}
}
}
return(flag);
}
參數theStr表示要判斷的字符串。如果theStr為空,則返回false;否則對theStr中的每個字符進行判斷,如果有一個字符不是數字類型(使用IsDigital函數判斷)則返回false。如果上述情況都沒有返回false,則返回true。
4.IsBetween(、)函數
IsBetween()函數的功能是判斷指定數據是否在兩個數字之間,代碼如下:
function isBetween (val, lo, hi) {
if ((val < lo) || (val > hi)) { return(false); }
else { return(true); }
}
參數val表示要比較的數值,參數lo表示比較范圍的下限,參數hi表示比較范圍的上限。程序將val與lo、hi進行比較,如果val的值不在它們之間,則返回false,否則返回true。
5.IsIDate()函數
IsDate()函數的功能是判斷指定數據是否是日期型數據,代碼如下:
function isDate (theStr) {
var the1st = theStr.indexOf('-');
var the2nd = theStr.lastIndexOf('-');
if (the1st == the2nd) { return(false); }
else {
var y = theStr.substring(0,the1st);
var m = theStr.substring(the1st+1,the2nd);
var d = theStr.substring(the2nd+1,theStr.length);
var maxDays = 31;
if (isInt(m)==false || isInt(d)==false || isInt(y)==false)
return(false);
else if (y.length < 4) return(false);
else if (!isBetween (m, 1, 12)) return(false);
else if (m==4 || m==6 || m==9 || m==11) maxDays = 30;
else if (m==2) {
if (y % 4 > 0) maxDays = 28;
else if (y % 100 == 0 && y % 400 > 0) maxDays = 28;
else maxDays = 29;
}
if (isBetween(d, 1, maxDays) == false) { return(false); }
else { return(true); }
}
}
可以看到前面定義的函數都是為了實現Isdate()函數的功能。
在search.asp中,定義“開始”按鈕的代碼如下:
<input type="submit" value=" 開 始 " language=javascript name="tijiao" onclick="return button2_onclick()">
當用戶單擊“開始”按鈕時,將觸發onclick事件,并執行Button2_onclick()函數,代碼如下:
function button2_onclick()
{
// 字段不能都為空,如果發布日期為空,則查詢條件不能空
if (form1.sdate.value=="" && form1.edate.value=="" && form1.searchcontent.value == "")
{
alert("查詢條件不能都為空!");
form1.searchcontent.focus();
return (false);
}
// 檢查日期格式是否正確
if (form1.sdate.value.length>0)
{
if(!isDate(form1.sdate.value))
{
alert("開始日期格式不正確,請重新輸入!");
form1.sdate.focus();
return (false);
}
}
if (form1.edate.value.length>0)
{
if(!isDate(form1.edate.value))
{
alert("截至日期格式不正確,請重新輸入!");
form1.edate.focus();
return (false);
}
}
}
這段程序將判斷用戶輸入的查詢條件是否為空,并使用自定義函數IsDate()驗證日期是否有效。
下面介紹searchResult.asp的實現方法。它的主要功能是根據用戶提交的查詢條件生成SELECT語句,并以表格的形式顯示查詢結果。在searchResuIt.asp中,定義了一個函數GetUserName(),它的功能是根據用戶名返回用戶的真實姓名,代碼如下:
<%
'根據用戶名讀取用戶姓名
Function GetUserName(UserId)
Dim RsUser,sql
Set RsUser = Server.CreateObject("ADODB.RecordSet")
sql= "SELECT * FROM Users WHERE UserName='" & Trim(UserId) & "'"
Set rsUser = Conn.Execute(sql)
If NOT rsUser.EOF Then
GetUserName = rsUser("Ename")
Else
GetUserName = "無名"
End If
End Function
%>
這里使用GetuserName()函數的作用是取得新聞提交人的姓名,并在查詢結果中顯示。如果將本系統用于企業內部的新聞發布平臺,則通常需要顯示提交人姓名。如果不需要此功能,也可以將相關代碼去掉。
searchResult.asp的最重要部分就是生成查詢新聞的SELECT語句,代碼如下:
<%
' 提取發布時間查詢范圍
sDate = Request("sdate")
eDate = Request("edate")
' 根據時間字段設置查詢語句,需要把時間字符串轉換為日期型
If Len(sDate)>0 And Len(eDate)>0 Then
strSqlPTime = " WHERE PostTime>='" & sDate & "'"
strSqlPTime = strSqlPTime & " And PostTime<='" & eDate & "'"
ElseIf Len(sDate)>0 And Len(eDate)=0 Then
strSqlPTime = " WHERE PostTime>='" & sDate & "'"
ElseIf Len(sDate)=0 And Len(eDate)>0 Then
strSqlPTime = " WHERE PostTime<='" & eDate & "'"
End If
' 取得查詢模式(精確查詢或模糊查詢),參見search.asp中的定義
searchcontent1 = Request("searchcontent")
fanwei = Request("fanwei")
If fanwei ="all" Then '精確查詢
searchcontent = searchcontent1
Else '模糊查詢
searchcontent = "%" & searchcontent1 & "%"
End If
' 取得查詢范圍值
searchfanwei = Request("D1")
If searchfanwei="title" Then '只在新聞標題中查詢
Response.Write "<h4><font color=#7966C6>按 信息標題 查詢的結果</font></h4><br>"
strSQL = " Title LIKE '" & searchcontent & "' ORDER BY PostTime DESC"
ElseIf searchfanwe="content" Then '只在新聞內容中查詢
Response.Write "<h4><font color=#7966C6>按 信息內容 查詢的結果</font></h4><br>"
strSQL = " Content LIKE '" & searchcontent1 & "' ORDER BY PostTime DESC"
End If
'合并查詢條件
If Len(strSqlPTime)=0 Then
strSQL = " WHERE " & strSQL
Else
strSQL = strSqlPTime & " And " & strSQL
End If
'記錄查找到的新聞序號
Dim ncnt
ncnt = 0
'輸出表格
Response.Write "<table width='100%'>"
Response.Write "<tr>"
Response.Write "<td align=middle width='10%'><b>序號</b></td>"
Response.Write "<td align=left width='30%'><b>信息標題</b></td>"
Response.Write "<td align=middle width='14%'><b>所屬類別</b></td>"
Response.Write "<td align=middle width='10%'><b>內容長度</b></td>"
Response.Write "<td align=middle width='16%'><b>提交人</b></td>"
Response.Write "<td align=middle width='20%'><b>提交時間</b></td>"
Response.Write "</tr>"
Dim rsSearch,rsCate
Set rsSearch= Server.CreateObject("ADODB.RecordSet")
Set rsCate = Server.CreateObject("ADODB.RecordSet")
'生成查詢語句
strSQL = "SELECT * FROM News " & strSQL
'Response.Write "sql :"& strSQL
rsSearch.Open strSQL, Conn, 1, 3
以上代碼的工作過程如下:
根據參數sdate和edate生成與日期相關的查詢條件;根據查詢模式(精確查詢或模糊查詢)生成相關的查詢條件。如果是精確查詢,則使用“=”;如果是模糊查詢,則使用LIKE和通配符%;根據查詢范圍生成相關的查詢條件;將所有查詢條件合并成WHERE子句;生成顯示查詢結果的表頭;生成并執行SELECT語句。
-接著程序將使用循環語句依次處理每條查詢記錄,代碼如下:
'依次處理查詢結果
Do While Not rsSearch.EOF
ncnt = ncnt + 1
Response.Write "<tr bgColor=Lavender style='COLOR:Purple;'>"
Response.Write "<td align=middle>"&ncnt&"</td>"
'輸出新聞標題及鏈接
Response.Write "<td><a href=NewsView.asp?id="&rsSearch("Id")&" onClick='return newwin(this.href)'>"&rsSearch("Title")&"</a>"
' 判斷是否有圖片
If rsSearch("attpic") Then
Response.Write "(附圖)"
End If
Response.Write "</td>"
' 取得信息分類名稱
sql = "SELECT * FROM Category WHERE CateId=" & rsSearch("CateId")
Set rsCate = Conn.Execute(sql)
If NOT rsCate.EOF Then
Response.Write "<td align=middle>"&rsCate("CateName")&"</td>"
End If
' 計算內容大小
If rsSearch("Content")="--" Then
nlength=0
Else
nlength = Len(rsSearch("Content"))
' 輸出內容大小、提交人姓名
Response.Write "<td align=middle>"&nlength&" Bytes</td>"
' 顯示提交人姓名
Response.Write "<td align=middle>"&GetUserName(rsSearch("Poster"))&"</td>"
' 顯示提交時間
Response.Write "<td align=middle>"&rsSearch("PostTime")&"</td>"
Response.Write "</tr>"
End If
rsSearch.MoveNext()
LOOP
Response.Write "</table>"
Set rsSearch = Nothing
Set rsCate = Nothing
Set Conn = Nothing
%>
1、在安裝IIS之前,必須安裝TCP/IT協議。
TCP/IP協議是執行IIS的必要條件,沒有它ASP就不能運行,所以必須先安裝TVP/IP協議(如果已經安裝就可以跳過這一節)。
步驟: 控制面板→雙擊"網絡" →單擊:"添加"按鈕 →選擇"協議"選項 →在廠商列表框中選擇Microsolf選項 →在"網絡協議"列表框中選擇TCP/CP,單擊"確定"
2、安裝IIS服務器程序
IIS 的安裝是創建ASP運行環境的關鍵一步,安裝好它以后,計算機就是一臺Web服務器了。
步驟:放入光盤,點擊控制面板->添加或刪除程序->添加或刪除windows組件,如圖8-1所示選擇INTERNET信息服務單擊下一步。
安裝好IIS后,進入控制面板下的管理工具找到 INTERNET信息服務雙擊即可打開。然后建立虛擬目錄,把自己首頁的目錄寫上去,然后取一個別名,主要是為了方便,再在默認文檔中,寫上主頁的文件名就可以了,以后在IE瀏覽器中只要打127.0.0.1就會顯示自己的主頁。
圖8-1
操作系統Windows 9X、windows NT Workstation/Server4.0、Windows 2000 Server/Professional版。
CPU:沒有大的要求,只要可以運行以上的Windows操作系統就可以了。當然,速度是越快越好。
內存:基于內存需要32MB,建議使用64MB以上內存,如果使用Windows 2000,建議用128MB內存。
硬盤空間:至少有50MB以上的磁盤空間來安裝所需的組件。
ASP軟件要求
Windows 98: PWS4.0版附屬于Windows 98 光盤的add=one\pws目錄,執行其中的setup.exe,即可安裝PWS4.0版。
Web服務器軟件建設
Web的內容保存在Web站點(Web服務器)中,用戶可以通過瀏覽器(Browser)訪問Web站點。因此,Web是一種基于客戶機/服務器的體系結構。也就是說,Web實際上是一種全球性通信系統,該系統通過Intrnet使計算機相互傳送基于超媒體的數據信息。Web是一個超文本信息系統,它的超文本鏈接使得Web文檔不再象書本一樣的固定的、線性的,而是可以從一個位置迅速轉到另外的位置,從一個主題到另一個相關的主題。Web是分布式的。無論系統的internet訪問WWW。對于Web,只要通過超鏈接指向所需的站點,就可以使物理上放置在不同位置的信息在邏輯上一體化。對用戶來說這些住處是一體的。
Web具有新聞性。Web站點上的信息是動態的,經常更新的。住處的提供者可以經常的對站上的信息進行更新,所以用戶(瀏覽者)可以得到最新的信息。
Web是動態的、交互的。以Java為代表的動態技術使Web從靜態的頁面變成可擴行程序,從而大大提高了Web的動態性和交互性。可以通過超鏈接,用戶的瀏覽順序和所到站點完全由用戶自行決定。
Web服務器硬件建設專線入網具有通信速度高等優點,但是費用相對較高,投資較大。需要具備入網專線。入網后網上所有終端和工作站均可享受Internet服務。用戶可向ISP申請X.25聲母或DDN專線。專線速度可達200bps至2048bps可選。
具有了專線以后,就需要位本地子網選擇一個路由器以實現路由功能,然后接入IGS網關;也可以不用路由器,直接接入IGS網關路由器因為IGS具有IP路由軟件,可局域網連上服務器。
經過老師耐心細致的指導,及設計小組同學們的密切合作,同時翻閱了大量的資料(包括網上資料,書本及學校的一些相關資料)經過近一個月的努力,網站的設計制作告一段落。總結這次“藍球網站設計”開發制作過程,我們綜合使用了目前因特網上的各種靜態制作方法及交互式動態網站的制作設計手段,并對初步利用后臺程序完成了網站的動態響應與生成網頁的技術。同時也從中學習了對靜態頁面的處理風格,色彩搭配,頁面導航方面有了一定經驗。對用Javascript語言制作動態效果也有了更進一步的認識。在交互式網頁設計學會了如何使用MYSQL建立數據庫,以及對數據庫瀏覽,修改,添加,查詢。如何用PHP編寫 程序來方便訪客,讀者在網上查詢學校各方面的信息。
目前網站的制作技術與要求,都已經告別了因特網初期網站制作的“幼稚”期,隨著各類網站的迅速增加與瀏覽者需求的提高,無不要求網站從立意,策劃,頁面設計到后臺程序的全面提高。無論是個人網站還是企業網站都必須被要求從瀏覽者角度出發,最大限度的滿足用戶的要求,這也是以后各類網站發展競爭的真正實質所在。
本次設計由于設計時間較緊,且相關模塊比較多,加之設計經驗的不足,在網站的整體設計及各模塊功能可能設計的不完全,有待于進一步的完善和改進。
1、《FrontPage2000入門與實戰技術》,人民郵電出版社2000年5月第1版。 2、互聯網上提供的網頁制作素材及特效。
3 ASP+SQLSEVER項目開發。
網站的建立與發布,最終離不開計算機網絡系統平臺的支持。計算機網絡是計算機技術和現代通信技術的有機結合。計算機網絡技術是由現代計算機處理技術和現代通信技術結合發展而成的,是社會信息化的基礎技術。 計算機網絡技術經過30余年的發展,已經成長為一棵參天大樹。從它的作用范圍角度講有局域網、城域網和廣域網;從傳遞的速率角度講有低速、高速和超高速寬帶網等之分;從連接的形式講有環形網、星形網、總線網等;從應用的類型講可以分成控制網、通訊網、管理網等;并且把最適應于人類與外部物理世界溝通的多媒體技術大量結合在一起,形成了豐富多彩的綜合運行環境。 通過本次課程設計的制作,不但是對我這三年所學知識的一個檢驗,也是對我計算機應用水平與寫作水平的一個考核,而且還給了我一個找出自己不足的機會。
由于課程設計者水平有限,時間倉促,錯誤之處在所難免,希各位讀者批評指正。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。