欧美日韩亚-欧美日韩亚州在线-欧美日韩亚洲-欧美日韩亚洲第一区-欧美日韩亚洲二区在线-欧美日韩亚洲高清精品

金喜正规买球

工作流的實現(在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
    西西人体大胆扒开下部337卩 | 国产又刺激又黄又爽又湿 | 国产精品吹潮在线观看中文 | 老熟女重囗味hdxx69 | 2025亚洲欧美日韩在线观看 | 国产精品三级不卡电影 | 亚洲日韩成人精品不卡在线 | 在线免费观看区一区二 | 欧美特黄特色三级视频在线观看 | 2025最新电影电视剧 | 日本一本二本三区免费 | 亚洲国产的精品太乱码一区二区 | 成在线人永久免费视频播放 | 蜜臀91精品国产高清在线观看 | 国产在线观 | 成人福利在线免费观看 | 激情视频小说在 | 国产美女爽到喷出水来视频 | 欧美日韩国产精品免费观看 | 欧美自拍偷拍视频 | 好看的日韩电影 | 免费91最新地址永久入口 | 神马影院手机在线观看 | 国产香港日本三级在线观看 | 国产亚洲精品午夜福利巨大 | 日本sm极度另类视频 | 国产精品精品自在线拍 | 亚洲成a人片在线观看天堂无 | 日韩精品一区二区免费在线观看 | 精品国产污网站在线观看15 | 999y| 国产一级a爱片免费看 | 把你的香肠放入我的扇贝里 | 亚洲精品视频一卡二卡三卡 | 又大又粗 | 亚洲天堂精品在线观看 | 成人动视频国产欧美精品 | 国产午夜a级理论片在线播放 | 国产99在线 | 三区免费高清视 | 一品二品国精破解 | 一区二区三区不卡 | 性欧美video高清 | 三年片观看免费观看大全 | 亚洲伊人色综合www962 | 日韩欧美国产91丝袜 | 亚洲高清国产拍 | a级全黄试看30分钟gif动图 | 好看的剧免费在线观看 | 日本一区二区三区免费在线观看 | 看国产电影 | 日韩亚射亚洲国产第一 | 亚洲欧美日韩在线精品一区二区 | 亚洲十大国产精品污污 | 中国老熟女重囗味hdxx | 日本三级私人电影网 | 国产精品亚洲综合一区在 | 韩国日本亚洲欧洲一区二区三区 | 97色轮 | 三级视频网站在线观看视频 | 亚洲欧洲精品一二三区 | 国产精品高清免费网站电影 | 国产欧美一级高清片 | 国产熟女一区二区三区浪潮 | 欧美一区二区三区男人的天堂 | 日韩国产欧美亚洲一区不卡 | 国产日韩高清一区二区三区 | 国产精品国语对白一区二区 | 日韩美女黄大片在线观看 | 精品夜恋影院亚洲欧洲 | 午夜性爱故事在线观看 | 国产精品极品美女自在线观看免费 | 国产精品免费观看网站 | 欧美性色欧美a在线观看 | 亚洲精品中文字幕无乱码 | 中文字幕精品一区二区日本大胸 | 10000部拍拍拍免费视频 | 精品一区二区三区视频在线 | 亚洲色人妇性爱视频 | 国产欧美日韩一区二区三区 | 日韩免费一区二区三区高清 | 国产精品探花一区在线观看 | 亚洲成a人片在 | 杨幂在日本一区二区视频 | 亚洲精品色午夜 | 国产亚洲午夜高清亚洲精品 | 亚洲欧美手机在线观看 | 精品91自产拍 | 国产日韩一区二区三区视频免费 | 亚洲精品动漫免费二区 | 日韩欧美激情视频 | 7777色鬼 | 国产香蕉一区二区在线网站 | 国语在线看免费观 | 看片国产| 国产乱子经典视 | 日韩欧美国产电影 | 精品香蕉伊思人在线观看 | 秋秋影视午夜福利高清 | 国产一区福利在线 | 日本三级韩国三级香港三级a级 | 国产欧美日韩精品综合第一区 | 日韩欧美综合在线制服 | 国产欧美一区二区 | 国产宅男宅女在线观看 | 文中字幕一区二区三区视频播放 | 一区二区三区日本精品 | 飘花在线影院 | 手机在线观看日韩电影大片 | 在线精品亚洲一区二区绿巨人 | 亚洲精品沙发午睡系列 | 九九九热在线精品免费全部 | 乱伦精品亚洲影视 | 精品亚洲成a人app | 爽国产片精品 | 在线观看日本欧美综合色 | 91福利官网| 欧美在线观看精品国产 | 精品国产高清自在线一区二区三区 | 日韩中文字幕免费视频 | 久在线免费观看成年人视频 | 亚洲色国产欧美日韩 | 免费看aⅴ| 国内综合网 | 国产精品免费视频观看玖玖 | 激情欧美一区二区三区 | 亚洲精品精华液一区二区 | 亚洲成a人片在线播放 | 国产高清在线a视频 | 国产精品一区二区手机在线观看 | 热门电影在线观看 | 国产一级淫片视频免费看 | 亚洲精品国产高清在线观看 | 真人做爰片免费 | 欧美三级 | 亚洲国产在线精品国偷产拍 | 国产欧美在线免费观看 | 一区二区三区在线播放 | 真实国产日韩欧美全部综合视频 | 全部视频欧美日韩在线无人 | 在线精品国精品国产尤物 | 免费观看网站 | 欧美另类69xxxx | 国产灌醉极品在线观看 | 97福利精品第一导航 | 国产亚洲精品国产91 | 最近在线观看免费完整版高清电影 | 亚洲欧美日韩综合第一页 | 成人午夜免费视频 | 亚洲中文在线精品国产 | 欧美一级鲁丝 | 国产99久9在线视频传媒 | 欧美日韩亚洲视频精品 | 综合色就爱涩涩涩综合婷婷 | 2025最流行电视剧 | 日韩欧美国产偷亚洲清高 | 五月天亚洲婷婷综合 | 美女在线观看永久免费网站 | 一区二区日韩激情综合网 | 99精品偷拍视频一区二区三区 | 五月综合激情婷婷六月色窝 | 99精品视频在线观看 | 中文字幕午夜福利片午夜福利片 | 国产刺激视频在线观看 | 亚洲欧美精品福利一区二区 | 免费人成在线观看网站免费观看 | 神马午夜福利我不卡手机电影 | 亚洲女色福利免费视频 | 国产免费日本高清 | 国产日韩精品一区二区在线观看 | 日本三级手机在线播放线观看 | 日本欧美韩国一区二区三区 | 日韩一区二区三区四区五区 | 最好免费观看高清视频大全 | 亚洲人成小说网站色 | 欧美另类69xxxxx极品 | 对白刺激的老熟女露脸 | 伊人亚洲日韩欧美一区、二区 | 大片免费网站 | 99视频在线精品自拍 | 国产婷婷| 国产高清一区二区三区四区 | 最新国产精品自在自线发布 | 欧美日韩国产精品视频 | 日韩系列第一页 | 美女一区二区三区 | 免费一级e一片在线播放 | 五月激情丁香婷婷综合第九 | 天堂中文在线资源 | 日本一区二区三区在线观看 | 欧美一区二区三区精品国产 | 国产午夜a级理论片在线播放 | 国产免费福利影院 | 国产美女在线观看 | 国内精品一区 | 亚洲午夜视频在线观看 | 91精品欧美一区二区综合在线 | 国产成年精品高清在线观看91 | 国产女主播在线观看免费观看 | 真实国产精品视频400部 | 天堂va欧美ⅴa亚洲va一国产 | 欧美午夜不卡在线观看最新 | 天堂成人| 日韩欧美在线综合网高清 | 国产精品天天天天影视 | 最近中文字幕完整版hd | 免费看污网站 | 高圆圆又紧又大又湿又爽 | 精品国产男人的 | 99热这里只有精品国产4 | 国产一级a爱做片免费看 | 九九热视频免费在线观看 | 观看免费视频 | 亚洲精品一品区二品区三品区 | 不卡视频在线播放 | 7160美女图片 | 日本精品高清一区二区 | 国产精品乱码高清在线观看 | 精品一区二区夜色 | 午夜国产在线一区二区三区 | 欧美乱妇高清无乱码在线观看 | 国产在线观看网站萌白酱视频 | 成人欧美一区二区三区在线观看 | 男女羞羞视 | 欧美一区二区三区男人的天堂 | 性xxxx视频播放 | 日本三级视频在线观看 | 九九热线精品视频在线观看 | 国产香蕉尹人在线观看视频 | 亚洲精品影院 | 后进极品翘臀在线播放 | 永久入口| 美女裸身网站免费看免费网站 | 成人夜视频寂寞在线观看 | 欧美在线成人怡红院 | 国产在线视频在线观看 | 精品国产鲁一鲁一区二区 | 国产痴汉系列在线播放 | 亚洲精品国产精品乱码不卡√ | 黑人巨大精品欧美一区二区一 | 亚洲国产日韩欧美一区二区三区 | 欧美另类第一页 | 一区二区三区高清视频 | 一区二区在线免费观看 | 日本黄页网站免费大全 | 日本久色 | 小说区图片区激情区视频区 | 欧美丰腴丰满大屁 | 国产精品h片在 | 亚洲国产成a人v在线观看 | 日本三级网站在线观看视频 | 在线观看视频欧美 | 日韩欧美中文字幕 | 亚洲精品国产精品国自产 | 亚洲激情午夜福利色色色 | 亚洲第一区欧美国产不卡综合 | 国产精品色三级在线观看 | 国产国产人免费视频成69大陆 | 日韩免费的视频在线观看香蕉 | 免费观看最新电影和热门影视剧 | 亚洲精品r级在线观看网站 国产黄大片在线观看画质 欧美无砖专区一中文字幕 欧美亚日韩国产aⅴ精品中极品 | 欧美v亚洲v综合ⅴ国产v | 国产日产欧产精品浪潮使用方法 | 中文字幕日韩一区二区三区不卡 | 一区二区三区在线观看欧美日韩 | 国产国产人精品视频69 | 国产亚洲午夜高清亚洲精品 | 免费网剧电视剧大全 | 日产无人区一线二线三线最新版 | 日本精品a在线观看 | 国产在线中文字幕 | 国产点击进入在线 | 在线不卡 | 国产天天看免 | 国产在线精品一区二区三区不卡 | 88国产精品视频一区二区三 | 国产对白精品刺激一区二区 | 91天天综合免费看国产 | 美女被肏翻白眼视频在线观看 | 成人欧美一区二区三区黑人 | 欧美视频人人干人人 | 欧美高清中文字幕综合网 | 亚洲日本国产一区二区精品成人 | 亚洲色中文字幕在线播放 | 国产亚洲成aⅴ人片在线奶水 | 午夜视频体内 | 2025最新国产在线看 | 成人国产精品日本在线 | 黑人性较视频免费视频 | 亚洲视频在线 | 观看国产色 | 中国免费xxxx视频在线观看 | 国产高清一区二区在线免费观看 | 91丝袜国产欧美 | 桃色影视国产一区二区三区 | 亚洲国产日韩欧美综合a | 免费一级e一片在线播放 | 国产又粗又猛又爽又黄 | 国产色系视频免费在线观看 | 国产激情免费视频在 | 国产性爱精品亚洲 | 一区国产传媒国产精品 | 朋友的妈妈2在完整有限中字第 | 337p亚洲精品 | 一个人看的www视频免 | 亚洲午夜成激人情在线国内 | 欧美国产在线专区 | 国产字幕制服中文在线 | 午夜影院网站野外大战 | 国产伦精品一区二区三区视 | 亚洲三级在线观看 | 国产精品素人搭讪在线播放 | 老少配老妇老熟女中文 | 国产香线 | 黑人操中国女人 | 性爱国产精品福利在线 | 乱码在线观看 | 日产乱码区别免费必看 | 91成人精品一区二区三区四区 | 国产精品日日做人人爱 | 日韩va不卡精品一区二区 | 国产日韩综合在线视频 | 午夜福利国产在线观看1 | 依依成人影院在线观看 | 乱色熟女综合一区二区三区 | 国产日韩欧美在线观看一区二区 | 欧美日韩国产无线码无毒 | 亚洲日本aⅴ精品一区二区在线 | 精品国产迪丽热巴在线 | 欧美xxx | 国产精品一区福利在线观看 | 国产一区二区三区不卡在线 | 日本xxxx色 | 韩国午夜理伦三级理论在线观看 | 国产原创精品在线 | 国产鲁鲁视频在线观看免费 | 亚洲免费观看视频 | 又大又粗又黄又硬又爽又免费视 | 国产日韩高 | 在线免费视频 | 国产在线观看精 | 国产在线一区二区三区在线 | 午夜国产一区 | 真实国产精品vr专区 | 日韩精品在线不卡一区二区 | 亚洲激精日韩激精欧美潮精品 | 91香蕉国产观看免费人人 | 天堂mv在线mv免费mv香蕉 | 欧美日韩日本中国高清视频在线 | 91国内精品在线入口 | 国产亚洲精品午夜高清影院 | 亚洲欧美一区二区三区久本道 | 旋复花7799电影| 欧美亚洲一区二区三区三 | 国产精品视频永久免费播放 | 中文字幕v| 不卡中文字幕激情视频网站 | 永久免费提 | 国产在线观看 | 成年入口无 | 中文欧美日韩无线码 | 国产在线一区二区三区不卡在线 | 久在线精品视频线观看 | 国产精品自产拍在线观看中文 | 亚精一区二| 丰满的继牳3中文字幕系列 电影推荐 | 全日爱韩国视频在线观看 | 自拍偷自拍亚洲 | 色久悠悠婷婷综 | 免费人成网站视频在线观看国内 | 日韩在线电影大全免费观看 | 日韩免费网页版视频 | 99视频精品全部国产盗摄视频 | 日韩经典欧美一区二区三区 | 国产男女拍拍拍高清视频 | 国产精品亲子乱子伦xxxx | 国产精品色一区二区三区 | 国产专区一区 | 网站免费观看 | 2025年国产| 国产精品最新高清 | 欧美亚洲精品一区二区在线观看 | 最新国产精品 | 日本三级全黄 | 在线观看国产一级 | 国产ppp视频| 欧美高清一区二区三区欧美 | 欧洲亚洲一区二区三区 | 国产情侣真实露脸在线最新 | 92国产福利午夜 | 久热最新精品视频在线观看 | 亚洲码欧美码一区二区三区 | 九九九热在线精品免费全部 | 中文中国国语 | 亚洲国产精品尤物yw在线 | 亚洲欧美日本人成在线观看 | 三区影院 | 国产精品视频露脸 | 日本在线综合一区二区三区 | 97韩剧tv网 | 不卡在线播放中文字幕在线 | 在线久色| 日韩国产一级一区精品 | 國產精品va| 飘雪影院手机免 | 国产精品高清自在线 | 欧美疯狂 | 国产自在自线精品午夜视频 | 欧美靠逼 | 欧美a√在线免费观看 | 学生精品国自产拍中文 | 亚洲欧美综合一区二区三区黄大片 | 日韩精品无 | 精品影片在线观看的网站 | 午夜男女爽爽影院在线 | 亚洲v女人的天堂在线观看 五月婷婷中文字幕 | 一级毛卡 | 欧美激情国产 | 中文字幕在线观看国产 | 日韩欧美色激情 | 成人区精品一区二区不卡亚 | 啦啦啦ww | 日本高清中文字幕在线 | 骚女影院 | 欧美激情视频区一区二区在线观看 | 神马午夜福利我不卡手机电影 | 成人午夜在线观看日韩 | 青青青国产在线观看资源 | 视频在线播放在线观看 | 亚洲精品综合在线发布 | 办公室激情上司和秘书小说 | 国产精品艾草在线观看 | 欧美激情精品久 | 日日夜人人澡人人澡人人看免 | 亚洲日本道1区2区3区不卡 | 九七电影院 | 亚洲成a人片在线观看www | 97精品亚成在人线免视频 | 欧美与黑人 | 色一情一伦一区二区三 | 中文有码国产精品 | 激情综合在线观看 | 亚洲是第一大洲的原因 | 色国产精品一区在线观看 | 10000部拍拍拍免费视频 | 国色一卡2卡二卡4卡乱码 | 日本一道在线播放高清 | 观看视频| 国产一级一片免费播放视频 | 丝袜亚洲日韩另类 | 亚洲精品一二三四区 | 国产精品亚洲专区 | 午夜日韩综合激 | 中国老熟女重囗味hdxx | 国产一级a毛一级a看免费视频 | 日韩a优精品在线观看 | 在线观看人| 国产va精品免费在线观看 | 欧美综合自拍亚洲综合区 | 国产在线精品一区二区不卡 | 欧美亚洲喷水视 | 亚洲免费视频一区二区 | 国产成本人三级在线观看网站 | 日本高清视频不卡 | 国产真实乱对白精彩 | 一级做a爰片久 | 欧美人与动性行为网站免费 | 亚洲精品一区二区三区四区五区 | 人人干97 | 日本一区二区三区在线观看不卡 | 亚洲精品自有码中文字 | 国产又粗又硬又大爽黄老大爷视 | 欧美国产精品一级二级三级 | 亚洲欧美日韩综合第一页 | 色护士极品影院 | 在线观看视频欧美 | 国产在线观看精品一区二区三区 | 欧美另类图片视频无弹跳 | 999精产 | 99精品一区二区三区免费视频 | 国语精品| 国产拍拍拍在线观看视频免费 | 五月天亚洲婷婷综合 | 学生精品国自产拍中文 | 欧美性xx | 亚洲精品第一国产综合精品 | 国产精品宾馆在线精品酒店↗ | 国产高清在线精品一区小说 | 好看的电影电视剧大全 | 亚洲免费无 | 中文字幕不卡在线观看 | 欧美激情第1页 | 国产视频精品一区白白色 | 激情福利社 | 国产一区二区三区四区五区加勒比 | 欧美精品videosex极品 | 亚洲综合国产在不卡在线首映 | 国产专区在线播放 | 老色鬼在线精品视频 | 放荡的美妇在线播放 | 中文日本 | 人人爱天天做夜夜爽2025 | 久99久热只有精品国产15 | 亚洲欧美香蕉在线日韩精选 | 神马午夜电影网手机在线播 | 在线看片免费人成视久网 | 国产精品无 | 欧美日本高清视频在线观看 | 一区二区三区四区在线不卡高清 | 国产精品v欧美 | 日韩成人午夜影院 | 99精品欧美一区二区三区 | 国产综合一区 | 国产超级乱婬视频免费 | 日本高清乱理伦片中文字幕 | 东日韩二三区 | 国产真实乱在线更新 | 亚洲国产精品福利片在线观看 | 日韩国产在线观看 | 三年片最新电影免费观看 | 国产l精品国产亚洲区在线观 | 欧美三级极品视频在线观看 | 国产日b| 日本乱码乱码免费高清视频 | 婷婷国产精品中文字幕 | 又大又粗又黄又硬又爽又免费视 | 亚洲狠狠婷 | 91视频网址 | 私人订制1080在线观看免费 | 精品国产中文 | 国产免费人成视频在线观看播放 | 青青草免费国产视频网站 | 亚洲精品亚洲欧美综合区 | 亚洲国产自 | 成+人+免费+黄+网站 | 国产一级精品在线观看 | 日韩精品三级 | 欧美在线成人怡红院 | 亚洲日韩国产欧 | 国产在线观看视频 | 国产精品视频一区 | 天堂草原影院电视剧 | 亚洲中文字幕第一页在线 | 欧美精品视频手机在线视频 | 欧美国产日韩一区二区 | 亚洲午夜精| 999y| 精品一区二区三区国产视频 | 最近在线观看免费完整版高清电影 | 欧美综合乱码一区二区三区 | 在线精品亚 | 欧美人成中文视频在线观看 | 成年人免费在线看的惊悚动作片 | 手机看片福利一区二区三区 | 乱码一线二线三线新区破解欧 | 免费高清直 | 日韩免费福利试看3分钟 | 国产女人抽搐喷浆视频 | 国产精品民宅偷窥盗摄 | 亚洲精品中文字幕码专区 | 国产精品视频专区 | 中文在线а√天堂官网 | 国产精品一品二区三区的使用体验 | 精品国产一区二区一区二 | 99视频在线免 | 操中国美女逼美女 | 视频观看中文 | 国产精品99在线观看 | 国产99视频精品免费观看9 | 日本三级网址狠狠 | 中文字幕日韩精品一 | 国产亚洲aⅴ在线电影 | 国产乱伦免 | 亚洲欧美日韩中文字幕二区 | 2025最新电影、电视剧、综 | 日本高清专区一区二无线 | 好看的韩国电影 | 国自产拍亚洲免费视频 | 成人日韩精品一区二区 | 九九九热在线精品免费全部 | 99热只有这里有99精品 | 高清影视电视剧在线观看 | 免费国产午夜高清在线视频 | 欧美亚洲自拍日韩在线 | 日韩免费一区二区三区高清 | 一本到国产在线精 | 国产国产人视频69免费 | 国产aⅴ片 | 日本在线视频在线 | 日韩一区在线观看免费观看免费 | 手机电影在线观看 | 中文字幕不卡高清dvd | 探花视频在线 | 欧美日韩在线播一区二区三区 | 性欧美vr高清极品 | 午夜dj| 亚洲午夜福利在线视频 | 视频一区二四三区四区 | 日韩精品一区二区免费在线观看 | 日皮视频免费观看 | 国产99久9在线视频 欧美日韩国产综合视频 | 国内精品自线一区二区三区 | 亚洲午夜私人影院 | 潘金莲与西门庆床戏在线 | 欧美三根一起进三p | 日本特级婬片中文免费看 | 69精品人人人人 | 亚洲人成网站在线 | 精品国产福利在线观看网站 | 最新色国产精品精品视频 | 天天被干免费观看视频 | 女明星a级毛 | 麻酥酥哟视频在线播放 | 午夜视频一区二区三区 | 欧美日韩国产高清精卡 | 制服丝袜亚洲中文综合 | 在线成人国产公开视 | 又大又粗又硬又黄的免费视频 | 国产一区二区在线视频观看 | 三年片在线观看免费大全电影 | 不卡的神马电影网 | 亚洲高清国产品国语在线观看 | 国语自产精品视频在线看 | 日本aⅴ精品一区二区三区日 | 亚洲综合国产在不卡在线首映 | 国女精品爽爽一区二区 | 男人扒开女人腿桶到爽免费 | 99re8这里有精品热视频 | 日韩一本到亚洲男人的天堂 | 秋霞伦理电影在线看 | 国产在线精品一区二 | 情趣五月天| 日本在线观看中文字幕 | 国产一区二区三区四区五区 | 亚洲免费在线国产视频午夜精 | 中文国产欧美在线观看 | 91精品国产乱码在线观看入 | 99热这里只有精品18 | www网站羞羞视 | 日本免费在线视频 | 十年造就经典 | 欧美亚洲欧美日韩中文二区 | 亚洲中文字幕丝袜制服视频 | 性欧美暴力猛交6 | 在线成人免费观看国产精品 | 男人精品一线视频在线观看 | 国产精品成熟老女人 | 热门好看动漫综艺 | 老熟女重囗味 | 精品成人一区二区三区电影 | 日本夫妻激情生活b区 | 精品在线视频免费在线观 | 激情五月婷婷丁香六月 | 在线观看亚洲精品国产 | 婷婷蜜桃国产精品一区 | 国产极品视频一区二区三区 | 精品露脸 | 中文字幕片| 无限国产| 神马午夜福利我不卡手机电影 | 免费网剧电视剧大全 | 欧美日韩变态另类在线观看 | 国产亚洲人成a在线v网站 | 亚洲+欧洲+日产 | 国产日韩一区二区三区视频免费 | 亚洲欧美色一区二区三区 | 欧美二区在线观看 | 国产高清一区二区三区四区 | 免费国产午夜高清在线视频 | 伊人焦久综合影院每日更新 | 99re视频热这里只有精品 | 日本最新高清不卡一区二区 | 国产美女淫秽一区二区三区 | 国产精品1234 | 欧美成成人免费 | 亚洲国产变态另类天堂 | 私人电影官网 | 91精品全国免费观看老司机 | 免费中文字幕不卡视频 | 日韩在线观看免费 | 在线永久观看国产精品电影 | 国色一卡2卡二卡4卡乱码 | 日本中文字幕专区视频在线 | 国产精品极品露脸清纯 | 久热爱精品视频在线 | 国精产品一区一区三区mba下载 | 日本天堂免费观看 | 九九中文字幕国产 | 国产片免费 | 亚洲激精日韩激精欧美潮精品 | 国产精品成人免费福利 | 国产在线观看一区二区三区四区 | 中文字幕无线码一区2025青青 | 午夜亚洲理| 日韩伦理福利免费 | 一本一本大道香蕉久在线精品 | 欧美日韩一区二区三 | 秋霞国产午夜 | 国产极品精品免费 | 天堂在线中文网www 女人的天堂a国产 | 57pao视频国产在线观看 | 免费人成大片在线播放 | 国产丝袜精品 | 亚洲一区二区三 | 亚洲精品国产高清在线观看 | 日产精品一品二品三品 | 在线网站| 国产综合成人色产三 | 午夜激情影 | 亚洲经典一区二区三区爱妃记歌词 | 思思精品 | 国产精品综合一区二区 | 99成人国产精品视频 | 欧美一区二区不卡视频 | 国产又污又爽又黄又刺激网站 | 色影院不卡中文 | 三级特黄60 | 欧美日韩一区二区三区视频网站 | 中文字幕永久一区二区三区 | 日本系列1 | a性视频 | 亚洲精品在线不卡 | 精品国产人成亚洲区 | 日韩a在线 | 999二区在线 | 国产丝袜在线精品丝袜不卡 | 伊人网视频在线观看 | 女人体视频1963 | 日产a一a区二区www | 国产剧情 | 国产私拍福利精品视频推出 | 日韩欧美国产一 | 亚洲精品亚洲人成在线播放 | 美女爽到尿喷出来 | 日韩精品免费一线在线观看 | 成人午夜免费观看 | 亚洲精品在看在线 | 亚洲欧美日韩精品色xxx | wwwwwww黄| 欧美日韩免费精品一区二区在线 | 国产乱视频在线观看 | 欧美性爱福| 国内三级自拍小视频在线观看 | 亚洲免费在线观看 | 亚洲免费在线观看一区二区 | 日韩一级一欧美一级国产 | 呦导航福利精品 | 夜爽8888视频在线观看 | 精品一线二线三 | 国产亚洲一区二区手机在线观看 | 国产亚洲精品成人a在线 | 国产日韩成人精品视频 | 二区三区爱欲九九 | 中文字幕亚洲欧美在线不卡 | 国产乱子伦精品 | 精品录音国产一区在线 | 国产精品国产高清 | 国产伦子伦对白视频 | 日本xxx| 99爱在线精品视频免费观看9 | 日本在线观看免费高清 | 日本一区二区高清国产 | 欧美精品人在线观看 | 桃色影视国产一区二区三区 | 国产精品视频1区 | 午夜不卡影院 | 国产精品久线在线观看 | 精品亚洲欧美中文字幕在线看 | 91探花国产综合在线精品 | 国产精品6 | 日本最新一日本一二三区 | 日本大肚 | 国产韩国日本欧美在线观看 | 成年入口无 | 亚洲人午夜射 | 黑人巨大精品欧美一区二区免费 | 国产精品亚 | 91国内揄拍 | 欧美日韩在线亚洲 | 欧美性xx | 日韩中文字幕34页视频 | 美国十次导航 | 国产免费一区二区三区视频 | 亚洲天堂国产视频 | 97在线也免费视频 | 国产99精 | 欧美日产欧美日产国产精品 | 一本大道中文日本香蕉 | 午夜在线观看视频 | 国产亚洲精品a在线看 | 欧美综合自拍亚洲综合百度 | 欧美一区福利 | 精品国产鲁一鲁一区二区 | 精品午夜福利在线视在亚洲 | 国产一区二区视频 | 亚洲精品国产精品 | 性xxxx视频播放 | 国产精品丝袜一区二区三区 | 日本免费一区二区在线 |