老司机夜插-理伦理片-理伦片免费-理伦片免费观看-理伦片免费看-理伦日韩-理论福利片-理论片第一页-理论片电影-理论片理论

金喜正规买球

工作流的實現(在Ruby on Rails環境下)

轉帖|其它|編輯:郝浩|2009-02-09 11:33:47.000|閱讀 3515 次

概述:工作流是企業開發中不可或缺的一個重要組件。有了工作流,客戶需求的實現速度將大大提高,同時兼顧到開發效率,靈活性。Java領域已經有了多個穩定的工作流,成了Java占領企業級開發的有力助手。

# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>

  工作流是企業開發中不可或缺的一個重要組件。有了工作流,客戶需求的實現速度將大大提高,同時兼顧到開發效率,靈活性。Java領域已經有了多個穩定的工作流,成了Java占領企業級開發的有力助手。但在ROR領域,目前還沒有出色的工作流出現。RubyForge上有一些工作流的項目,但仔細看下,都是針對Java工作流的移植,而且達不到可以實用的程度。面對這個現狀,我在2006年自己開發了一個小型Ruby工作流,雖然代碼量小,但是實用性卻不錯,對于一些真實的使用案例能夠輕松勝任,也有力的支撐著我繼續向ROR道路前行。

  下面介紹我的工作流是怎么實現的。

  用VC寫一個工作流設計器,這個小軟件功能比較簡單,包含一些簡單符號的繪圖及拖拽,比如開始、結束、狀態、流轉。對于每個狀態可以設置權限,對于每個流轉可以設置條件。我在工作流領域研究的不是很深,開發這個設計器就以實用性為原則,沒有實現的特別復雜。在能夠實現用戶需求的基礎上怎么簡單怎么做。

點擊查看大圖

文件保存為xml格式

Xml代碼
<?xml version="1.0" encoding="gb2312" ?> 
<workflow> 
    <start right="" leave="" enter="@form.a2 = @user.truename&#x0D;&#x0A;@form.c2 = @user.department.name" x1="97" y1="156" x2="247" y2="279" /> 
    <end right="行政歸檔" x1="969" y1="148" x2="1129" y2="285" enter="" /> 
    <state name="部門經理審批" right="領導" enter="" leave="" x1="343" y1="179" x2="453" y2="253" /> 
    <state name="總經理審批" right="經理審批" enter="" leave="" x1="566" y1="34" x2="668" y2="98" /> 
    <state name="行政審批" right="行政審批" enter="" leave="" x1="717" y1="191" x2="870" y2="244" /> 
    <trasit name="" condition="" from="開始" to="部門經理審批" /> 
    <trasit name="大于等于3天" condition="@form.b5!=nil &amp;&amp; @form.b5 &gt;=3" from="部門經理審批" to="總經理審批" /> 
    <trasit name="" condition="@form.b5 == nil || @form.b5 &lt;3" from="部門經理審批" to="行政審批" /> 
    <trasit name="" condition="" from="總經理審批" to="行政審批" /> 
    <trasit name="" condition="" from="行政審批" to="結束" /> 
</workflow> 

<?xml version="1.0" encoding="gb2312" ?>
<workflow>
    <start right="" leave="" enter="@form.a2 = @user.truename&#x0D;&#x0A;@form.c2 = @user.department.name" x1="97" y1="156" x2="247" y2="279" />
    <end right="行政歸檔" x1="969" y1="148" x2="1129" y2="285" enter="" />
    <state name="部門經理審批" right="領導" enter="" leave="" x1="343" y1="179" x2="453" y2="253" />
    <state name="總經理審批" right="經理審批" enter="" leave="" x1="566" y1="34" x2="668" y2="98" />
    <state name="行政審批" right="行政審批" enter="" leave="" x1="717" y1="191" x2="870" y2="244" />
    <trasit name="" condition="" from="開始" to="部門經理審批" />
    <trasit name="大于等于3天" condition="@form.b5!=nil &amp;&amp; @form.b5 &gt;=3" from="部門經理審批" to="總經理審批" />
    <trasit name="" condition="@form.b5 == nil || @form.b5 &lt;3" from="部門經理審批" to="行政審批" />
    <trasit name="" condition="" from="總經理審批" to="行政審批" />
    <trasit name="" condition="" from="行政審批" to="結束" />
</workflow>

  然后將這個文件發布到系統上,由Ruby來解析這個工作流,解析工作流的Ruby代碼(放在lib目錄下)如下:

Ruby代碼
#Flow.rb  
 
require 'rexml/document' 
require "State" 
require "Trasit" 
require "Flow" 
require "pp" 
 
include REXML  
 
class Flow   
  attr_accessor :name, :publish_time 
  attr_reader :trasits, :states 
  def initialize(name, xmlstr, publish_time)  
    @publish_time = publish_time  
    @name = name  
      
    #存放所有狀態,包括開始狀態和結束,開始狀態放在第一個,結束狀態放在最后  
    @states = Array.new 
    @trasits = Array.new 
      
    #載入XML文檔  
    doc = Document.new(xmlstr)  
      
    #開始解析doc文檔  
    root = doc.root  
      
    #解析開始狀態節點  
    root.elements.each("start") {|element|  
      start = State.start  
      start.name = "開始" 
      start.enter = element.attributes["enter"].gbk  
      start.leave = element.attributes["leave"].gbk  
      start.right = element.attributes["right"].gbk  
      start.x1 = element.attributes["x1"].to_i  
      start.x2 = element.attributes["x2"].to_i  
      start.y1 = element.attributes["y1"].to_i  
      start.y2 = element.attributes["y2"].to_i  
      @states << start  
      break 
    }  
      
    #解析所有狀態節點  
    root.elements.each("state") {|element|  
      state = State.new 
      state.name = element.attributes["name"].gbk  
      state.right = element.attributes["right"].gbk  
      state.enter = element.attributes["enter"].gbk  
      state.leave = element.attributes["leave"].gbk  
      state.x1 = element.attributes["x1"].to_i  
      state.x2 = element.attributes["x2"].to_i  
      state.y1 = element.attributes["y1"].to_i  
      state.y2 = element.attributes["y2"].to_i  
      @states << state  
    }  
      
    #解析結束狀態節點  
    root.elements.each("end") {|element|  
      end_node = State.new 
      end_node.name = "結束" 
      end_node.right = element.attributes["right"].gbk  
      end_node.enter = element.attributes["enter"].gbk  
      end_node.x1 = element.attributes["x1"].to_i  
      end_node.x2 = element.attributes["x2"].to_i  
      end_node.y1 = element.attributes["y1"].to_i  
      end_node.y2 = element.attributes["y2"].to_i  
        
      @states << end_node  
    }  
    #解析所有流轉  
    root.elements.each("trasit") {|element|  
      from_name = element.attributes["from"].gbk  
      to_name = element.attributes["to"].gbk  
          
      for state in @states 
        if state.name == from_name  
          from_node = state  
        end 
        if state.name == to_name  
          to_node = state  
        end 
      end         
          
      trasit = Trasit.new(from_node, to_node)  
      trasit.name = element.attributes["name"].gbk  
      trasit.condition = element.attributes["condition"].gbk  
          
      from_node.trasits << trasit  
      to_node.guest_trasits << trasit  
      @trasits << trasit    
    }  
  end 
    
  def start  
    @states[0]  
  end 
    
  def get_state(name)  
    for state in @states 
      return state if state.name == name  
    end 
    nil 
  end 
    
end 

#Flow.rb

require 'rexml/document'
require "State"
require "Trasit"
require "Flow"
require "pp"[SPAN]

include REXML

class Flow
  attr_accessor :name, :publish_time
  attr_reader :trasits, :states
  def initialize(name, xmlstr, publish_time)
    @publish_time = publish_time
    @name = name
   
    #存放所有狀態,包括開始狀態和結束,開始狀態放在第一個,結束狀態放在最后
    @states = Array.new
    @trasits = Array.new
   
    #載入XML文檔
    doc = Document.new(xmlstr)
   
    #開始解析doc文檔
    root = doc.root
   
    #解析開始狀態節點
    root.elements.each("start") {|element|
      start = State.start
      start.name = "開始"
      start.enter = element.attributes["enter"].gbk
      start.leave = element.attributes["leave"].gbk
      start.right = element.attributes["right"].gbk
      start.x1 = element.attributes["x1"].to_i
      start.x2 = element.attributes["x2"].to_i
      start.y1 = element.attributes["y1"].to_i
      start.y2 = element.attributes["y2"].to_i
      @states << start
      break
    }
   
    #解析所有狀態節點
    root.elements.each("state") {|element|
      state = State.new
      state.name = element.attributes["name"].gbk
      state.right = element.attributes["right"].gbk
      state.enter = element.attributes["enter"].gbk
      state.leave = element.attributes["leave"].gbk
      state.x1 = element.attributes["x1"].to_i
      state.x2 = element.attributes["x2"].to_i
      state.y1 = element.attributes["y1"].to_i
      state.y2 = element.attributes["y2"].to_i
      @states << state
    }
   
    #解析結束狀態節點
    root.elements.each("end") {|element|
      end_node = State.new
      end_node.name = "結束"
      end_node.right = element.attributes["right"].gbk
      end_node.enter = element.attributes["enter"].gbk
      end_node.x1 = element.attributes["x1"].to_i
      end_node.x2 = element.attributes["x2"].to_i
      end_node.y1 = element.attributes["y1"].to_i
      end_node.y2 = element.attributes["y2"].to_i
     
      @states << end_node
    }
    #解析所有流轉
    root.elements.each("trasit") {|element|
      from_name = element.attributes["from"].gbk
      to_name = element.attributes["to"].gbk
    
      for state in @states
        if state.name == from_name
          from_node = state
        end
        if state.name == to_name
          to_node = state
        end
      end    
    
      trasit = Trasit.new(from_node, to_node)
      trasit.name = element.attributes["name"].gbk
      trasit.condition = element.attributes["condition"].gbk
    
      from_node.trasits << trasit
      to_node.guest_trasits << trasit
      @trasits << trasit 
    }
  end
 
  def start
    @states[0]
  end
 
  def get_state(name)
    for state in @states
      return state if state.name == name
    end
    nil
  end
 
end[SPAN]

Ruby代碼
#FlowMeta.rb  
 
$LOAD_PATH.unshift(File.dirname(__FILE__))  
 
require "Flow" 
require "EncodeUtil" 
 
class FlowMeta  
  class << self 
    def LoadAllFlows()  
      YtLog.info "loading all workflow..." 
      $Workflows.clear  
      flows = YtwgWorkflow.find(:all)  
      for flow in flows  
        #LoadWorkFlow(flow.name, flow.content.sub!('<?xml version="1.0" encoding="gb2312" ?>', ''))  
        LoadWorkFlow(flow.name, flow.content, flow.publish_time)  
      end 
    end 
          
    def LoadWorkFlow(name, str, publish_time=Time.new)  
      YtLog.info name  
      $Workflows[name] = Flow.new(name, str, publish_time)  
    end 
          
    def Remove(name)  
      $Workflows.delete(name)  
    end 
  end 
end 

#FlowMeta.rb

$LOAD_PATH.unshift(File.dirname(__FILE__))

require "Flow"
require "EncodeUtil"

class FlowMeta
  class << self
    def LoadAllFlows()
      YtLog.info "loading all workflow..."
      $Workflows.clear
      flows = YtwgWorkflow.find(:all)
      for flow in flows
        #LoadWorkFlow(flow.name, flow.content.sub!('<?xml version="1.0" encoding="gb2312" ?>', ''))
        LoadWorkFlow(flow.name, flow.content, flow.publish_time)
      end
    end
  
    def LoadWorkFlow(name, str, publish_time=Time.new)
      YtLog.info name
      $Workflows[name] = Flow.new(name, str, publish_time)
    end
  
    def Remove(name)
      $Workflows.delete(name)
    end
  end
end

Ruby代碼
#State.rb  
 
##工作流中的狀態  
 
require "Trasit" 
class State  
  attr_accessor :name, :leave, :enter, :right, :trasits, :guest_trasits 
  attr_accessor :x1, :x2, :y1, :y2 
  def initialize  
    #從此狀態出發的流轉  
    @trasits = Array.new 
      
    #從其他狀態到此狀態的流轉  
    @guest_trasits = Array.new 
  end 
      
  def trasits  
    @trasits 
  end 
      
  def add_trasit(trasit)  
    @trasits << trasit  
  end 
    
  def add_guest_trasit(trasit)  
    @guest_trasits << trasit  
  end 
      
  class << self 
    def start  
      start = State.new 
      start.name = "開始" 
      start  
    end 
  end 
end 

#State.rb

##工作流中的狀態

require "Trasit"
class State
  attr_accessor :name, :leave, :enter, :right, :trasits, :guest_trasits
  attr_accessor :x1, :x2, :y1, :y2
  def initialize
    #從此狀態出發的流轉
    @trasits = Array.new
   
    #從其他狀態到此狀態的流轉
    @guest_trasits = Array.new
  end
 
  def trasits
    @trasits
  end
 
  def add_trasit(trasit)
    @trasits << trasit
  end
 
  def add_guest_trasit(trasit)
    @guest_trasits << trasit
  end
 
  class << self
    def start
      start = State.new
      start.name = "開始"
      start
    end
  end
end

Ruby代碼
#Trasit.rb  
 
class Trasit  
    attr_accessor :condition, :name, :from, :to 
      
    #新建流轉類,from,to均為State類對象  
    def initialize(from, to)  
        @from = from  
        @to = to  
    end 
end 

#Trasit.rb

class Trasit
 attr_accessor :condition, :name, :from, :to
 
 #新建流轉類,from,to均為State類對象
 def initialize(from, to)
  @from = from
  @to = to
 end
end

  OK,解析工作流的任務就算完成了,250行Ruby代碼,一個小型的,可定制化程度高的工作流引擎就算是完成了。下面我們就看怎么使用這個工作流了。

  工作流引擎完成以后下面自然而然就會想到用戶在每個流程點上看到的表單界面從何而來?對于這個功能,我專門寫了表單設計器和表單解析引擎,表單解析引擎可將xml格式的表單翻譯為html格式的表單。這個表單組件更為復雜,超出了本討論的范圍,暫且先不說了。[SPAN]

  下面說一下數據庫表,為了使用這個工作流引擎需要建立3張表:

Sql代碼
//工作流表  
CREATE TABLE `ytwg_workflow` (  
  `id` int(11) NOT NULL auto_increment,  
  `name` varchar(100) default NULL,          //工作流名稱  
  `content` longtext,                                   //工作流內容,設計器保存的xml文件  
  `publish_time` datetime default NULL,     //發布時間  
  `formtable` varchar(30) default NULL,      //表單數據存放的表格,每個工作流建立后會單獨建立數據庫表,存放表單數據  
  `position` int(11) default NULL,                 //排序位置  
  `reserved1` varchar(100) default NULL,      
  `reserved2` varchar(100) default NULL,  
  `reserved3` varchar(100) default NULL,  
  `reserved4` varchar(100) default NULL,  
  `reserved5` varchar(100) default NULL,  
  `reserved6` varchar(100) default NULL,  
  PRIMARY KEY  (`id`)  
)   
 
//工作流狀態表單界面表  
CREATE TABLE `ytwg_stateinterface` (  
  `id` int(11) NOT NULL auto_increment,  
  `flowid` int(11) default NULL,                     //工作流id  
  `name` varchar(100) default NULL,            //狀態名稱  
  `content` longtext,                                     //表單,表單設計器保存的xml文件  
  `publish_time` datetime default NULL,       //發布時間  
  `reserved1` varchar(100) default NULL,       
  `reserved2` varchar(100) default NULL,  
  `reserved3` varchar(100) default NULL,  
  `reserved4` varchar(100) default NULL,  
  `reserved5` varchar(100) default NULL,  
  `reserved6` varchar(100) default NULL,  
  PRIMARY KEY  (`id`)  
)   
 
//表單處理記錄表  
CREATE TABLE `ytwg_formhistory` (  
  `id` int(11) NOT NULL auto_increment,  
  `userid` int(11) default NULL,                    //用戶id  
  `flowid` int(11) default NULL,                     //工作流id  
  `formid` int(11) default NULL,                     //表單id  
  `process_time` datetime default NULL,      //處理時間  
  PRIMARY KEY  (`id`)  
)  

//工作流表
CREATE TABLE `ytwg_workflow` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(100) default NULL,          //工作流名稱
  `content` longtext,                                   //工作流內容,設計器保存的xml文件
  `publish_time` datetime default NULL,     //發布時間
  `formtable` varchar(30) default NULL,      //表單數據存放的表格,每個工作流建立后會單獨建立數據庫表,存放表單數據
  `position` int(11) default NULL,                 //排序位置
  `reserved1` varchar(100) default NULL,   
  `reserved2` varchar(100) default NULL,
  `reserved3` varchar(100) default NULL,
  `reserved4` varchar(100) default NULL,
  `reserved5` varchar(100) default NULL,
  `reserved6` varchar(100) default NULL,
  PRIMARY KEY  (`id`)
)

//工作流狀態表單界面表
CREATE TABLE `ytwg_stateinterface` (
  `id` int(11) NOT NULL auto_increment,
  `flowid` int(11) default NULL,                     //工作流id
  `name` varchar(100) default NULL,            //狀態名稱
  `content` longtext,                                     //表單,表單設計器保存的xml文件
  `publish_time` datetime default NULL,       //發布時間
  `reserved1` varchar(100) default NULL,    
  `reserved2` varchar(100) default NULL,
  `reserved3` varchar(100) default NULL,
  `reserved4` varchar(100) default NULL,
  `reserved5` varchar(100) default NULL,
  `reserved6` varchar(100) default NULL,
  PRIMARY KEY  (`id`)
)

//表單處理記錄表
CREATE TABLE `ytwg_formhistory` (
  `id` int(11) NOT NULL auto_increment,
  `userid` int(11) default NULL,                    //用戶id
  `flowid` int(11) default NULL,                     //工作流id
  `formid` int(11) default NULL,                     //表單id
  `process_time` datetime default NULL,      //處理時間
  PRIMARY KEY  (`id`)
)

  每發布一個工作流后,跟著要為這個工作流動態創建數據庫表,存放表單數據。我是通過向這個工作流發布一個表單模板來動態創建表的。

  下面看如何使用工作流:

Ruby代碼
#發布工作流    
def create  
    stream = params[:ytwg_workflow][:content]  
    content = stream.read  
    name = stream.original_filename[0, stream.original_filename.index(".")]  
    if YtwgWorkflow.find(:all, :conditions=>"name='#{name}'").size > 0  
      flash[:error] = "存在同名工作流,上傳失敗" 
      render :action => 'new' 
      return 
    end 
      
    @ytwg_workflow = YtwgWorkflow.new()  
    @ytwg_workflow.name = name  
    begin 
      @ytwg_workflow.content = content  
    rescue 
      flash[:error] = "上傳文件非法" 
      render :action => 'new' 
    end 
    @ytwg_workflow.publish_time = Time.new 
    if @ytwg_workflow.save  
      FlowMeta.LoadWorkFlow(@ytwg_workflow.name, @ytwg_workflow.content.sub!('<?xml version="1.0" encoding="gb2312" ?>', ''))  
      flash[:notice] = '添加工作流成功' 
      redirect_to :action => 'list' 
    else 
      flash[:error] = "添加工作流失敗" 
      render :action => 'new' 
    end 
  end 
 
  #上傳表定義模板,根據這個表單動態生成數據庫表  
  def upload_formtable  
    stream = params[:content]  
    content = stream.read  
    helper = XMLHelper.new 
    helper.ReadFromString(content)  
    formtable = helper.tables[0]  
    if !formtable  
      flash[:notice] = "上傳文件格式錯誤" 
      redirect_to :action=>"listinterface" 
      return 
    end 
    conn = ActiveRecord::Base.connection  
    conn.create_table "ytwg_#{formtable.GetTableID}", :primary_key=>:id do |t|  
      t.column "userid", :integer         #流程發起人的id  
      t.column "flowid", :integer         #工作流的id  
      Integer(0).upto(formtable.GetRowCount()-1) do |row|  
        next if formtable.IsEmptyRow(row)  
        Integer(0).upto(formtable.GetColumnCount()-1) do |col|  
          next if formtable.IsEmptyCol(col)  
          cell = formtable.GetCell(row, col)  
          next if !cell.IsStore || !cell.IsEffective  
          next if formtable.GetCellDBFieldName(row, col).downcase == "id" 
               
          t.column "_state", :string, :limit=>30  
          t.column "_madetime", :datetime 
          t.column "_lastprocesstime", :datetime 
          if cell.GetDataType == 1    #CCell.CtNumeric  
            t.column formtable.GetCellDBFieldName(row, col).downcase, :float 
          elsif cell.GetDataType == 0    #CCell.CtText                 
            if cell.IsCheckWidth()  
              t.column formtable.GetCellDBFieldName(row, col).downcase, :string, {:limit=>cell.GetTextWidth}  
            else 
              t.column formtable.GetCellDBFieldName(row, col).downcase, :string, {:limit=>100}  
            end       
          elsif cell.GetDataType == 3 #CCell.CtDate  
            t.column formtable.GetCellDBFieldName(row, col).downcase, :datetime 
          end              
        end 
      end 
    end 
      
    flow = YtwgWorkflow.find(params[:id])  
    flow.formtable = formtable.GetTableID  
    flow.save  
      
    flash[:notice] = "建表成功" 
    redirect_to :action=>"listinterface" 
  end 
 
  #上傳狀態節點的表單界面  
  def uploadinterface  
    stream = params[:content]  
    content = stream.read  
      
    interfaces = YtwgStateinterface.find(:all, :conditions=>"flowid = #{params[:id]} and name = '#{params[:name]}'")  
    if interfaces.size > 0  
      interface = interfaces[0]  
      interface.publish_time = Time.new 
    else 
      interface = YtwgStateinterface.new 
      interface.flowid = params[:id]  
      interface.name = params[:name]  
      interface.publish_time = Time.new 
    end 
    interface.content = content  #EncodeUtil.change("UTF-8", "GB2312", content)  
    interface.save  
    flash[:notice] = "上傳狀態界面成功" 
    redirect_to :action=>"listinterface" 
  end 
 
  #用戶點擊某一工作流連接后,查看自己已經發起的工作流。  
  def show_form  
    @flow = YtwgWorkflow.find(params[:flowid])  
    YtwgForm.set_table_name("ytwg_" + @flow.formtable)  
    YtwgForm.reset_column_information()   
    form = YtwgForm.find(params[:formid])  
       
    interfaces = YtwgStateinterface.find(:all, :conditions=>"flowid=#{params[:flowid]} and name='#{form._state.split(',')[0]}'")  
    if interfaces.size > 0  
      helper = XMLHelper.new 
      helper.ReadFromString(interfaces[0].content)  
      @style = helper.StyleToHTML(helper.tables[0])  
      @html = helper.TableToEditHTML(helper.tables[0], helper.dictionFactory,   
        {:record=>form, :encoding=>"gb2312"})  
      @historys = YtwgFormhistory.find(:all, :conditions=>"flowid=#{params[:flowid]} and formid = #{params[:formid]}")  
    else 
      render :text=>"沒有上傳工作流界面" 
    end 
  end 
 
  #用戶發起或者審批一個表單  
  def write_form  
    @flow = YtwgWorkflow.find(params[:flowid])  
    YtwgForm.set_table_name("ytwg_" + @flow.formtable)  
    YtwgForm.reset_column_information()   
 
    if params[:formid]  
      form_record = YtwgForm.find(params[:formid])  
      state_name = form_record._state  
    else 
      form_record = YtwgForm.new 
      form_record._state = '開始' 
      state_name = form_record._state  
    end 
      
    states = []  
    for state in form_record._state.split(',')  
      states << state if checkright(state)  
    end 
    if states.size > 0  
      state_name = states[0]  
    else 
      state_name = '開始' 
    end 
 
    process = FlowProcess.new($Workflows[@flow.name], form_record, state_name)  
    process.user = session[:user]  
    process.signal_enter  
      
    interfaces = YtwgStateinterface.find(:all, :conditions=>"flowid=#{@flow.id} and name = '#{state_name}'")  
    if interfaces.size ==0  
      render :text=>"沒有上傳開始界面" 
      return 
    end 
    @start_interface = interfaces[0]  
    helper = XMLHelper.new 
    helper.ReadFromString(@start_interface.content)  
    @style = helper.StyleToHTML(helper.tables[0])  
    @html = helper.TableToEditHTML(helper.tables[0], helper.dictionFactory,   
      {:record=>form_record,:encoding=>"gb2312", :script=>helper.script})  
    @historys = YtwgFormhistory.find(:all, :conditions=>"flowid=#{params[:flowid]} and formid = #{params[:formid]}") if params[:formid]  
  end 
 
  #用戶寫完一個表單后點擊提交  
  def update_form  
    @flow = YtwgWorkflow.find(params[:id])  
    YtwgForm.set_table_name("ytwg_" + @flow.formtable)  
    YtwgForm.reset_column_information()   
    if params[:formid]  
      form = YtwgForm.find(params[:formid])  
      form.update_attributes(params[@flow.formtable])  
        
      states = []  
      for state in form._state.split(',')  
        states << state if check_state_right(@flow.name, state)  
      end 
      state_name = states[0]  
    else 
      form = YtwgForm.new(params[@flow.formtable])  
      form._madetime = Time.new 
      form._state = '開始' 
      state_name = form._state  
      form.userid = session[:user].id  
      form.flowid = @flow.id  
    end 
 
    form._lastprocesstime = Time.new      
    process = FlowProcess.new($Workflows[@flow.name], form, state_name)  
    process.user = session[:user]  
    process.signal_leave  
      
    history = YtwgFormhistory.new 
    history.userid = session[:user].id  
    history.flowid = @flow.id  
    history.formid = form.id  
    history.process_time = Time.new 
    history.save  
    redirect_to :action=>'myform', :id=>params[:id]  
  end 
 
 #等待我處理的流程  
  def show_waiting_form  
    @forms = get_wait_form(params[:id])  
    render :layout=>false 
  end 
 
 #獲得某一種單據中等待當前登陸者審批的  
  def get_wait_form(flowid)  
    forms = []  
    flow = YtwgWorkflow.find(flowid)  
    if !flow.formtable || flow.formtable.size==0  
      return forms  
    end 
    YtwgForm.set_table_name("ytwg_" + flow.formtable)  
    YtwgForm.reset_column_information()   
    for state in $Workflows[flow.name].states  
      next if state.name == "結束" 
        
      conditions = []  
      conditions << "_state='#{state.name}'" 
        
      #如果可以從多個狀態轉移到這個狀態,則等待所有狀態都執行完此狀態才可以執行  
      if state.guest_trasits.size == 1      #只可以從一個狀態轉到這里  
        conditions << " _state like '%,#{state.name}'" 
        conditions << "_state like '#{state.name},%'" 
      end 
 
      if state.right == "領導" 
        all_forms = YtwgForm.find(:all, :conditions=>conditions.join(' or '), :order=>"id desc")  
        for form in all_forms  
          forms << form if YtwgUser.find(form.userid).department.leader_id == session[:user].id rescue nil 
        end 
      else 
        for right in state.right.split(',')  
          if checkright(right)  
            forms += YtwgForm.find(:all, :conditions=>conditions.join(' or '), :order=>"id desc")  
          end 
        end 
      end 
    end 
    forms.uniq!  
    return forms  
  end 

#發布工作流 
def create
    stream = params[:ytwg_workflow][:content]
    content = stream.read
    name = stream.original_filename[0, stream.original_filename.index(".")]
    if YtwgWorkflow.find(:all, :conditions=>"name='#{name}'").size > 0
      flash[:error] = "存在同名工作流,上傳失敗"
      render :action => 'new'
      return
    end
   
    @ytwg_workflow = YtwgWorkflow.new()
    @ytwg_workflow.name = name
    begin
      @ytwg_workflow.content = content
    rescue
      flash[:error] = "上傳文件非法"
      render :action => 'new'
    end
    @ytwg_workflow.publish_time = Time.new
    if @ytwg_workflow.save
      FlowMeta.LoadWorkFlow(@ytwg_workflow.name, @ytwg_workflow.content.sub!('<?xml version="1.0" encoding="gb2312" ?>', ''))
      flash[:notice] = '添加工作流成功'
      redirect_to :action => 'list'
    else
      flash[:error] = "添加工作流失敗"
      render :action => 'new'
    end
  end

  #上傳表定義模板,根據這個表單動態生成數據庫表
  def upload_formtable
    stream = params[:content]
    content = stream.read
    helper = XMLHelper.new
    helper.ReadFromString(content)
    formtable = helper.tables[0]
    if !formtable
      flash[:notice] = "上傳文件格式錯誤"
      redirect_to :action=>"listinterface"
      return
    end
    conn = ActiveRecord::Base.connection
    conn.create_table "ytwg_#{formtable.GetTableID}", :primary_key=>:id do |t|
      t.column "userid", :integer         #流程發起人的id
      t.column "flowid", :integer         #工作流的id
      Integer(0).upto(formtable.GetRowCount()-1) do |row|
        next if formtable.IsEmptyRow(row)
        Integer(0).upto(formtable.GetColumnCount()-1) do |col|
          next if formtable.IsEmptyCol(col)
          cell = formtable.GetCell(row, col)
          next if !cell.IsStore || !cell.IsEffective
          next if formtable.GetCellDBFieldName(row, col).downcase == "id"
         
          t.column "_state", :string, :limit=>30
          t.column "_madetime", :datetime
          t.column "_lastprocesstime", :datetime
          if cell.GetDataType == 1    #CCell.CtNumeric
            t.column formtable.GetCellDBFieldName(row, col).downcase, :float
          elsif cell.GetDataType == 0    #CCell.CtText              
            if cell.IsCheckWidth()
              t.column formtable.GetCellDBFieldName(row, col).downcase, :string, {:limit=>cell.GetTextWidth}
            else
              t.column formtable.GetCellDBFieldName(row, col).downcase, :string, {:limit=>100}
            end    
          elsif cell.GetDataType == 3 #CCell.CtDate
            t.column formtable.GetCellDBFieldName(row, col).downcase, :datetime
          end          
        end
      end
    end
   
    flow = YtwgWorkflow.find(params[:id])
    flow.formtable = formtable.GetTableID
    flow.save
   
    flash[:notice] = "建表成功"
    redirect_to :action=>"listinterface"
  end[SPAN]

  #上傳狀態節點的表單界面
  def uploadinterface
    stream = params[:content]
    content = stream.read
   
    interfaces = YtwgStateinterface.find(:all, :conditions=>"flowid = #{params[:id]} and name = '#{params[:name]}'")
    if interfaces.size > 0
      interface = interfaces[0]
      interface.publish_time = Time.new
    else
      interface = YtwgStateinterface.new
      interface.flowid = params[:id]
      interface.name = params[:name]
      interface.publish_time = Time.new
    end
    interface.content = content  #EncodeUtil.change("UTF-8", "GB2312", content)
    interface.save
    flash[:notice] = "上傳狀態界面成功"
    redirect_to :action=>"listinterface"
  end

  #用戶點擊某一工作流連接后,查看自己已經發起的工作流。
  def show_form
    @flow = YtwgWorkflow.find(params[:flowid])
    YtwgForm.set_table_name("ytwg_" + @flow.formtable)
    YtwgForm.reset_column_information()
    form = YtwgForm.find(params[:formid])
    
    interfaces = YtwgStateinterface.find(:all, :conditions=>"flowid=#{params[:flowid]} and name='#{form._state.split(',')[0]}'")
    if interfaces.size > 0
      helper = XMLHelper.new
      helper.ReadFromString(interfaces[0].content)
      @style = helper.StyleToHTML(helper.tables[0])
      @html = helper.TableToEditHTML(helper.tables[0], helper.dictionFactory,
        {:record=>form, :encoding=>"gb2312"})
      @historys = YtwgFormhistory.find(:all, :conditions=>"flowid=#{params[:flowid]} and formid = #{params[:formid]}")
    else
      render :text=>"沒有上傳工作流界面"
    end
  end

  #用戶發起或者審批一個表單
  def write_form
    @flow = YtwgWorkflow.find(params[:flowid])
    YtwgForm.set_table_name("ytwg_" + @flow.formtable)
 &nbsp;  YtwgForm.reset_column_information()

    if params[:formid]
      form_record = YtwgForm.find(params[:formid])
      state_name = form_record._state
    else
      form_record = YtwgForm.new
      form_record._state = '開始'
      state_name = form_record._state
    end
   
    states = []
    for state in form_record._state.split(',')
      states << state if checkright(state)
    end
    if states.size > 0
      state_name = states[0]
    else
      state_name = '開始'
    end

    process = FlowProcess.new($Workflows[@flow.name], form_record, state_name)
    process.user = session[:user]
    process.signal_enter
   
    interfaces = YtwgStateinterface.find(:all, :conditions=>"flowid=#{@flow.id} and name = '#{state_name}'")
    if interfaces.size ==0
      render :text=>"沒有上傳開始界面"
      return
    end
    @start_interface = interfaces[0]
    helper = XMLHelper.new
    helper.ReadFromString(@start_interface.content)
    @style = helper.StyleToHTML(helper.tables[0])
    @html = helper.TableToEditHTML(helper.tables[0], helper.dictionFactory,
      {:record=>form_record,:encoding=>"gb2312", :script=>helper.script})
    @historys = YtwgFormhistory.find(:all, :conditions=>"flowid=#{params[:flowid]} and formid = #{params[:formid]}") if params[:formid]
  end

  #用戶寫完一個表單后點擊提交
  def update_form
    @flow = YtwgWorkflow.find(params[:id])
    YtwgForm.set_table_name("ytwg_" + @flow.formtable)
    YtwgForm.reset_column_information()
    if params[:formid]
      form = YtwgForm.find(params[:formid])
      form.update_attributes(params[@flow.formtable])
     
      states = []
      for state in form._state.split(',')
        states << state if check_state_right(@flow.name, state)
      end
      state_name = states[0]
    else
      form = YtwgForm.new(params[@flow.formtable])
      form._madetime = Time.new
      form._state = '開始'
      state_name = form._state
      form.userid = session[:user].id
      form.flowid = @flow.id
    end

    form._lastprocesstime = Time.new   
    process = FlowProcess.new($Workflows[@flow.name], form, state_name)
    process.user = session[:user]
    process.signal_leave
   
    history = YtwgFormhistory.new
    history.userid = session[:user].id
    history.flowid = @flow.id
    history.formid = form.id
    history.process_time = Time.new
    history.save
    redirect_to :action=>'myform', :id=>params[:id]
  end

 #等待我處理的流程
  def show_waiting_form
    @forms = get_wait_form(params[:id])
    render :layout=>false
  end

 #獲得某一種單據中等待當前登陸者審批的
  def get_wait_form(flowid)
    forms = []
    flow = YtwgWorkflow.find(flowid)
    if !flow.formtable || flow.formtable.size==0
      return forms
    end
    YtwgForm.set_table_name("ytwg_" + flow.formtable)
    YtwgForm.reset_column_information()
    for state in $Workflows[flow.name].states
      next if state.name == "結束"
     
      conditions = []
      conditions << "_state='#{state.name}'"
     
      #如果可以從多個狀態轉移到這個狀態,則等待所有狀態都執行完此狀態才可以執行
      if state.guest_trasits.size == 1      #只可以從一個狀態轉到這里
        conditions << " _state like '%,#{state.name}'"
        conditions << "_state like '#{state.name},%'"
      end

      if state.right == "領導"
        all_forms = YtwgForm.find(:all, :conditions=>conditions.join(' or '), :order=>"id desc")
        for form in all_forms
          forms << form if YtwgUser.find(form.userid).department.leader_id == session[:user].id rescue nil
        end
      else
        for right in state.right.split(',')
          if checkright(right)
            forms += YtwgForm.find(:all, :conditions=>conditions.join(' or '), :order=>"id desc")
          end
        end
      end
    end
    forms.uniq!
    return forms
  end

有了上面這些最核心的函數后,如何使用這個工作流基本就算明白了。除此之外還有許多附加的小功能需要去實現,比如導出Excel,導出PDF,在網頁上展示工作流的流程圖(我用VML實現)。以下是請假登記表的表單顯示界面:

點擊查看大圖

  這個工作流的應用現狀:

  目前這個工作流還沒有商用,只有一個應用場景。前幾個月我們公司買了一套金和OA,在銷售員滿嘴跑火車的吹噓下我們經理花9800買了,后來實施的時候發現金和的工作流根本無法使用。一個簡單的請假申請單都無法實現自定義表單和流程,無奈之下我基于我的工作流組件,快速開發了一套OA,幾天之后就上線,然后邊用邊完善,一個月以后就很少再動了。目前公司對這套OA還是比較滿意的。雖然我的OA比國內的優秀OA產品還有很大差距,但是這套工作流組件至少還是能夠勝任大多數場合,對于尚不能滿足的場合還可以靈活擴展。


標簽:

本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn

文章轉載自:JavaEye

為你推薦

  • 推薦視頻
  • 推薦活動
  • 推薦產品
  • 推薦文章
  • 慧都慧問
相關產品
控件
  • 產品功能:工作流
  • 源 碼:非開源
  • 產品編號:10581
  • 當前版本:v3.1 [銷售以商家最新版為準,如需其他版本,請來電咨詢]
  • 開 發 商: ASPOSE 正式授權
  • ">Aspose.Workflow

    提供了一個功能強大的工作流引擎以及一整套符合業界標準的工作流對象

    控件
  • 產品功能:工作流
  • 源 碼:非開源
  • 產品編號:10721
  • 當前版本:v2004 r2 [銷售以商家最新版為準,如需其他版本,請來電咨詢]
  • 開 發 商: Schneider Electric Software, LLC 正式授權
  • ">Skelta Workflow.NET

    建立在.NET、XML以及Web services技術之上的業務流程管理工作流軟件,同時也是世界上第一個可嵌入的工作流引擎

    控件
  • 產品功能:UI界面
  • 源 碼:非開源
  • 產品編號:11483
  • 當前版本:v2.15 [銷售以商家最新版為準,如需其他版本,請來電咨詢]
  • 開 發 商: tmssoftware 正式授權
  • ">TMS Workflow Studio

    一個Delphi/ C ++ Builder VCL框架的業務流程管理(BPM)控件,為你的應用程序添加工作流和BPM功能

    控件
  • 產品功能:工作流
  • 源 碼:非開源
  • 產品編號:11878
  • 當前版本:2014 R2 SP2 [銷售以商家最新版為準,如需其他版本,請來電咨詢]
  • 開 發 商: Schneider Electric Software, LLC 正式授權
  • ">Wonderware Skelta BPM

    全球第一且功能強大的.NET企業級業務流程管理和高級工作流解決方案

    掃碼咨詢


    添加微信 立即咨詢

    電話咨詢

    客服熱線
    023-68661681

    TOP
    国精产品一区一区三区 | 2021日日摸夜夜添夜夜添影院 | 最近2019免费中文字幕视频三 | 欧美人又长又大又粗无码视频一区 | 国产黄毛片 | 九九热热九九 | 不卡高清AV手机在线观看 | 亚洲九九九 | 少妇做爰又色又紧夜视频 | 欧美 亚洲 有码中文字幕 | 色视频免费观看 | 四虎影视最新的2024版地址 | 欧美综合自拍亚洲综合图 | 91精品国产免费青青碰在线观看 | 精品国产人妻精品 | 中国ZLJZLJZLJZLJ精品 | 日本黄页网 | 午夜福利小视频400 午夜副利电影手机高清在线直播app下载 | 婷婷五月色吧 | 特级毛片A片久久久久久 | 六月丁香婷婷综合 | 久久天天躁狠狠躁夜夜躁2014 | 国产精品情侣自拍 | 精品无人区一区二区三区 | 色吧网| 日韩欧美 亚洲视频 | 羞羞答答.NT视频在线观看 | 蝌蚪网在线视频 | 免费黄色电影观看 | 98久久人妻少妇激情啪啪 | 狠狠色噜噜狠狠狠狠888奇米 | 艳妇臀荡乳欲伦岳TXT免费下载 | 青草草在线视频 | 欧美精品一卡2卡3卡4卡乱码 | 国产激情无码激情A片免费软件 | jizz孕妇孕交 | 日韩不卡手机视频在线观看 | 国产成在线观看免费视频 | 亚洲 校园 欧美 国产 另类 | 国产三级级在线观看大学生 | 中国黄色网址大全 | 国产午夜精品AV一区二区麻豆 | 久久成年人视频 | 丁香激情综合 | 国产精品V无码A片在线看 | 中文字幕一区二区三区在线观看 | 麻豆映画传媒新剧免费观看 | 亚洲精品无码成人AAA片 | 国产男人午夜视频在线观看 | 一卡二卡国产3卡4卡乱码 | 色综合五月激情综合色一区 | 欧美视频第一区 | 色播视频网站 | 开心色播网网址 | 无套内谢少妇毛片A片樱花 无套内谢孕妇毛片免费看 无修无遮h韩漫视频网站 | 黄色在线网| 色久久好 | 午夜人妻无码AV一区二区 | 欲求不満の人妻松下纱荣子 | 亚洲免费一区 | 欧美 亚洲 另类 综合网 | 666夜色666夜色国产免费看 | 一本久道久久综合婷婷五月 | 父皇轻点插好疼H限 | 国产成人久久婷婷精品流白浆 | 欧美日本综合一区二区三区 | 国产亚洲精品久久精品6 | 欧美精品XXXXBBBB | 男女又黄又刺激B片免费网站 | 日本高清无卡码一区二区久久 | 中文字幕一区二区三区在线观看 | 被教官按在寝室狂到腿软视频 | 欧美另类人妖 | 一日本道不卡高清a无码 | 欧美理伦视频 | 中文字幕国产一区 | 精品福利app导航 | 狠狠色狠狠色综合日日91app | 色国产在线 | 思思久久99热只有频精品66 | 一级一毛片a级毛片 | 校园刺激全黄H全肉细节文 校园激情人妻古典武侠 | 亚洲AV永久综合在线观看尤物 | 亚洲免费人成 久久 | 欧美成人亚洲国产精品 | 肥老熟妇伦子伦456视频 | 亚洲第一黄色网址 | 国产无遮挡又黄又爽免费网站 | 五月婷婷六月爱 | 全国精品影院 | 免费看美女被靠的网站 | 91网站视频在线观看 | 国产女人成人精品视频 | 国产91久久精品一区二区 | 欧美日韩另类在线观看视频 | 婷婷五月在线视频 | 久久国产精品99国产精 | 国产亚洲精品久久久久的角色 | 久久国产AVJUST麻豆 | www视频在线观看天堂 | 亚洲精品欧美精品中文字幕 | 免费国产精品丝袜 | 小荡货好紧好爽奶头好大视频网站 | 亚洲m男在线中文字幕 | 欧美AAAAAA级午夜福利视频 | 依依社区人妻 | 无翼乌之全彩爆乳口工不知火舞 | 妻子的背叛免费看 | 91在线一区二区三区 | 国产一级做a爰片久久毛片男 | 97久久伊人精品影院 | 蝌蚪在线视频 | WWW亚洲精品久久久乳 | 日韩伦理电影 | 波多野结衣99 | 一本色道在线久88在线观看片 | 国内精品久久久久久网站 | 中国少妇内射XXXHD | 欲妇放荡叫床小说 | 日韩成人免费在线 | 午夜久久影院 | 天天插狠狠干 | 免费国产a国产片高清不卡 免费观看一级欧美在线视频 | 2022av视频| 色六月婷婷亚洲婷婷六月 | 色情无码WWW视频无码小说 | 成人网站免费观看 | 成年人深夜福利 | 精品一区二区三区四区五区六区 | 日韩经典欧美一区二区三区 | 欧美日本一二三区 | 国产精品免费综合一区视频 | 四虎影视www四虎免费 | 日韩人妻无码精品系列 | 在线观看黄网视频免费播放 | 亚洲色土 | 精品人妻无码一区二区三区手机版 | 国产免费不卡v片在线观看 国产美女一级做视频爱 | 91精品丝袜 | 国产成人精品综合 | 日本免费一区视频 | 真实国产乱子伦露脸 | 波多野结衣dvd在线播放 | 国产无套内射又大又猛又粗又爽 | 午夜性做爰电影 | 松岛枫 qvod 四四房播播 | 上司揉捏人妻丰满双乳电影 | 王瑞儿bt种子 | 国产亚洲精品免费 | 7723日本电影免费观看完整版 | 日本精品巨爆乳无码大乳巨 | 51啪啪| 免费国产黄色片 | 91制片厂果冻传媒公司麻豆 | 欧美日韩无 | 成人国内精品久久久久影院 | 美女扒开胸罩露出奶头的动态图片 | 伊人网综合 | 欧美色妞网 | 丝瓜APP下载安装无限绿巨人 | 免费的性L交A片Y | 在线观看免费播放网址成人 | 男女无遮挡猛进猛出免费观看视频 | 97色情在线观看免费高清 | 亚洲国色天香卡2卡3卡4 | 国产在线视频区 | 东日韩二三区 | 国产亚洲精品hd网站 | 神兵小将第一季免费观看 | 国产永久在线观看 | 啊灬啊灬啊灬快灬A片免费直拍 | 亚洲午夜在线视频 | 99久久久国产精品免费牛牛四川 | 亚洲v在线| 免费AA片少妇人AA片直播 | 狂躁美女大BBBBBB视频1 | 四虎最新紧急更新地址 | 亚1州区2区3区4区产品乱码2021 | 看三d大片.| 2018最新午夜在线视频 | 亚洲人成一区二区不卡 | 欧美一级欧美一级高清 | 无人在线观看免费高清直播视频 | 草草视频免费在线观看 | uzumakikushina玖辛奈本子 | 图片区 日韩 欧美 亚洲 | 成熟妇人A片免费看网站 | 女18一级大黄毛片免费女人 | 搞黄网站免费看 | 亚洲AV无码男男A片在线观看 | 亚洲精品久久久久久成人 | 国产精品久久久亚洲第一牛牛 | 亚洲福利天堂 | 国产AV高清怡春院 | 春色校园亚洲综合小说 | 成人A片产无码免费奶头小说 | 在线天堂最新版资源 | 九九精品视频一区二区三区 | 日本黄色三级视频 | 一个人看的片BD高清动漫 | 成人午夜视频精品一区 | 欧洲色情大片啪啪免费观看 | 自拍视频综合在线精品 | 五月丁香国产在线视频 | 狠狠色狠狠色综合日日五 | 一区二区三区四区在线播放 | 亚洲精品久久无码AV片动漫网站 | 亚洲国产成人九九综合 | 免费的好黄的漫画 | 国产激情在线观看 | 五月色综合无码一区二区三区 | 无码日本精品一区二区三 | 日本香港三级和澳门三级 | 欧美日韩一线 | 婷停五月深爱五月 | 黄色三级网 | 中文字幕日本一区 | 国产精品成人久久久 | xxxxxbbbbb欧美性极品 | 亚洲欧美日本国产综合在线 | 天天黄色| 99看视频| 岛国大片在线播放高清 | 亚洲色图欧美激情 | 国产一国产一级毛片古装 | 久久久精品免费 | 欧美视频一区在线 | 国产成人久久精品推最新 | 涩涩的网站图片 | 亚洲精品无码一区专区国产 | 国产精品自产拍在线观看中文 | 国产日韩精品欧美一区喷水 | 天天操天天干天天摸 | 亚洲天堂资源网 | 免费一级欧美大片视频在线 | 色窝窝华人社区 | 日韩精品视频在线观看免费 | AV国产乱码一区二区三视频 | 亚洲国产精品日韩一线满 | 久久影城 | 色欲AV亚洲永久无码精品麻豆 | 亚洲日本一期二期三期精华液 | 婷婷电影网 | 韩国和日本免费不卡在线V 韩国精品AV一区二区三区 | 中文字幕在线视频播放 | 国内精品一卡二卡三卡 | 国产又粗又猛又黄又爽A片 国产又粗又猛又爽又黄A片 | 日本免费不卡在线一区二区三区 | 99久久精品免费看国产免费软件 | 精品亚洲日韩国产一二三区 | 久久综合一 | 精品无码人妻一区二区三区国产 | 丁香五月综合缴情综合 | 久久精品AV麻豆 | 97视频资源 | 亚洲精华国产精华精华液网站 | 99国模沟沟茂密的黑森林 | 91精品国产入口 | 国产中文字幕一区 | 色欲AV蜜臀AV在线观看麻豆 | 上课时勃起了女同学帮我口 | 精品3d动漫视频一区在线观看 | 91精品久久久久久久99蜜桃 | 国产人妻一区二区三区色戒乐 | 1769国内精品观看视频 | 窝窝午夜视频 | 天堂精品视频 | 天美传媒 高清 | 宝贝看我是怎么吃你水蜜桃的视频 | 黄色网址视频免费 | 中文字幕无线手机在线 | 国产午夜男女爽爽爽爽爽 | 免费国产成人高清在线网站东京 | 国产在线高清不卡免费播放 | 无翼乌之全彩爆乳口工不知火舞 | 国产乱码一二三区精品 | 国产日韩精品视频无吗 | 亚洲免费视频日本一区二区 | 男同免费视频大全69 | 97蜜桃网| 国产免费看JIZZ视频 | 久久久99精品免费观看精品 | 快播3d肉蒲团 | 亚洲成成品网站源码中国有限 | chinesegay又粗又大短视频 | 99精品久久久久久久免费看蜜月 | 综合自拍亚洲综合图区Av | 无人高清视频免费观看在线下载 | a色网站| 99热久久国产精品这里有 | 1000部做羞羞事禁片免费视频网站 | 免费大片av网站 | 69精品国产久热在线观看 | 日日撸.com| 亚洲精品国产一区二区 | 国产偷亚洲偷欧美偷精品 | 国产一在线 | 免费观看羞羞的事情网站 | 婷婷夜色 | 日本aa大片 | 欧美影片一区二区三区 | 99热这里只有精品8 99热这里只有精品9 | 国产美女视频免费观看的网站 | 动漫在线观看片A免费观看 法国艳妇LARALATEXD | 在线观看国产三级视频 | 国产成人18黄网站在线观看网站 | 天天操天天干天天爽 | 国产亚洲精品资源在线26u | 一区三区在线专区在线 | 国产成人亚洲精品2020 | 久久久这里只有精品加勒比 | 黄色一级网站 | 天天碰夜夜操 | 先锋影音av资源站av | 午夜精品射精入后重之免费观看 | 又色又爽又黄的A片免费看苍井空 | 欧美真人性做爰一二区欧美影院 | 国产精品一区二区三区高清在线 | www.精品在线 | 无码免费一区二区三区免费播放 | 久久er视频| 日本处888xxxx| 2019中文字幕在线 | 国产传媒18精品A片熟女 | 国产福利小视频在线播放观看 | 女人自熨全过程(有声) | 久久视频在线视频观看: | 在线视频福利 | 欧美videos超乳巨大 | 日韩最新视频一区二区三 | 国产亚洲欧美日本一二三本道 | 最后的朋友结局 | 免费永久观看美女视频网站网址 | 91久久香蕉国产线看观看软件 | 欧美极品少妇XXXOOO图片 | 国产婷婷综合在线视频中文 | 宝贝乘把腿张开让我添动态图 | 欧美一道本 | 久久国产中文字幕 | 精品国产国产精2024久久日 | 97精品国产97久久久久久 | jizz在线播放 | 少妇做爰免费视看片 | 亚洲精品v欧美精品动漫精品 | 在线免费自拍 | 成人免费在线视频观看 | 狠狠色噜噜狠狠狠狠2022 | 国产精品99久久久久久人 | 久久精品人妻无码一区二区三区V | 337日本| 三级网站免费 | 国产色情无码永久免费软件 | 午夜福利电影网站鲁片大全 | 久久视频在线视频 | 99精品免费观看 | 99re视频精品全部免费 | 亚洲影视自拍揄拍愉拍 | 日本漫画之吃奶乳漫画 | 制服 丝袜 亚洲 中文 综合 | 国产亚洲产品影市在线产品 | 色交网站| 嫩草欧美曰韩国产大片 | 成人A片动漫无码免费播放 成人A片免费看男人社区 | 欧洲色网站 | 神马影院夜伦鲁鲁片 | 日韩不卡在线观看视频不卡 | 永久黄网站色视频免费观看 | 日韩国产在线播放 | 免费无码又黄又爽又刺激 | 欧美黄区| 站长推荐国产精品视频 | 亚洲VA天堂VA欧美片A在线 | 91亚洲国产成人久久精品网站 | 97色婷婷 | 久久精品人妻无码一区二区三区网 | 日本熟妇人妻另类无码 | 香港三级欧美国产精品 | 国产精品久久久久久日本 | 国产亚洲欧美在线观看三区 | 天天做天天干 | 99re久久| 热re99久久精品国99热 | 麻豆成人AV久久无码精品 | 亚洲综合精品香蕉久久网97 | 国产日韩欧美精品一区二区三区 | 国产精品对白交换视频 | 三级黄色片在线观看 | 日本三级全黄 | 狠狠躁天天躁夜夜躁婷婷 | 日本亚洲高清 | 91视频h| 鲁鲁在线视频 | 日韩高清成人毛片不卡 | 精品国产一区二区三区久久影院 | 欧美成人久久一二三区A片 欧美成人无码A区在线观看免费 | a级欧美| 亚洲欧美强伦一区二区另类 | 欧美日韩亚洲一区二区三区 | 色在线电影| 欧美囗交xx×bbb视频 | 青草青在线免费视频 | 俺去也色五月 | 中文字幕 亚洲 有码 在线 | 亚洲午夜精品在线 | 国产精品久久久久毛片真精品 | 亚洲爆乳精品无码AAA片 | 日韩精品网 | 欧美三级免费网站 | 五月天婷婷精品免费视频 | 九九热热九九 | 久久久日韩成人精品电影 | 亚洲天堂2017手机在线 | WW网站女生福利 | 午夜福利在线电影视频 | 久久综合九色欧美综合狠狠 | 亚洲伊人成色综合网 | 国产免费的又黄又爽又色 | 酒神免费全集观看 | 日本三级韩国三级香港三级网站 | 中文字幕一区在线播放 | 亚洲精品无码成人A片在线虐 | 国产SUV精品一区二区33 | 诱含整夜不拔h1v1 | 最新色网站 | GV无套内射日本帅哥 | 成人在免费视频手机观看网站 | 亚洲AV无码偷拍在线观看 | 熟女人妻久久中文字幕一二区 | 九九九日产 | 自偷自拍亚洲欧美清纯唯美 | 波多野结衣免费在线 | 欧美在线视频一区二区三区 | 国产婷婷综合在线视频中文 | 春色视频一区二区三区 | 草草影院在线观看 | 九一传媒果冻制片厂 | 浴室里强摁做开腿呻吟的漫画 | 热热色原网站 | 亚洲AV在线无码播放毛片浪潮 | 伊人久久综合成人亚洲 | 欧美天堂久久 | 欧日韩美香蕉在线观看 | 搡女人真爽免费视频网站 | 将军野外玩弄公主H文 | 欧美干色| 欧美高清在线视频一区二区 | 男女做爰猛烈啪啪吃奶真人免费 | 精品久久日产国产一二三区 | 欧美一区二区三区精品 | 日本久久精品免视看国产成人 | 国产一级一国产一级毛片 | 久久福利合集精品视频 | 人体内射精一区二区三区 | 在线a级| 久久精品5 | 免费国产一级特黄久久 | 日本后进式猛烈xx00动态图 | 亚洲欧美视频在线观看 | 欧美一卡2卡三卡4卡公司 | 国产亚洲欧美精品永久不卡 | 亚洲精品综合久久 | 在线免费日本 | 色网址大全123 亚洲 | 日本免费一区二区三区a区 日本免费一区二区久久人人澡 | 国产精品久久久久久人妻香蕉 | 日韩aa在线观看 | 中文字幕日本六区小电影 | 免费看男人J放进女人J无遮掩 | 97久久久亚洲综合久久88 | 国产无套内射又大又猛又粗又爽 | 看草逼| 在线观看免费av网站 | 免费啪视频观免费视频 | 国产久操视频 | 综合色桃花久久亚洲 | 诱受H嗯啊巨肉舍友1V1 | 亚洲A片永久精品无码APP | A级成人毛片免费视频高清 a天堂v | 国产极品精频在线观看 | 最近最新2018中文字幕8 | 成人乱码一区二区三区四区 | 亚洲高清台 | 爱婷婷视频在线观看 | 美女被C污黄网站免费观看 美女被抽插舔B到哭内射视频免费 | 偷偷鲁在线影院 | 亚洲AV无码乱码A片无码18禁 | 天上人间影院久久国产 | 色中色最新网站 | 蜜桃MV在线播放免费观看网站 | 色爱区综合激月婷婷激情五月 | 91色在线观看 | 一本到国内在线视观看 | 艳妇臀荡乳欲伦交换在线播放 | 男女生性毛片免费观看 | 欧美一区二区三区精品影视 | 性论坛大全 | 最近中文国语字幕在线播放视频 | 欧洲一卡2卡3卡4卡乱码视频 | 国产探花在线精品一区二区 | 永久免费精品视频 | 中文字幕日本不卡一二三区 | 一级黄色免费观看 | 最近免费字幕高清在线观看 | 日韩欧美精品在线 | 宅女午夜福利免费视频 | 亚洲色无码A片一区二区红樱 | 美国人成毛片在线播放 | 国产成人精品日本亚洲18图 | 日本高清不卡免费 | 日韩一卡2卡3卡4卡乱码网站导航 | 国产波多野结衣中文在线播放 | 国产精品综合AV一区二区国产馆 | 日韩一级不卡 | 色搜网站 | 医生护士一级毛片 | 日本无码中文精品a8198v | 国产成人精品免费久久久久 | 久久三级毛片 | 中日韩精品卡一卡二卡3卡 中日文字字幕乱码视频 | 久久久久久久99精品免费观看 | 大香伊人蕉在线观 | 日韩欧美精品一区二区三区 | 精品自拍视频在线观看 | 国产亚洲欧美日韩v在线 | 久久三级国产 | 国产精品久久久久久久hd | av首页| 亚洲中文字幕无码专区日本苍井空 | 少妇无码吹潮久久精品AV网站 | 国产午夜精品一区理论片飘花 | 国产精品自拍亚洲 | 日本高清无日本高清视频 | 日韩欧美中国a v | 中文字幕国产日韩 | 波多野结衣高清在线播放 | 日本a在线观看 | 亚洲精品久久精品一区二区 | 欧美老少欢xxx | 青青草国产线观看 | 在线看黄页| 88av 在线| 免费大片黄在线观看视频 | 一级视频在线免费观看 | 亚洲天天综合网 | 久久国产天堂福利天堂 | 日本丰满大乳乳液 | 狠狠色丁香久久婷婷综合_中 | 亚洲人成网77777色在线播放 | 久久精品国产999久久久 | 亚洲AV国产精品无码A片 | 一区二区久久久久草草 | 欧美又粗又大XXXX无码 | 农村熟妇高潮精品A片 | 亚洲精品永久免费 | 国产精品黄在线观看免费网站 | 影音先锋男人站 | 亚洲毛片无码专区亚洲A片 亚洲蜜桃AV色情精品成人 | 超91在线 | 一区二区视屏 | 99视频只有精品 | 美味三姐妹在线观看 | 国产精品A久久20242024 | 91久久九九精品国产综合 | 男女做爰的全部过程A片 | 情深不悔再爱难为 | 91成人啪国产啪永久地址 | 亚洲三级中文字幕 | 91久久线看在观草草青青 | 日本二区免费一片黄2019 | 亚洲一区二区三区四区五区黄 | 在线观看免费的小电影网站 | 九九九九九 | 97蝌蚪自拍自窝 | 欧美成人香蕉网在线观看 | 色中色网 | 一级生活毛片 | 先锋影音av资源网 | 在线观看免费av网站 | 一个人在线观看的免费视频www | 国产精品扒开腿做爽爽爽日本无码 | 免费A片国产毛A片无码久久 | 午夜影院欧美 | 天堂中文网 | 在线看v片 | 在线18av| 福利视频导航网址 | 久久99热这里只有精品66 | www毛片com | 国产AV亚洲精品久久久久久小说 | 国产又黄又粗又爽又色的视频软件 | 自拍视频一区二区 | 免费看的久久久久 | 看黄视频网站 | 成人在免费观看视频国产 | 丁香花在线观看免费观看图片 | 色欲AV久久一区二区 | 亚洲综合久久成人A片红豆 亚洲综合激情小说 | 少妇把腿扒开让我爽爽视频 | 秋霞伦理片看福利 | 欲女熟妇国产一区二区 | 黑人两根一起强进30p | 色妞网站 | 亚洲人成人网毛片在线播放 | 日本v视频 | 91碰视频 | 久久久综合中文字幕久久 | 好看的毛片| 人人爱夜夜爽日日做视频 | 日韩欧美中国a v | 最新发布页ccyycom草草影院 | 最新的国产成人精品2022 | 成年女人免费看一级人体片 | 狠狠色噜噜狠狠狠 | 黄篇网站在线观看 | 韩国三级日本三级在线观看 | 色哟哟在线观看免费网址 | 欧美孕妇乱大交xxxx | 成 人毛茸茸的视频 | 麻豆AV传媒在线播放免费观看 | 视频色版 | 国产成人精品免费久久久久 | 日日夜夜影院 | xxxxhdi8日本hd | 快播人人看电影网 | AV国産精品毛片一区二区网站 | 国产在线播放KKK | 日本熟妇乱人伦A片一区 | 国产SUV精品一区二AV18款 | 中国人xxxxbbbb国产 | 2021韩国理论片在线观看私人影院 | 激情六月色 | 九九在线免费视频 | AV天堂午夜精品一区二区三区 | 99久久精品免费看国产漫画 | 亚洲免费国产 | 小莹的性荡生活45章最新章节 | 日本后进式猛烈xx00动态图 | 在线精品国产一区二区 | 免费网站看片成年 | 亚洲天堂久久精品成人 | 麻豆精品久久久一区二区 | 欧美性生交片4 | 日本xxwwwxxxx| 色情A片成人网站免费看 | 青草欧美 | 婷婷五月小说 | 99久久精品免费看国产 | 国产91专区| 色视频网站在线观看 | 视频二区 中文字幕 欧美 | 亚洲AV久久无码精品九九九小说 | 三级网址在线播放 | 精品国产乱码久久久人妻 | 九九精品免视看国产成人 | 午夜久久久久久禁播电影 | 国产人妻无码一区二区三区不卡 | 亚洲第一色网 | 日本免费在线视频 | YELLOW影视免费 | 扬名立万免费观看完整版 | 日本一卡二卡3卡四卡在线新区 | 国产亚洲精品网站在线视频 | 成年黄网站色视频免费观看 | 日本成熟人妻理伦无码新片 | 成人免费的性色视频网站 | 意大利军营医生1976 | 一区二区三区好的精华液杨朝越 | 久久草色播 | 欧美视频在线观看xxxx | 伊人婷婷涩六月丁香七月 | 亚洲人成图片小说网站 | 国产午夜福利视频第三区 | 少妇大叫太大太粗太爽了A片在线 | 男人天堂网夜色99视频 | 久久久亚洲欧洲国产 | 久久久国产精品免费A片分环卫 | 亚洲精品久久一区二区三区2024 | 天堂国产在线观看 | 成年黄页网站大全免费 | 出轨的女人国语在线观看 | 久久97久久 | 人久人久人久污污污精品国产 | 四虎精品8848ys一区二区 | 中文字幕视频免费在线观看 | 国产黄色免费观看 | 樱井莉亚 ed2k | 老女老肥熟国产在线视频 | 美女18禁永久免费观看网站 | 日产精品卡2卡三卡乱码网址 | 一个人免费看的视频www | 狠狠人妻久久久久久综合九色 | 免费的青榴视频在线观看 | 天天干天天夜 | v片免费观看 | 欧洲精品不卡1卡2卡三卡 | 香港韩国三级日本三级 | 狠狠色伊人亚洲综合第8页 狠狠色网 | 毛片无码一区二区三区A片视频 | 四虎影视国产精品永久在线 | 美女裸乳裸体无遮挡免费A片软件 | 免费无码又爽又刺激A片小说 | 欧美bbbbbxxxxx | 特级淫片aaaaa片毛片 | 久久aa毛片免费播放嗯啊 | 亚洲日本香蕉视频观看视频 | 波多野结衣免费 | 天天干天天插 | 色姑娘综合网久久 | 日本不卡一区二区三区 | 四虎必出精品亚洲高清 | 91精品免费久久久久久久久 | 国偷自产视频一区二区99 | 东京热 影音 | 久久久久久不卡 | 亚洲无人区码一码二码三码的区 | 国产精品久久人妻无码网站一区L | 国产一级在线 | 97视频免费上传播放 | 最新亚洲国产手机在线 | YELLOW字幕中文字幕免费 | 黑人狂躁日本少妇在线观 | 激情婷婷综合 | 色爱综合区五月小说 | 日本无码毛片一区二区手机看 | 抖音无限次短视频老司机APP | 国产免费一级片 | 九七色伦| 成人亚洲A片V一区二区三区小说 | 欧美日本一区二区三区生 | 黄色免费在线观看视频 | 伦敦金属交易网价 | 色又黄又爽18禁免费视频 | 亚洲欧美bt | 亚洲熟妇毛茸茸 | 日本免费观看网站 | 91欧美精品综合在线观看 | 樱花草视频在线观看高清WWW | 日本黄页网站免费 | 国产ts在线播放 | 久久综合香蕉久久久久久久 | 97色伦97色伦国产 | 草色噜噜噜AV在线观看香蕉 | 成人无码WWW在线看免费 | 成人无码区免费A片视频韩国 | 成人国产一区二区精品小说 | 在线视频一区二区三区三区不卡 | 97久久国产露脸精品国产 | 69福利 | 久久国产成人福利播放 | 免费高清日本 | 深爱综合网| 黄色网页在线看 | 波多野结衣一区二区三区四区 | 亚洲色一色噜一噜噜噜 | 精品日韩二区三区精品视频 | 苍井空电影去哪儿看网址 | 一区不卡二区卡 | 两性影院 | 中文一级片 | 欧美做受 | 亚洲一区二区免费视频 | 亚洲女人影院想要爱 | 99精品久久精品一区二区 | 久久久久久毛片免费观看 | 99re6在线视频 | 小妖精朕受不了了高h | 奇米777四色影色在线看 | 国产高清资源一卡二卡 | 欧美精品九九99久久在观看 | 秋霞一级 | 精品久久久爽爽久久久AV | 影音先锋av男人资源 | 国产精品成人无码A片免费网址 | 黄色一级免费看 | 一本色道久久综合亚洲精品加 | 美景之屋4在线未删减免费 美景之屋4在线 | 久久国产毛片 | 97神马| 最近最新高清中文字幕MV在线 | 国产精品二区页在线播放 | 办公室激情波多野结衣 | 手机在线观看黄色 | 色播亚洲| 黄视频免费网站 | 亚洲AV永久综合在线观看尤物 | 三级毛片在线播放 | 天堂资源中文最新版在线一区 | 日日夜夜天天干 | 再深点灬舒服灬受不了了视频 | BL年下猛烈顶弄H | 樱花草在线观看播放视频www | 欧美xxxxb| v在线观看| 国产精品青青在线麻豆 | 真实国产乱子伦精品一区二区三区 | 精品久久久一二三区 | 国产精品边做奶水狂喷小说 | 日韩在线精品视频 | 有没有看片的免费资源 |