国产精品青草久-国产精品情侣愉拍-国产精品区网红主-国产精品区一区二-国产精品热久久-国产精品热热热-国产精品人aⅴ-国产精品人成在线-国产精品人妻人伦-国产精品人人

金喜正规买球

工作流的實現(在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ⅴ人片在线观看www | 成人性视频欧美一区二区三区 | 少妇高潮喷水久久久久久久久 | 久久99久久精品免观看吃奶 | 欧美一区二区三区久久成人 | 国产白丝丝高跟在线观看 | 99精品亚洲 | 亚洲av乱码一区二区三区 | 国产熟女一区二区三区浪潮 | 98国产在线观看精品 | swag精品电视剧在线观看 | 精品成人av一区二区三区 | 无限国产资源好片2025 | 国产精品不卡免费视频 | 在线看所有av的网站 | 国产剧情调教在线 | 亚洲成a人片在线播放器 | 亚洲精品无码久久久久 | 日韩电影免费在线观看网站 | 国产午夜激无码αv毛片久久 | 丰满人妻一区三区 | 国产日韩精品一区二区在线播放 | 国产精品自产拍在线观看免费 | 亚洲av乱码久久精品蜜桃 | 亚洲国产天堂久久综合 | 久久99热66这里只有精品一 | 内射人妻无码色av麻豆 | 麻豆国产一级片在线观看 | 人妻av中文系列 | 99久久免费国产特黄 | 99热这里国产免费久久 | 国产在线无码一区二区三区 | 天天射天天操天天干中文字幕 | 97干视频| 无码av久久久久久久久 | 91se在线观看一区二区 | 人妻无码熟妇乱又伦精品视频 | 亚洲国产精品无码久久电影 | 午夜成人a片精品视频免费观看 | 国产精华液一线二线三线 | 国产亚洲精品va片在线播放 | 亚洲一区二区美女av | 亚洲av无码一区二区三区在线 | 亚洲精品无码高潮喷水a片小说 | 国产一级在线观看视频 | 国产高清无密码一区二区三区 | 精品国产91久久久久久无码 | 日日噜噜夜夜爽爽狠 | 国产在线一区二区三区无码 | 亚洲国产精品网站在线播放 | 欧美日韩人妻精品一区二区三区 | 国产一级按摩精油电影 | 亚洲v日本v欧美v综合v | 99久久99久久精 | 中文国产高清综合乱色视频在线播放 | 99久久精品免费看国产一区二区 | 少妇被躁爽到高潮无码文 | 97国产喷水福利在线二区 | 无码aⅴ精| 国产乱人伦偷精品视频 | 亚洲国产www | 怡红院怡春院欧美精品 | 国产无码精品久久久久久久 | 97久久精品人妻人人搡人人玩 | 亚洲国产高清美女在线观看 | 国产成人精品久久亚洲高清不卡 | 日本爽妇网 | a级毛片免费高清视频 | 日韩亚洲人成 | 无码天堂亚洲国产av麻豆 | 在线一区视 | 精品日韩一区二区三区av蜜桃 | 无码偷窥清纯综合图区 | 人妻无码久久一区二区三区免费 | 国产精品欧美在线另类小说 | 亚洲一区精品在线影视 | 日韩人妻无码一区二区三区久久99 | 欧美午夜激情久久久久久 | 午夜福利在线观看一区二区 | h漫无码动漫av | 国内精品久久久久久99 | 妇女精品一二区 | 国产亚洲精品久久久美女 | 羞羞影院午夜男女爽爽免费 | 欧美日韩精品一区二区三区高清视频 | 自拍熟女日韩高清 | 无码国产伦一 | 国产精品天天看 | 国内精品自线一区二区三区 | 亚洲熟妇av一区二区三区 | 91香蕉视频成人 | 国产一区二区精品久久呦 | 亚洲中文字幕网资源站 | 日韩精品 | 91传媒完整版高清在线观看 | 人妻免费公开在线视频 | 亚洲女人的天堂网观看 | 日本国产一区二区三区 | 日本a级精品一区二区三区 日本a片把舌头伸进 | 亚洲综合久久久久久888 | 亚洲一区二区三区播放在线 | 无码aⅴ免费一区二区三区 无码av | 狠狠色噜噜 | 欧美亚洲自拍日 | 麻豆果冻传媒av人妻少妇无码 | 国产三级a毛视频在线观看 国产三级a三级三级 | 国产在线观看私人影院 | 国产91色综合久久麻豆 | 91亚洲精品乱码久久久久久蜜桃 | 中文字幕久久久 | 国产精品日韩幕无码不卡 | 一区二区三区日本视频 | 国产无套专区 | 波多野结衣在线观看一码 | 亚洲av久播在线观看 | 亚洲日本中文字幕乱码在线 | 久别的草原电视剧免费观看高清 | 国产精品国产自 | 国产免费a级在线观看 | 91精品国产闺蜜国产 | 亚洲av乱码一区二区三区按摩 | 97国产婷婷综合在线视频 | 天天综合久久一区二区 | 亚洲毛片网| 亚洲国产精品高清在线观看 | 99久无码中文字幕 | 精品国产专区91在线尤物 | 一区二区亚洲av无码 | 日本午夜精品一本在线观看 | 国产一区二区 | 国产成人精品午夜福利2025 | 欧美一区二区久久精品 | 在线免费视频 | 91精品最新国内在线播放 | 特级毛片a级毛片免费观看网站 | 二区三级国产成人精品人人 | 97色伦背后的神秘故事与深刻思考 | 欧美婷婷六月丁香综合 | 91极品女神私人尤物在线播放 | 无码国产69精品 | 亚洲午夜一区二区三区在线观看 | 99久久人人爽亚洲精品美女 | 在线免费观看成年人视频 | 国产人妖xxxx | 国产乱国产乱老熟300部视频 | 精品少妇爆乳无码aⅴ区 | 日本人妻丰满熟妇久久久久久 | 午夜亚洲精品福利一区二区 | 99热app下载| 日本乱偷人妻中文字 | 91亚洲精品乱码久久久久久蜜桃 | 国产成人精品免高潮在线观看 | 精品区一区二区三 | 欧美精品三级一区二区三区 | 国产尤物精品 | 亚洲av无码乱码一级毛片色欲 | 国产欧美在线一区二区三区 | 黄网站色视频免费观看无码一区 | 欧美性大战xxxxx久久久√ | 亚洲日本欧美中文幕 | 国产尤物精品 | 黄a大片av永久免费 黄瓜视频在线观看 | 国产福利91精品在线观看 | 最新欧美精品一区二区三区 | 日韩精品欧美在线视频在线 | 在线观看国产一区二区三区 | 午夜成人理论无码电影在线播 | 国产精品99久久久久久 | 日韩av成人一区二区三区 | 久久不见久久见免费影院www日本 | 97国产精品 | 午夜理论片精品国产 | 欧美一区二区三区黑人免费 | 午夜成人精品福利网站在线观看 | 国产一级特黄在线播放 | 亚洲av无码1区2区久久 | 精品国产麻豆 | 中文字幕1区无码影片 | 亚洲av一级在线免费观看 | 午夜无码国产理论在线 | 国产有码无码精品在线 | 免费无码av片在线观 | 99精品免视看 | 91精品福利尤物视频 | 日韩在线视频一区二区三区 | 亚洲无码原创 | 成人看片黄a免费看在线 | 国产在线观看免费 | 亚洲精品影院在线观看 | av片在线观看永久免费 | 国产成人久久综合777777麻豆 | 日韩人妻系列无码专区三级 | 另类专区精品 | 亚洲精品少妇久久久久久希岛爱理 | 91人妻人人澡人人爽人人玩 | 日本护士╳╳╳hd少妇 | 国产精品毛片av一区二区 | 99久久天天躁狠狠躁夜夜躁 | 91在线播放免 | 午夜亚洲日本在线 | 国产91精品在线观看导航 | 国产午夜成人久久无码一区二区 | 69日本精品成人无码视频 | 午夜男女爽爽视频在线观看 | 日韩人妻香蕉网在线 | 果冻传媒独家原 | 国产一级二级三级在线观看 | 91香蕉视频观看精品在线 | 国产精品国产自线 | 国产欧美日韩综合精品一区二区三 | 精品久久国产视频 | 97人妻免 | 国产日韩久久久 | 精品国产乱码久久久久 | 91人妻精品无码ww九色 | 蜜臀av在线播放一区二区三区 | 欧美一区二区三区激情 | 欧美精品网站一区二区三区 | 国产精品一区二区av麻豆 | 色视频综合无码一区二区三区 | 国产欧美日韩一区二区三区蜜桃 | 中文成人无码精品久久久 | 国产欧美整片∧v | 91亚洲国产成人久久精品蜜臀 | 国产亚洲综合精品一区二区三区 | 精品视频无码一区二区三区 | 国产高潮白浆加无码 | 日韩经典欧美一区二区三区 | 精品视频一区 | 日韩一级a欧美成人 | 九色91| a级毛片免费网站 | 国产色欲色欲色www无码 | 久久东京国产中文字幕 | 亚洲综合精品网站在线观看 | 日韩精品一区二区三 | 欧美色欲激情视频一区二区三区 | 无遮挡国产高潮视频免费观看 | 精品久久aⅴ人妻中文字幕 精品久久av电影 | 日韩电影免费在线观看网站 | 欧美午夜理伦三级在线观看 | 国产精品人妻一区二区三区四 | 日韩毛片无码永久免费看 | 怡红院成永久免费人全部视频 | 99精品久久毛片a片 99精品免费在线观看 | 国产美女口爆吞精一区二区 | 国内视频在线精品一区 | 韩国r级无码电影在线观看 韩国r级无码片在 | 国产一区二区精品久久呦 | h漫无码动漫av | 91久久精品国产91性 | 99热国产这里只有精品久久 | 久久成年 | 在线观看免费人成视频色9 在线观看免费视频一区 | 国产av无码久久 | 91网址 | 午夜亚洲理论片在线观看 | 亚洲无码在线播放 | 国产精品高清另类一区二区三区 | 国产欧美日韩在线观看影院 | 日韩电影| 成人涩涩小片视频日本 | 亚洲精品无码久久久久av老牛 | 欧美日韩一区二区三区在线播放 | 无码中文字幕a | 国自产精品手机在线视拍 | 亚洲a∨毛片无码专区国产乱码 | 一区二区国产精品 | 国产一区二区精品久久91 | 性色av一二三天美传媒 | 成人精品动漫一区二区三区 | 99久久综合精品五月天 | 成人免费无码大片a | 国产高清色播视频免费看 | 国产va免费精品高清在线 | 亚洲国产精品无码久久久久久曰 | 久久er99热精品一区二区 | 高潮喷奶水在线播放视频 | av天堂午夜精品一区二区三区 | 中文字幕乱码一区二区免费 | 国产在线看片免费人 | 成人午夜精品无 | 欧美色欲成人一区二区三区 | 99热免费版官方下载安装v2.0 | 久草免费在线 | 日本动漫在中国大陆传播分析 | 中文字幕免费大全日本一片 | 欧美日韩国产第 | 熟妇人妻系列v无码一区二区 | 精品国产午夜理论片不卡 | 99久久精品午夜一区二区 | 成人午夜视频精品一区 | 精品中文字幕免费在线观看 | 国产av熟女一区二区三区 | 99精品众筹模特实拍[碧蓝的世界] | 91精品欧美激情在线播放 | 精品无码不卡中文字幕 | 国产强伦姧在线观看 | 午夜影院一区二区三区 | 岛国大片在线一区二区三区 | 国产综合精品91 | 色狠狠色狠狠综合天天 | 日韩理论电影在线观看 | 中文亚洲av片在线观看不卡 | 91亚洲国产成人久久精品 | 国产精品亚洲一区 | 亚洲无码大片在线观看 | 国产欧美日韩一区二区三区 | 综合欧美综合欧美色 | 亚洲视频一区二区在线观看 | 国产av无码专区亚洲av中文 | 四虎国产精品永久免费网址 | 97精品人人做人人爱 | 亚洲精品久久久中文字幕痴女 | 国产欧美日本在线观看 | 亚洲av无码乱码精品国产九色 | 国语91 | 人妻少妇久久久久久97人妻 | 日本欧美一区二区三区乱码 | 高清一区二区三区尤物 | 亚洲av无码专区在线观 | 国产乱人| 亚洲aⅴ无码码潮喷在线观看 | 深夜国产一区二区三区在线看 | 国产一级在线观看www色 | 成人性爱视频网站 | 精品国精品国产自在久国产 | 日本高清在线播放一区二区三区 | 午夜精品久久久久久久无码 | 日韩精品视频在线第一区 | 国产精品一区久久 | 国产愉拍精品视频手 | 精人妻无码| 69国产成人综合久久精 | 熟女丰满:丰盈之美 | 欧美日韩aⅴ一区二区三区 欧美日韩变态另类在线观看 | 精品一区二区三区国产在线观看 | 成人一区二区三区视频 | 成人在线高清 | 精品一区二区国语对白 | 精品国产免费看久久久 | 黑料不打烊吃瓜 | 欧美日韩aⅴ精品大片 | 国产女明星专区视频在线播放 | 91香蕉成人app最新版官网 | 国产成人精品免费视频大全麻 | 亚洲性爱av免费在线播放 | av老司机午夜福利片免费观看 | 国产良妇出轨视频在线观看 | 亚洲av日韩av高潮无码专区 | 无码一区二区三三精品视频久久久 | 久久99精品久久久久婷婷 | 久久av无吗不卡 | 91麻豆果冻天美精东蜜桃传媒 | 久久99精品久久久久久久不卡 | 高清一级片 | 老司机免费视频福利0 | 99久久毛片无码一区二区三区 | 亚洲国产成人一区二区精品区 | 国产91亚洲中文天堂在线观 | 欧美日韩第一区 | 国产曰的好深好爽免费视频 | 无码乱人伦一区二区亚洲一 | 在线不卡免费高清播放av网站 | av中文一区二区三区桃花岛 | 少妇高潮无套内谢麻 | 91熟妇在线视频 | 91免费国产视频久久久 | 在线视频www色 | 国产精品高清一区二区三区久久你 | 国产偷抇久久精品a片蜜臀a | 果冻传媒视频在线播放 | 人人干在 | 国产好吊妞视频在线 | 午夜福利伦伦电影理论片在线观看 | 国产aⅴ精品一区二区三区 国产aⅴ精品一区二区三区久久 | 国产精品原创巨作无遮挡 | 欧美中国一级黄色网站 | 麻豆国产av巨作国产剧情 | 黄色毛片成年人a级片 | 免费无码片国产在线观看 | 99久久国产综合精品五月天喷水 | 91亚洲精品国产自在现线 | 久久波多野av | 无码国产伦一区二区三区视频 | 亚洲成av人无码综合在线 | 人妻少妇精品久久久久中文 | 国产又色又爽又黄刺激视频 | 东京热人妻系列无码专区 | 亚洲精品第一页 | 国产成人精品亚洲av无人区一区 | 亚洲国产欧美一区二区三区 | 国产欧洲黄色一级片视频 | 99久久精品熟女高潮喷水免费 | 色婷婷日韩精品一区二区麻豆 | 亚洲中文字幕永久有效 | 国产亚洲成在线播放va电影 | 成人老司机深夜福利久久 | 国产午夜亚洲 | 特级黄绝一级在线观看不卡 | 日本大片免a费观看视频老师 | 极品无码一区二区三区 | 日本一品道无码免费专区在线观看 | 国产三级精品三级在线专 | 日本免费人成视频在线观看 | 亚洲精品无码高潮喷水a片软 | 91国产天堂网 | 97超开公碰在线视频 | 99久久精品国产一区二区三区 | 国产美女精品 | 亚洲国产一成久久精品国产成人综合 | 中文字幕精品一区二 | 日本免费一区二区三区最新 | 成人免费无码一区二区三区 | 成人电影免费观看 | αv天堂在线观看免费αⅴ αv在线视频免费观看男人 | 亚洲av午夜福利精品一区二区三 | 97无码人妻视频在线 | 日本一区二区三区免费在线观看 | 黄a大片av永久免费 黄瓜视频在线观看 | 亚洲av成人精品日韩在线播放 | 一区二区无码 | 99视频国产精 | 91免费无码国产在线观看i | 国产精品网站在线观看免费传媒 | 亚洲精品中文字幕不卡在线 | 亚洲午夜免费视频 | 亚洲91av视频在线观看 | 精品国产欧美一区二区 | 毛片a片高潮喷水免费看 | 97精品伊人久久 | 日本精品不卡在线观看 | 亚洲精品一线在线观看 | 国产精品久久久久精品综合 | 日本欧美大码一区二区 | 99久久国产综合精品五月天喷水 | 国产成人精品免高潮在线观看 | 亚洲精品色婷婷在线影院 | 日本一道本不卡免费播放 | 日本啪视频在线观看精品综合 | 国产午夜福利一区二区播 | 国产作爱视频免费播放 | 精品国产成人亚洲午夜福利 | 亚洲精品高清αv在线播放 亚洲精品高清国产 | 极品少妇一区二区三区四区 | 九九热精品在线视频观看 | 99久久网站 | 极品私人尤物在线精品视频 | 亚洲无码在线播放 | 色婷婷综合和线在线 | 国产精品2025观看久久 | 国产一级久久久免费看 | 福利视频99 | 国产片精品一区在线播放 | 亚洲av日韩av天堂影片精品 | 精品国产a∨无码一区二区三区 | 国产做爰xxxⅹ性视频国 | 国产人妻精品一区二区三区不卡 | 999在线视频精品免费播放观看 | 国产精品三级av及在线观看 | 国产aⅴ精品一区二区三区 国产aⅴ精品一区二区三区久久 | 国产精品vi | 亚洲av综合永久无码精品天堂 | 高跟丝袜| 欧美色欲激情视频一区二区三区 | 人妻少妇精品无码专区二区 | 亚洲aⅴ中文无码字幕色 | 黄色免费国产小视频 | 国产日韩欧美日韩欧美 | 午夜视频国产 | 国产系列丝袜熟女精品视频 | 日韩一区二区中文字幕 | 国产精品无码在线观看 | 精品亚洲av无码 | 欧美日韩视频在线第一区 | 黄色视频免费观看 | 国产欧美另类久久 | 国产农村 | 欧美日韩高清中文在线 | 免费无码片国产在线观看 | 99久久国产精品免费热6 | 精品国产91av自在自线麻豆 | 亚洲精品国产a久久久久久 亚洲精品国产va在 亚洲精品国产啊女成拍色拍 | 91探花国产 | 天天看天天射 | 国产男女无遮挡猛进猛出 | 国产一区二区在线播放 | 色婷婷av国产精品欧美毛片 | 国产精品视频免费观看 | 91精品人妻一区二区三区 | 97久久超碰成人精品网页 | 色婷婷综合久久久久中文 | 狠狠色噜噜狠狠狠狠91 | 国产精品一区蜜臀91 | 国产真实露脸乱子伦 | 韩国理论电影午夜三级在线观看 | 国产一国产一级无码网站 | 欧美日韩精品一区二区三区 | 无码av天堂一区二区三区 | 国产成年人免费视频 | 午夜理论片yy4080私人影院 | 亚洲日本成本人观看 | 动漫3d精品一区二区三区乱码 | 91大神精品视频高清免费观看 | 一区二区国产高清视频在线 | 国产白嫩精品久久 | 日韩av一区二区精品不卡 | 无人区麻豆乱码久久久 | 欧美成人精品三级在线观看 | 91九色蝌蚪 | 国产精品对白清晰受不了了 | 亚洲午夜在线观看 | 日本中文字幕一二区视频 | 欧美熟妇三级在线观看 | 国产欧美一区二区三区精品视频 | 亚洲av无一区二 | 无码专区午夜福利在线观看 | 在线观看精品国产福利片2025 | 欧洲人体亚洲 | 无码免费午夜福利看片 | 综合三级免费日本 | 成人嫩草影院免费观看 | 日日夜人人澡人人澡人人看免 | 少妇高潮喷水惨叫久无码一区二区 | 在线天堂8高清版在线观看 在线天堂官网 | 亚洲av无码无限 | 一区二区在线看 | 精品无码不卡中文字幕 | 在线观看成人网站 | 日韩av影视久久 | 国产高清极品美女黄色网站 | 亚洲精品1区2区3区4区 | 高清一级淫片a级 | 国产清纯白嫩美女正无套播放 | 精品国产一 | 成人免费v片在线观看 | 国产精品97久久久久久久 | 午夜精品国产拍精品福利 | 亚洲成av人片天堂网久久 | 亚洲精品无码久久久久av麻豆 | 国产一区二区三区在线免费观看 | 国产美女在线观看 | 日本成人性爱免费在线观看网站 | 国产色秀视频在线播放 | 国产v片成人影院在线观看 国产v片在线播放 | 午夜精品久久久久久久无码 | 福利视频一区二区牛牛 | 欧美又粗又大xxxxbbbb疯狂 | 国产盗摄在线一区 | 国产刺激对白国产情侣 | 国产成人午夜福利在线播放 | 亚洲s色大片在线观看 | 午夜国产在线观看 | 国产精品欧美v片免费观看 国产精品欧美福利久久 | 国产亚洲国产av网站在j | 欧美猛交xxxxx | 成人老司机深夜福利久久 | 欧美日韩在线视频一区 | 国产精品99久久免费观看 | 麻豆毛片| 一区二区国产精品 | 国产黄在线免费 | 99精品国产在热久久无毒 | 国产成人精品久久 | 国产亚洲精品aaaa片在线播放 | 中文字幕色婷婷在线精品中 | 亚洲av永久无码区成人网站 | 精品少妇爆乳无码av无码专区 | 欧美精品久久久久精品 | 国产v亚洲v天堂无码久久久91 | 少妇高潮喷水惨叫久无码一区二区 | 午夜精品久久久久久99热 | 中文字幕1区无码影片 | 国产色视频网站免费 | 国产亚洲精品自在久久 | 国产亚洲系列第一页在线播放 | 亚洲综合极品香蕉久久网 | 亚洲乱码卡一卡二卡新区仙踪 | 91精品人妻一区二区三区浪潮 | 午夜看看av| 成全影院大全在线观看国语 | 午夜成人亚洲理伦片在线观看 | 亚洲精品中文字幕无乱码 | 在线观看91精品国产网站 | 一级片中| 国产精品福利电影一区二 | 日韩精品无码区免费专区 | 3d动漫精品啪啪一区二区免费 | 精品国产av丁香六月无码 | 无人区一码卡二卡三乱码 | 国产探花视频 | 国产旗袍丝袜在线观看视频 | 亚洲欧美成人久久综合中文 | 日本老司机午夜福利视频 | 亚洲一区二区入口 | 九九精品成人免费国产片 | 国产高清日韩 | 国产一级婬片a免费播放口 国产一级婬片a片aaa毛片小说 | 亚洲a∨无码专区亚洲a∨网站 | 国产一级淫片免费大片 | 午夜tv | 亚洲av午夜福利精品一区二区三 | 亚洲s色大片在线观看 | 欧美在线视频一区二区 | 午夜丁香婷婷免费手机在线观 | 国产亚洲第一午夜福利合集 | 国产午夜福利100集发布 | 成人无码h免费动漫在线观看 | 亚洲av无码一区东京热久久 | 午夜视频免费观看 | 超碰国产精品最新 | 国内精品久久久久久久97牛牛 | 日韩精品一区中文字幕在线 | 久久er热在这里只有精品66 | 日本一道本不卡免费 | 神马午夜影院 | 国产成人精品a∨一区二区 国产成人精品aa毛片 | 女人喷液抽搐高潮视频 | 日韩一区二区三区四区区区 | 亚洲国产成人精品久久 | 91精品国产91久久国产作爱视频 | 国产高潮流白浆喷水免费 | 国语精品自产拍在线 | 久久国产福利播放 | 国产乱子经典视频在线观看 | 欧美日韩精品一区二区三区视频在线 | 91精品国产免费青青碰在线 | 日本高清一级婬片a级中文字幕 | 操女优国产成人综合色在线观看网站 | 99精品众筹模特实拍[碧蓝的世界] | 中文字幕无码免费不卡视频 | 亚洲丝袜制服欧美另类 | 国产一道精品视频一区二区三区 | 午夜精品国产电影在线观看 | 日日噜噜夜夜爽爽狠 | 國產在線91精品入口 | 国产高清免费在线观看 | 果冻文化传媒官网 | 无码人妻精品一区二区三区秋 | 97久久天 | 精品久久久久久中文字幕人妻 | 亚洲精品久久久中文字幕痴女 | 国产图色一色屋精品视频 | 国产区精品 | 欧美日韩在线一区二区三区 | 狠狠操一区 | 福利一区二区 | 精品亚洲成av人在线观看 | 亚洲精品无码久久久久不卡 | 91九色porny永久地址 | 91免费精品国偷自产在线在线 | 国产精品一区在线观看播放 | 色综合热无码热国产 | 果冻文化传媒有限公司 | 日韩精品一区二区亚洲av观看 | 日产国产亚洲系列 | 国产99欧美精品久久精品 | 不卡的av在线系列 | 少妇被躁爽到高潮无 | 国产办公室无码视频在线观看 | 99好久被狂躁a片 | 九一国产在线观看 | 国产成人精品一区二区三区… | 国产麻豆成人传媒免费观看 | 日韩欧美国产精品专区 | 精品国产亚洲一区二区三区 | 欧美高清一区三区在线专区 | 免费无码午夜精品电影 | 东京无码熟妇人妻av在线网址 | 97亚洲精华液 | 国产a∨天天免费观看美女 国产a∨天天免费观看美女18 | 亚洲亚洲人成综合丝袜图片 | 三上悠亚精品二区在线观 | 99re6在线视频精品免费下载 | 亚洲日本va中文字幕久久 | 亚洲国产成人精品无码一区二区 | 91探花视频在线 | 精品一区二区三区四区五区六己 | 最新天堂√最新版中文在线99 | 日本高清天码一区在线播放 | 国产伦精品一区 | 97精品久久天干天天蜜 | 国产精品成人无码视频 | 9lporm自拍视频区 | 日本aaaa级| 在线观看欧美亚洲少妇 | 亚洲av中文无码乱人伦在线播放 | 午夜性色福利视频 | 特级毛片爽www免费版 | 欧美色精品视频在线观看免费 | 亚洲欧美另类日韩综合 | 中文午夜人妻无码看片 | 极品丰满少妇xxxhd剃毛 | 午夜福利理论片高清在线观看 | 国产精品初高中精品免费观看 | 天堂网在线观看av | 日韩精品无码综合一区二区 | 国产精品视频久久久 | 91精品国产日韩 | 亚洲v欧洲v | 国产精品香蕉在线观看 | 欧美性色xxxxⅹooo | 欧美精品一国产成人综合久久 | 久久www精品成人 | 国产又粗又 | 亚洲av无码潮喷在线观看 | 在线播放真实国产乱子伦 | 91影视免费版安卓 | 亚洲欧美一| 丰满岳乱妇在线观看中字无码 | 精品人妻一区二区三区浪潮在线 | 亚洲av永久天堂在线观看 | 91国内精品久久 | 91在线啪国自产观看高清频道 | 国产啪精品视频网给免丝袜 | 国产蜜桃午夜亚洲精品电影网 | 九九精品一区二区三区 | 精品视频一区二区噜噜 | 91se在| 国产精品美女一区二区三区 | 91久久久久国产一区二区 | a品人v在线播放 | 亚洲中文字幕aⅴ天堂自拍 亚洲中文字幕aⅴ无码天堂 | 97超碰在线播放 | 精品一区二区三区在线 | 3d经典动漫影片推荐! | 国产精品99久久久久久一二区 | 色婷婷在线观看视频 | 在线观看黄aⅴ免费观看 | 亚洲av无码成人专区 | 久久99精品久久久久久噜噜噜 | 99精品国产免费观看 | 97在线观看永久免费视频 | 东京一区二区三区高清视频 | 亚洲av片无码久久尤物 | 在线观看国产亚洲视频免费 | 日本一道本不卡免费 | 国产aⅴ一区二区三区精品 国产aaaa | 在线美剧天堂 | 国产福利萌白酱精品tv一区 | 久久国产成人精品国产成人亚洲 | 成人伊人精品色xxxx视频 | 精品日本一区二区三区在线观看 | 国精产品999国精产品官网 | 国产精品岛国久久久久 | 国产freesexvide | 国产亚洲欧美日韩国产片 | 欧美日韩高清视频一区二区三区 | 国产一区二区精品久久 | 丰满熟女一区二区 | 特级丰满少妇一级aaaa爱毛片 | 亚洲欧美大码a在线观看 | 91香蕉成人app网站 | 欧美亚州综合久久手機看片影視 | 中文字幕奈奈美被公侵犯 | 99亚洲精品久久电影 | 亚洲国产美女主播在线观看 | 国产av+刺激+无码 | 久久99精品久久久久久hb | 爱豆传媒免费全集在线观看反转爽剧 | 欧美日韩一区二区三区四区在线观看 | 国产成a人片在线观看视频 国产成a人片在线观看视频9 | 特级丰满少妇一级aaaa爱毛片 | 国产精品国产三级国产专播 | 中文精品久久久久国产不卡 | 国产v亚洲v天堂无码卡通 | 丰满少妇乱子伦精品无码专区 | 91福利国产在线观一区二区 | aⅴ无码国产在线看 | 自在自线亚洲а | 人妻无码αv中文字幕久久 人妻无码不卡在线看 | 国产福利一区二区免费视频 | 国产乱人视频在线观看ktv | 国产精品白丝祙喷水视 | 精品一区二区三区的国产在线观 | 91制片厂制作果冻传媒八夷兔子 | 精品熟人妻一区二区三区四区不卡 | 99视频国产精品 | 亚洲欧美另类成人综合图片 | 凹凸国产熟女精品视频app | 国产片av国语在线观看手机版 | 伊人亚洲综合中文字幕 | 亚洲视频手机在线观看 | 欧日韩国产无码专区 | 亚洲无码码视频在线观看 | 91啪在线视频 | 国产成年网站v片在线观看 国产成年无码av片在线 | 欧美精品一级 | 91高清免费国产自产 | 麻豆91精品91久久久的内涵 | 亚洲欧美日韩国产一级a | 国色一卡2卡3卡4卡在线新区 | 日本精品中文字幕在线播放 | 97密桃75hd中字在线观看 | 欧美日韩一区二区三区在线播放 | 国产女人的高 | 成人免费理论片 | 午夜成a人片在线观看 |