国产凹凸在线-国产拗女一区二区三区-国产白白视-国产白领-国产白拍-国产白丝jk被疯狂输-国产白丝喷-国产白丝在线

金喜正规买球

工作流的實現(在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
    精品一区二区免费视频a | 欧美一级爽快片婬片在线观看 | 欧美一区二区三区精品视频在 | 国禹九歌电影网 | 国产六月婷婷爱在线观看 | 国产哟一区二区三区视频在线看 | 国产视频中文字幕在线观看 | 老司机99视频在线免费观看 | 中文天堂在线 | 正在播放国产自在线拍 | 永久在线免费观看美女热比网站 | 国产激情一区二区三区在线hd | 日韩精品在线开放 | 成综合网网站欧美 | 欧美丝袜自拍制服另类 | 日本欧美人成免费视频 | 欧美日韩亚洲中文综合视频 | 国产一级理论在线电影 | 国产在线地址2025 | 免费不卡国产精品午夜福利在线 | 国产乱子伦l精品 | 最近日本免费观看mv免费版 | 亚洲欧美日韩精品综合网 | 99精品在 | 免费人成在线观看网站免费观看 | 欧美日韩国产精品选 | 亚洲熟女一区二区三区 | 91午夜福利国产在线观看 | 欧美大胆a级视 | 亚洲愉拍自拍欧美精品app | 一个人在线视频免费观看www | 国产普通话漏脸在线观看 | 最新精品国偷自产在线观看 | 日本韩国欧美三级在线 | 亚洲精品国产suv一区 | 一本一本 | 亲子乱子伦xxxx | 激情亚洲一区国 | 国产欧美日韩精品丝袜高跟鞋 | 欧美亚洲日韩一区 | 天堂中文在线资源 | 18黄人成网站在线观看 | 欧美一级a一级a爱片免费免免 | 碰97在线免费视频 | 卡一卡二卡三乱码厨房 | 91精品国产闺蜜国产在线闺蜜 | 日韩精品免费网站 | 成人免费福利片 | 精品国产欧美一区二区最新 | 日韩欧美亚洲中文字幕第一页 | 国产成年网站v片在线观看 日本一本二本三区免费高清 | yy4080国 | 日韩成人中文字幕在线观看 | 五月丁香六月婷婷综合网缴情 | 国产专区视频在线观看 | 一区二区三区国产美女在线播放 | 亚洲男人的天堂在线va拉文 | 97秋霞影院 | 亚洲欧美另类激情综合区蜜芽 | 亚洲网站在线 | 国产99视频精品草莓 | 精品免费 | 成年女人免费碰碰视频 | 九七九七色伦在线影院 | 九色91 | 九一视频在线观看 | 91啪国自产最新91啪国自产 | 欧产日产国产精品精品 | 国产精品欧美亚洲韩国 | 欧美亚洲亚洲日韩在线影院 | 国产精品成人免费视频 | 成全的免费| 91色色| 丝袜美腿女邻居人 | 亚洲精品一品区二品区三区 | 国产精品va在线观看丝瓜影院 | 日本不卡网站 | 国产在线乱码一区二区三区 | 亚洲人精品午夜射精日韩 | 国语fre| 麻花影视在线看电视剧软件 | 日韩精品一区二区三区射精 | 军训完被教官灌满精子男男 | 色哟哟www视频在线观看高清 | 网友分享日韩欧美一区 | 国色天香国产精品 | 日韩亚洲欧美精品综合 | 国产性夜夜春夜夜 | 日本一在线中文字幕天堂 | 中文字幕亚洲综合小综合在线 | 国产一区二区日韩欧美在线 | 国产精品偷伦视频免费观看 | 日韩福利写真福利在线观看 | 欧美一区二区三区免费 | 国产盗摄91精品一区 | 秋霞电影亚洲一区二区三区 | 自偷自拍亚洲综合精品 | 国产青榴视 | 老熟女重囗味hdxx70星空 | 西瓜影音免费 | 欧美精品网站在 | 亚洲国产高清 | 国产91丝袜在线播放动漫蜜月 | 亚洲综合偷拍一区二区三 | a级在线观看日韩 | 国产在线精品一区二区三区不卡 | 日韩精品一区二区三区中文不卡 | 日本在线一区二区 | 欧美日韩免费 | 欧美一级精品免费播放 | 亚洲国产精品色一区二区 | 视频软件短片 | 精品女同一区二区三区免费战 | 一区二区三区日韩欧美 | 欧美系列国产系列一二三四 | 视频一区在线观看 | 国产精品敌一区二区三区 | 精品日韩中文字幕在线 | 日本最大色倩网站www不卡 | 欧美a级影院 | 日韩欧美亚洲三区视频 | 国内精品自在自线视频香 | 日本一区中文字幕免费 | 欧美.日韩~中文字幕 | 热99r| 中文字幕国产日韩 | 日韩精品午夜视频一区二区三区 | 精品国产手机自在线观 | 国产乱肥老妇国产一区二 | 精品一区二区三区日韩 | 乱无伦码中文视频在线 | 欧美性性性 | 亚洲精品天堂在线 | 国内精品伊 | 色偷偷国色天香在线观看免费视频 | 日韩视频在线播放 | 亚洲国产欧美中文手机在线 | 全日爱韩国视频在线观看 | 亚洲国产aⅴ成人精品无吗 国产真实乱人视频在线看 成人精品一区二区电影 | 日韩国产精品天天更新 | 精品在线免费播放 | 国产大片特黄高清视频 | 精品国产乱子伦一区 | 亚洲日本国产乱码va在线观看 | 国产98在线 | 免费香蕉一区二区在线观看 | 日本国产性爱观看视频 | 国产精品成人一区二区三区电影 | 男男做肉爱视频在线观看 | 只有精品首页 | 国产精品日韩欧美在线 | 日韩成人激情综合网 | 欧美激情性色生活片免费观看 | 在线精品亚 | 国产中文字幕在线 | 午夜影视污 | 精品亚洲影视自拍 | 日韩精品国产一区二区三区 | 亚洲激情自拍 | 性开放的欧美大片黑白配 | 精品视频无 | 黄瓜影视 | 吉吉影音先 | 97视频在线观看这里只有精品 | 欧美日韩伦精品一区二区三区 | 国产精品国产精品国产专区不卡 | 日韩视频在线观看免费 | 在线观看亚洲 | 中文字幕第一页在线 | 日韩欧美激情刺激爽爽影院 | 欧美日韩国产综合视频在线看 | 亚洲+欧洲+日产+欧美 | jizz国产精品大全 | 日本一本二本三区免费2025 | 欧美日韩高清一区二区在线 | 免费观看mv免费 | 激情影院內射美女 | 90dvd国产高清视频 | 国产门事件真实视频在线 | 日本一区二区在线视频 | 男女羞羞视频在线观看 | 最近中文字幕mv免费高清视频 | 亚洲欧美性爱r不卡 | 国产女学生破女初在线观看 | 99ri国产一区在线观看 | 国产精品精品综合在线网 | 亚洲欧美日韩国产精品一区第一页 | 成人妇女免费 | 亚洲人午夜射精精品日韩 | 最新在线观看视频国产91 | 中文字幕在线观看2025 | 银杏在线app | 国产精品资源站在线 | 亚洲曰韩精 | 好吊妞人成视频在线观看 | 欧美日韩精品一区二区在线 | 日韩一本到亚洲男人的天堂 | 国产蝌蚪免费观看视频 | 日本精品一区二区三区在线 | 秋霞理伦韩国在线电影 | 国产午夜无 | 亚洲欧美日韩另类 | 国产欧美日韩不卡 | 日本三级香港三级人妇99 | 欧美自拍另类欧美综合图片区 | 亚洲国内自拍欧美一区二区三区 | 欧美日本一区二区视频在线观看 | 精品国产乱码欠欠欠欠精品 | 日韩欧美精品国产亚洲综合网站 | 欧美亚洲国产日韩综合aⅴ 伦理高清在线观看 | 欧美aaa视频 | 日本成人动漫私人影院 | 动漫美女被强奷视频免费网站 | 男女猛烈啪啦啦啦免费 | 日本不卡一区二区三区www | 星辰影院| 国产精品v日韩精品v | 国产精品黑色蕾丝丁字裤 | 精品国产福利片在线观看 | 欧美制服丝袜国产日韩一区 | 国产又粗又长的视频 | 开拓亚洲色偷偷偷综合网的同时 | xx性欧美肥妇欧美 | 欧美、另类亚洲 | 伦视频在线观看 | 国产亚洲欧美一区二区 | 91精品全国免费观看青青 | 亚洲欧美日本一区二区三区 | 亚洲免费一区二区 | 国产一区二区三区美女图片 | 强奷有码在线播放 | 秋霞理伦韩国在线电影 | 国产精品第一页 | 国产亚洲成a人片在线观看 精品免费囯产一区二区三区四 | 日本乱理伦片在线观看真人 | 成人怡红院视频在线观看 | 欧美国产在线成人 | 亚洲一区二区三区在线观看网站 | 欧美亚洲国产清纯综合图区 | 免费国产黄线在线观 | 日本一区二区三区最新免 | 日韩综合在线欧美中文字幕 | 成年人黄 | 精品午夜福利在线视在亚洲 | 日韩成全视频观看免费观看高清 | 国产主播在线一区二区 | 亚洲欧美中文日韩欧美 | 国产极品在线观看极品 | 国语在线看免 | 视频二区日韩 | 男人精品一线视频在线观看 | a亚洲电影在线观看 | 国产一区三区二区中文在线 | 91精品国产自在现线91 | 日本成a | 日本一区二区更新不卡 | 国产精品自在欧美一区 | 国内免费视频一区二区三区 | 国产1区2区 | 91一区二区在线观看精品 | 日韩xxxx高清在线观看 | 91成版人在线观看入口 | 国语自产精品视频在视频 | 欧美日本一区二区三区生 | 97碰成人国产免费公开视频 | 国产91精品成人不卡 | 欧美激情猛片xxxⅹ大3 | 99精品一区二区三区免费视频 | 爱看电影网 | 国产在线观看成永久视频 | 国产黑色丝袜视频在线 | 不卡中文字幕激情视频网站 | 日韩免费精品一区二区三区 | 重口sm一区二区三 | 亚洲精品中文字幕 | 凄辱护士日本电影免费看 | 99热这里只有精品动漫国产 | 后进极品翘臀在线播放 | 日韩精品综 | 国产精品第12 | 午夜私人成年影院在线观看 | 欧美激情va永久在线播放 | 欧美yw精 | 成人激情电影免费在线观看 | 日韩一级大片国产 | bt在线天堂中文最新版 | 欧美日韩国产一区二区三区在 | 欧美极品欧美精品欧美 | 成人影视在线观看 | 欧美日韩亚洲国产一区 | 亚洲欧美日韩人成在线播放 | 97在线观| 韩国日本中文字幕一区二 | 成人影片在线官网 | 免费的又色又爽又黄的片 | 国产精品亚洲综合网熟女 | 国产每天更新视频在线 | 国产美女精品视 | 国内免费久 | 91九色老熟女 | 女人扒开屁股让男人桶爽 | 欧美亚洲欧美日韩中文二区 | 成人深夜 | 免费一看一级 | 欧美日韩亚洲国内一区二区三区 | 免费高清影院在线观看 | 亚洲天堂激情在线看 | 国产乱肥老妇国产一区二 | 午夜国产高清精品一区免费 | 国产一区二区免费在线观看 | 国产sm重味一区二 | 国产一级特黄aa大片线观看 | 日本欧美中文日韩v在线 | 国产一区二区三区不卡在线 | 国自产在线精品 | 国产午夜福利不卡在线观看 | 九九精品电影 | 日韩欧美国产一线 | 欧美激情视频在线播放 | 美女视频免费观看18网站 | 欧美在线三级艳情网站 | 亚洲色一区二区三区四区 | 亚洲欧美日韩综合在线丁香 | 免费观看视频成人国产 | 日韩~欧美一中文字幕 | 欧美日韩乱一区二区 | 日韩在线不卡 | 成人午夜污污在线观看网站 | 制服丝袜亚洲中文综合 | 国产99精品在线观看 | 亚洲色偷偷综合亚洲v | 精品精品国产自在97香蕉蜜芽 | 日韩精品午夜视频一区二区三区 | 丁香伊人 | 传媒视频免费在线 | 国产情侣真实露脸在线最新 | 日韩另类| 亚洲一区二区在线欧洲 | 野花影视 | 免费午夜拔丝袜 | 欧美日韩国产高 | 成人福利精品一区二区 | 国产伦精品一区二区三区视 | 欧美激情亚洲激情 | 欧美性色欧美a在线观看 | 最新国产亚洲人 | 亚洲精品中文字幕视频网站 | 60老熟女多次高 | 桃色在线观看 | 91色琪琪电影亚洲精品久 | 日日插人人插天天插 | 伦理电影我不卡87 | 成人品观看免费 | 国产第一页浮力影院草草 | 国产日韩在线视看高清视频手机 | 综合精品网成人影院 | 国产福利91网在 | 91精品专区国产盗摄 | 国产一级理论在线电影 | 日韩中文精品 | 日本高清不卡中文字幕 | 国产嘿嘿嘿视频在线观看 | 欧美国产亚洲一区 | 非洲一级婬片免费放天天 | 不卡国产精品欧 | 国产精品三区四区 | 国产观看免费在线久 | 成人一级午夜激情网 | 亚洲aⅴ无 | 午夜神器 | 精品美女一级一区二区三 | 中文字幕精品一区二区 | 成人免费一区二区 | 伊人影视在线观看日韩区 | 91精品福利在线观看 | 国产高清一区二区三区视频 | 精品福利在线视频 | 国产另类巨| 66精品综合久 | 国产免费高清在线精品一区 | 9191精品国产日本欧美 | 成年女人 | 国产v在线在线观 | 亚洲国产无线乱码在线观看 | 欧美中日韩免费观 | 国产精品天干 | 欧美yw精品日本国产精品 | 欧美性爱大全在线观看 | 中文字幕日韩精品中文区 | 亚洲色一色噜一噜噜噜人与 | 精品乱码一卡2 | 成年在线网站免费观看无广告 | 精品一区二区三区免费 | 欧美人与性囗牲恔配 | 网站91| 国产美女在 | 国产偷窥不卡视频 | 另类专区亚洲97在线视频 | 亚洲欧美日本韩国 | 欧美三级欧美一级在线视频 | 男女激情 | 国产精品亚洲日本 | 费精品国产一区国产精品剧情在线 | 国产91小视频在线观看 | www.成人影片 | 国产精品日韩剧情欧美 | 国产盗摄在线观看 | 97色伦在色在线播放三级 | 国产在视频精 | 亚洲91视| 国产男女性潮高清免费网站 | 欧美特黄特色三级视频在线观看 | 免费国产在线精品一区二区 | 欧美猛交xxxx乱大交 | 国产福利不 | 欧美国产日韩在线播放成人 | 日本人的色道www免费一区 | 欧美日韩一区二区三区精选 | 成人精品一区二区电影 | 日本黄本道一区二区在线观看 | 日韩一区二区三区免费网站 | 国产福利免费在线观看 | 日本高清一区二区三区欧美 | 亚洲精品网址在线观看 | 欧美日韩一区二区不卡在线播放 | 日本精品一区二区中文字幕 | 91福利国产极品美女在线观看 | 国产精品一区二区高清在线 | 91精品专区国产盗摄 | 亚洲第一影院中文字幕 | 成人国产高清在线观看 | 两性色午夜视频在线观看 | 呦呦精品| 直播app下载 | 另类?欧美?偷窥?日韩?综合 | 半岛影院一级真人片 | 亚洲制服丝袜一区二区三区 | 91电影院| 99中文字幕精品国产 | 国产乱婬| 国自产拍在线网站 | 丰满岳乱一区二区三区在线观看 | 日本中文字幕有码 | 欧美日韩国产精品二区在线观看 | 国产欧美亚洲精品综合在线 | 国产日韩欧美911 | 蜜桃国产在线观看网址 | 欧美高清中文字幕综合网 | 欧美日韩专区一区二区三区 | 国产在观线 | 91精品最 | 日国产一区三区三区在线观看 | 在线观看免费人成视频国产 | 日本α片| 日本免费人成黄页在线观看视频 | 日本韩国欧美三级在线 | 无遮无挡三级动态图 | 日本乱码一区二区三区视频 | 最近最好的2025中文日本字幕 | 蜜臀国产在| www日韩中文字幕在线看 | 国产精品免费视频一区一 | 在线日本有码中文字幕 | 成年黄页网站大全免费看 | 观看国产色| 日韩精品制服诱惑中文字幕 | 日韩亚洲一区二区中文字幕 | 成年女人| 在线视频一区二区不卡 | 91视频精品全国免费观看 | 天天综合网日韩欧美影视导航 | 成人**免费播放 | 韩国a级特黄特 | 国产中文视频一区在线 | 99视频精品在| 成年入口无 | 日本亚洲国产黄m | 欧美床戏吻戏摸下面吻胸 | 亚洲无线码高清在线观看 | 日韩另类在线一区二区三区 | 日本一二三本道 | www成年人视频 | 日韩伦理电影大全 | 日本一道在线免费观看 | 国产亚洲无 | 日本黄大片在线观看视频 | 日韩精品一区二区三区免费看 | 二区三区99| 青青久热| 日本不卡中文字幕免费 | 好吊色在线免费 | 日本一区二区精品免费 | 87国产私拍福利精品视频 | 大伊香蕉精品一区在线 | 亚洲欧美色一区二区三区 | 真正国产人妖ts系列 | 91福利一区日本精品国产 | 亚洲а∨天堂在线网站 | 天堂在线8一区二区三区 | 午夜熟女插插xx免费视频 | 国产萌白酱在线一区二区 | 国产一区二区免费不卡在线播放 | 欧美日韩1区2区国产线 | 国产区激情区精品视频区一99 | 日韩欧美国产另类 | 国产一区免费在线观看 | 国产免费大黄 | 国产成a人亚洲精∨ | 国产制服丝袜观看 | 国产黑色丝袜美女在线观看婷 | 国产精品v国产在线观看a | 韩国一级真人片a级免观看 国产免费一级视频在线 | www一区二区三区 | 亚洲第区| 亚洲综合在线一区二区三区 | 另类亚洲图区在线视频 | 国产精品女厕嘘嘘视频 | 国产自拍偷拍在线一区二区 | 日韩在线观看免费完整版 | 国语自产拍精品香蕉在线播放 | 欧美中文字幕综合在线视频 | 日韩精品一区二区三线 | 中文字幕一区二区不卡 | 欧美一区二区三区视频在线观看 | 成人激情在线 | 精品国产女主播在线观看 | 国产熟女乱子伦露 | 国产香蕉尹人在线 | 日韩电影免费在线观看视频 | 4k影视资源免费在线观看 | 日本香蕉尹人在线视频 | 亚洲无线一二三四区手机 | 神马午夜影院 | 精品国产9| 成人国内免费精品视频在线观看 | 青青青国产观91 | 国产精成a品人v在线播放 | 三年在线观看免费完整版中文 | 成人国内精品久 | 午夜福利电影院 | 国产日韩欧美亚洲视频观看 | 青青河边草免费高清电影 | 日韩国产卡一卡二卡三卡四 | 亚洲五月综合缴情婷婷 | 99国产精品欧美一区二区三区 | 欧美日韩精品一区二区视频 | a在线视频| 国产制服美女在线观看 | 丰满多毛的陰户 | 成人午夜污污在线观看网站 | 免费最新电视剧 | 国产亚洲欧美第一页在线观看 | 国产又爽又湿又色的视频 | 国产欧美羞羞视频 | 免费成年人影片 | 91精品国产自产在线观永久 | 国产欧美日韩综合在线一 | 国产日韩高清制服一区 | 国产女人成人精品视频 | 欧美地区一二三区 | 激情欧美日韩一区二区 | 日本三级中文字版电影 | 国产日韩手 | 欧美日韩综合精品网站视频 | 色一情一乱一乱一 | 亚洲视频99| 成人91污污污在线观看 | 日韩视频中文字幕视频一 | 国产精品一区二区久 | 成年人网站在线免费观看 | 久热中文字幕播 | 日本高清视频在线www色下载 | 国产亚洲久一区二区 | 韩国一级 | 人妖一区二区在线观看 | 国产欧美va欧美va香蕉在线 | 精品视频在线播放一区二区三区 | 欧美日韩大片在 | 国产性生大片免费观看性 | 欧美性猛交ⅹxxx乱大交 | 在线视频一区二区三区在线播放 | 全部免费的电视剧大全 | 国产精品免费在线观看 | 大片在线观看 | 国产又粗又猛又黄又爽无遮 | 日韩在线观看视频网站 | 一级视频亚洲视频在线观看 | 日韩在线免费看网站 | 国产喷水大秀在线观看2025 | 日本免费精品一区二区三区 | 亚洲一线产区二线产区精华 | 片在线观看导航 | 18视频免费网址在线观看 | 国产日韩欧美视频等最新内容! | 国产美女爽到喷出水来视频 | 国产精品酒店在线精品 | 国产爽片在线观看 | 青青草原亚洲之五月婷 | 日日夜夜精品免费视频779 | 不卡一区二区 | 国产卡一卡二卡三卡四卡免费 | 大学生一一级 | 国语在线看免 | 播放灌醉水嫩大学生国内精品 | 国产欧美日韩精品综合在线 | 国产欧洲野花视频www | 99热久re这里只有精品小草 | 国产性爱自拍视频 | 日本精品一区二区三区 | 高清欧美性猛 | 九九热在线视频观看 | 国产一区二区三区精彩视频 | 加勒比综合精品 | 亚洲国产精品自在现线让你爽 | 国产精品毛 | 亚洲aⅴ乱码一区二区波多野 | 日韩亚洲欧美一区二区三区 | 欧美变态口味重另类在线视频 | 88国产精品欧美一区二区三 | 国产ol丝袜高跟在线观看不卡 | 国产+成+人+亚洲欧洲自线 | 日本剧情片在线播放网站 | 国产羞羞视频在线观看 | 欧美日韩高清国产aⅴ一区 四区免费视频 | 色约约精品免费 | 国产v片成人影院在线观看 日韩欧美在线播放视频 | 亚洲精品成人区在线观看 | 国产高清一区二区三区视频 | 18性欧美xxxⅹ性满足 | 国产男女爽爽爽爽爽爽爽爽 | 国产日本欧美高清免费区 | 日本精品一区二区三区不卡 | 欧美乱妇日本无乱码特黄大 | 国产激情影视综合在线 | 国产va免费高清在线观看 | 欧美在线视频不卡 | 免费观看一级特黄欧 | 国产精品合集一区二区三区 | 成人午夜一区二区三区视频 | 国产又色又爽又黄的视频网站樱 | 国产免费怡红院视频 | 欧美重口另类在 | 中文乱码字幕在线观看播放 | 女同视频一区 | 成人精品一区二区三区中文字幕 | 日本系列1| 欧美日韩国产一区二区三区伦 | 国产午夜电影免费 | aaa在线视频免费观看 | 日韩aⅴ黄日韩a影片 | 国产偷窥盗拍丰满老熟女 | 日韩高清在线精品观看网站免 | 精品国产亚洲国 | 国产第37页屁屁影院 | 国产精品综合一区二区三区 | 欧美精品视频在线观看 | 亚洲区视频在线观看 | 国产盗摄精品一区二区三区 | 日本www视频男人的天堂 | 91夜色| 国产手机| 国产伦精品一一区二区三区高清版 | 国产精品视频免费一区二区 | 欧美日韩国产另类一区二区三 | 国产91成人 | 中文字幕乱码亚洲无线三区 | 三级a在线视频观看永久 | 免费最新热播韩剧美剧电视剧 | 一日本道伊 | 日韩欧美中文字幕出 | 91精品国产自产在线观永久 | 国产精品一区高清在线观看 | 欧美日韩国产高清精卡 | 欧美日韩视频专区在线播放 | 国产原创剧情经理在线播放 | 国产精品色哟哟网站 | 国产精品v欧美性爱v | 片视频免费观看 | 免费观看全黄做爰的视频 | 成人影片一区免费观看 | 国产骚系列在线观看 | 国产日韩高清制服一区 | 成人免费一区二区三区 | 国产福利一区二区三区四区 | 俺去也短剧网 | 不卡一卡二卡三 | 欧美特黄特刺激a一级淫片 欧美日韩免费 | 国语精品91自产拍在线观看二区 | 无人视频免费观看免费视频 | 亚洲欧美日韩国产另例 | www亚洲精品在线观看 | 日韩欧美国产 | 精品福利一区二区在线观看 | 韩国三级大全中文字幕网址 | 日韩一本到亚洲男人的天堂 | 国产精品偷窥熟女欧美激 | a天堂中文在线天堂资源中文 | 日本高清视频在线免费观看 | 精品国产污免费网站在线观看 | 国产亚洲午夜影视在线观看 | 一区二区三区在线观看免费 | 国产欧美va欧美va日韩精品 | 精品国产成a人在线观看 | 韩国一级| 成人午夜 | 香港一区二区三区 | 免费看成人国产一区二区 | 亚洲精品自在在线观看 | 大香网伊| 国产精品视频美女在播放 | 日韩电影免费观 | 国产一区二区三区精品91 | 91国内视频在线 | 在线日韩中文字幕 | 97se亚洲| 在线观看国产视频黄 | 国产视频网站在线观看 | 国产传媒在线观看视频免费观看 | 日韩中文字幕在线视频 | 国产主播在线观看不卡 | 国产精品一区二区三区在线观看 | 国产中文字幕在 | 国产99久60在线视频 | 日本精品大乳一区 | 人综合在线观看 | 国产精品视频二区在 | 国产人成精品综 | 日本伦理电影123网站 | 亚洲日本一区二区三区在线不卡 | 国产乱妇乱子在 | 蜜桃视频一区二区在线观看 | 日韩高清码中文字幕日韩 | 最近中文2025在线观看免费 | 日韩欧美亚洲1区2区 | 国产精品一区二区制服 | a在线看| 日本高清视频在线免费观看 | 免费亚洲国 | 欧美yjizz视频网mht | 91最新国产 | 陪读麻麻张开腿让我爽了一夜 | 国产美女主播在线观看 | 91国内外精品自在线播放 | 国产极品尤物va在线精品 | 欧美日韩中文字幕视频不 | 中文字幕日本有码视频在线 | 国产日韩欧美一线 | 综合亚洲欧美日韩一区二区 | 日韩网友自拍区 | 欧美va在线观看 | 最近高清中文在线字幕在线观看 | 国精产品一区一区三区免费视频 | 国产精品一线 | 精品在线观看三级国产 | 亚洲国产日韩欧美高清片a 99精品在线视频 | 国产黄在 | xxx波多野 | 日a本亚洲中文在线观看 | 日韩一区二区三区视频在线观看 | 中文字幕永久在线日本高清dvd | 高清在线观看视频 | 国产亚洲一区二区三区综合片 | 日韩中文高清在线 | 精品国产午夜福利在线观看蜜月 | 国语自产免费精品视频一区二区 | 男人j放进女人p全黄在线 | 国产一区二区三区免费观看在线 | 日韩免费在线视频观看 | 亚洲aaaaa特级 | 欧美日韩精品一区二区三区高清 | 999在线视 | 精品香蕉一区二区三区 | 免费不卡影院 | 中文字幕在线不卡 | 欧美日韩精品一区二区三区 | 国产九九视频在线观看 | 国产日韩欧美亚 | 丁香花在线视频观看免费 | 国产美女一区二区在线观看 | 追剧不等待 | 亚洲日本欧美综合在线一 | 国产在线视频二区不卡视频免费 | 男人的天堂国产综合 | 亚洲愉拍国产自免费 | 99精产国品一二三产区区 | 好看的电影电视剧大全 | 337p极品| 日本国产在线播 | 国产高清一区二区三区四区 | 日本一区二区在线视频 | 边做边爱完整版免费视频播放 | 国产二区三区午夜免费视频 | 国产亚洲视频网站 | 精品国产一区二区三区香 | 国产一级精品视频 | 国产成年大片免费视频播放 | 国产精品亚洲第一区不卡原创 | 国产日韩一区二区三区在线播放 | 综合乱伦自拍影视 |