Sfoglia il codice sorgente

init fohow git project

abiao 5 anni fa
parent
commit
93acb2c3a4
100 ha cambiato i file con 9821 aggiunte e 2 eliminazioni
  1. 48 0
      Gemfile
  2. 296 0
      Gemfile.lock
  3. 2 2
      README.md
  4. 261 0
      README.rdoc
  5. 7 0
      Rakefile
  6. BIN
      app/assets/images/rails.png
  7. 16 0
      app/assets/javascripts/application.js
  8. 135 0
      app/assets/javascripts/ckeditor/config.js
  9. 5 0
      app/assets/javascripts/ckeditor/plugins/lineheight/lang/en.js
  10. 5 0
      app/assets/javascripts/ckeditor/plugins/lineheight/lang/zh-cn.js
  11. 146 0
      app/assets/javascripts/ckeditor/plugins/lineheight/plugin.js
  12. 7 0
      app/assets/javascripts/rails_admin/custom/ckeditor_ajax.js.coffee
  13. 1 0
      app/assets/javascripts/rails_admin/custom/ui.js
  14. 14 0
      app/assets/stylesheets/application.css.scss
  15. 109 0
      app/assets/stylesheets/rails_admin/rails_admin.scss.erb
  16. 17 0
      app/controllers/application_controller.rb
  17. 4 0
      app/controllers/base_controller.rb
  18. 33 0
      app/controllers/chunjie_config_stat_controller.rb
  19. 39 0
      app/controllers/kaijiang_controller.rb
  20. 7 0
      app/controllers/nianzhong_report_controller.rb
  21. 1551 0
      app/controllers/report_controller.rb
  22. 209 0
      app/controllers/zt_report_controller.rb
  23. 16 0
      app/helpers/application_helper.rb
  24. 0 0
      app/mailers/.gitkeep
  25. 68 0
      app/models/ability.rb
  26. 120 0
      app/models/ad_item.rb
  27. 51 0
      app/models/ad_item_click_statistic.rb
  28. 51 0
      app/models/ad_item_show_statistic.rb
  29. 51 0
      app/models/ad_position.rb
  30. 68 0
      app/models/address.rb
  31. 44 0
      app/models/admin_permission.rb
  32. 19 0
      app/models/admin_permissions_admin_role.rb
  33. 36 0
      app/models/admin_role.rb
  34. 19 0
      app/models/admin_roles_admin_user.rb
  35. 96 0
      app/models/admin_user.rb
  36. 213 0
      app/models/ali.rb
  37. 252 0
      app/models/article.rb
  38. 44 0
      app/models/article_cat.rb
  39. 99 0
      app/models/balance.rb
  40. 112 0
      app/models/balance_order.rb
  41. 108 0
      app/models/cash_balance.rb
  42. 134 0
      app/models/channel_qrcode.rb
  43. 69 0
      app/models/channel_qrcode_result.rb
  44. 5 0
      app/models/ckeditor/asset.rb
  45. 13 0
      app/models/ckeditor/attachment_file.rb
  46. 31 0
      app/models/ckeditor/picture.rb
  47. 36 0
      app/models/common_use_limit.rb
  48. 113 0
      app/models/invite_benefit_order.rb
  49. 68 0
      app/models/key_word_push.rb
  50. 84 0
      app/models/merchant.rb
  51. 80 0
      app/models/merchant_user_relation.rb
  52. 110 0
      app/models/navigate_icon_config.rb
  53. 303 0
      app/models/order.rb
  54. 114 0
      app/models/order_detail.rb
  55. 26 0
      app/models/parent_signup_channel.rb
  56. 118 0
      app/models/poster_qrcode_record.rb
  57. 50 0
      app/models/poster_qrcode_scan_record.rb
  58. 198 0
      app/models/product.rb
  59. 46 0
      app/models/product_cat.rb
  60. 101 0
      app/models/product_picture.rb
  61. 74 0
      app/models/push_after_sub.rb
  62. 139 0
      app/models/push_tmpl.rb
  63. 33 0
      app/models/push_tmpl_record.rb
  64. 96 0
      app/models/recharge_cash_order.rb
  65. 37 0
      app/models/session.rb
  66. 118 0
      app/models/share_info.rb
  67. 646 0
      app/models/share_material.rb
  68. 61 0
      app/models/sign_up_channel.rb
  69. 57 0
      app/models/sign_up_channel_qrcode_result.rb
  70. 168 0
      app/models/take_cash_order.rb
  71. 220 0
      app/models/user.rb
  72. 66 0
      app/models/wx_form_id.rb
  73. 86 0
      app/models/wx_gongzhonghao.rb
  74. 70 0
      app/models/wx_menu.rb
  75. 249 0
      app/models/wx_user.rb
  76. 86 0
      app/models/wx_user_gongzhonghao.rb
  77. 436 0
      app/models/wxku_commodity.rb
  78. 144 0
      app/models/xcx_push_tmpl.rb
  79. 33 0
      app/models/xcx_push_tmpl_record.rb
  80. 34 0
      app/models/xcx_version.rb
  81. 17 0
      app/views/chunjie_config_stat/index.html.erb
  82. 20 0
      app/views/devise/sessions/new.html.erb
  83. 15 0
      app/views/layouts/application.html.erb
  84. 114 0
      app/views/layouts/devise_layout.html.erb
  85. 49 0
      app/views/rails_admin/cash_balance/refuse_takecash.html.erb
  86. 4 0
      config.ru
  87. 79 0
      config/application.rb
  88. 6 0
      config/boot.rb
  89. 35 0
      config/config.yml
  90. 43 0
      config/database.yml
  91. 7 0
      config/environment.rb
  92. 39 0
      config/environments/development.rb
  93. 71 0
      config/environments/production.rb
  94. 45 0
      config/environments/test.rb
  95. 7 0
      config/initializers/backtrace_silencers.rb
  96. 58 0
      config/initializers/ckeditor.rb
  97. 265 0
      config/initializers/devise.rb
  98. 15 0
      config/initializers/inflections.rb
  99. 1 0
      config/initializers/load_config.rb
  100. 0 0
      config/initializers/mime_types.rb

+ 48 - 0
Gemfile

@@ -0,0 +1,48 @@
+# source 'https://rubygems.org'
+source 'https://gems.ruby-china.com'
+
+gem 'rails', '4.2.7.1'#, '3.2.13'
+gem 'mysql2'#, '0.3.18'
+gem 'syck'
+gem "minitest", "5.10.1"
+# Gems used only for assets and not required
+# in production environments by default.
+group :assets do
+  gem 'sass-rails'#,   '~> 3.2.3'
+  gem 'coffee-rails'#, '~> 3.2.1'
+  gem 'bootstrap-sass'
+  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
+  gem 'therubyracer', :platforms => :ruby
+  gem 'uglifier'#, '>= 1.0.3'
+  gem 'compass'#,'0.12.6'
+end
+
+gem 'jquery-rails'
+gem 'unicorn'
+gem 'thin'
+
+#后台管理rails_admin框架
+gem "rails_admin"
+gem "devise"
+gem "cancancan"
+gem "ancestry"
+gem "rails_admin_nestable"
+gem 'ckeditor'#, '~> 3.7.0.rc3'
+# gem 'ckeditor', '4.1.3'
+gem 'paper_trail', '5.2.3'
+gem "paperclip"#, '4.3.7'
+gem 'paperclip-storage-aliyun'
+
+#请求相关辅助类
+gem "rest-client", '~>1.8.0'
+gem "uuid"
+gem "xml-simple"
+gem "chinese_pinyin"
+gem "aliyun-sdk", '~>0.4.1'
+gem "rails_admin_import"
+gem "coffee-script-source"#, '1.8.0'
+gem "safe_yaml"
+gem 'tzinfo-data'
+
+gem 'bcrypt-ruby', '~> 3.0.0', :require => "bcrypt"
+#gem 'rails_admin_example_theme', :git => 'git://github.com/bbenezech/rails_admin_example_theme.git'

+ 296 - 0
Gemfile.lock

@@ -0,0 +1,296 @@
+GEM
+  remote: http://gems.ruby-china.org/
+  specs:
+    actionmailer (4.2.7.1)
+      actionpack (= 4.2.7.1)
+      actionview (= 4.2.7.1)
+      activejob (= 4.2.7.1)
+      mail (~> 2.5, >= 2.5.4)
+      rails-dom-testing (~> 1.0, >= 1.0.5)
+    actionpack (4.2.7.1)
+      actionview (= 4.2.7.1)
+      activesupport (= 4.2.7.1)
+      rack (~> 1.6)
+      rack-test (~> 0.6.2)
+      rails-dom-testing (~> 1.0, >= 1.0.5)
+      rails-html-sanitizer (~> 1.0, >= 1.0.2)
+    actionview (4.2.7.1)
+      activesupport (= 4.2.7.1)
+      builder (~> 3.1)
+      erubis (~> 2.7.0)
+      rails-dom-testing (~> 1.0, >= 1.0.5)
+      rails-html-sanitizer (~> 1.0, >= 1.0.2)
+    activejob (4.2.7.1)
+      activesupport (= 4.2.7.1)
+      globalid (>= 0.3.0)
+    activemodel (4.2.7.1)
+      activesupport (= 4.2.7.1)
+      builder (~> 3.1)
+    activerecord (4.2.7.1)
+      activemodel (= 4.2.7.1)
+      activesupport (= 4.2.7.1)
+      arel (~> 6.0)
+    activesupport (4.2.7.1)
+      i18n (~> 0.7)
+      json (~> 1.7, >= 1.7.7)
+      minitest (~> 5.1)
+      thread_safe (~> 0.3, >= 0.3.4)
+      tzinfo (~> 1.1)
+    aliyun-sdk (0.4.1)
+      nokogiri (~> 1.6)
+      rest-client (~> 1.8)
+    ancestry (2.2.2)
+      activerecord (>= 3.0.0)
+    arel (6.0.3)
+    autoprefixer-rails (6.5.3)
+      execjs
+    bcrypt (3.1.11-x64-mingw32)
+    bootstrap-sass (3.3.7)
+      autoprefixer-rails (>= 5.2.1)
+      sass (>= 3.3.4)
+    builder (3.2.2)
+    cancancan (1.15.0)
+    chinese_pinyin (1.0.1)
+    chunky_png (1.3.8)
+    ckeditor (4.2.0)
+      cocaine
+      orm_adapter (~> 0.5.0)
+    climate_control (0.0.3)
+      activesupport (>= 3.0)
+    cocaine (0.5.8)
+      climate_control (>= 0.0.3, < 1.0)
+    coffee-rails (4.2.1)
+      coffee-script (>= 2.2.0)
+      railties (>= 4.0.0, < 5.2.x)
+    coffee-script (2.4.1)
+      coffee-script-source
+      execjs
+    coffee-script-source (1.11.1)
+    compass (1.0.3)
+      chunky_png (~> 1.2)
+      compass-core (~> 1.0.2)
+      compass-import-once (~> 1.0.5)
+      rb-fsevent (>= 0.9.3)
+      rb-inotify (>= 0.9)
+      sass (>= 3.3.13, < 3.5)
+    compass-core (1.0.3)
+      multi_json (~> 1.0)
+      sass (>= 3.3.0, < 3.5)
+    compass-import-once (1.0.5)
+      sass (>= 3.2, < 3.5)
+    concurrent-ruby (1.0.2)
+    devise (4.2.0)
+      bcrypt (~> 3.0)
+      orm_adapter (~> 0.1)
+      railties (>= 4.1.0, < 5.1)
+      responders
+      warden (~> 1.2.3)
+    domain_name (0.5.20161129)
+      unf (>= 0.0.5, < 1.0.0)
+    erubis (2.7.0)
+    execjs (2.7.0)
+    ffi (1.9.14-x64-mingw32)
+    font-awesome-rails (4.7.0.0)
+      railties (>= 3.2, < 5.1)
+    globalid (0.3.7)
+      activesupport (>= 4.1.0)
+    haml (4.0.7)
+      tilt
+    haml-rails (0.9.0)
+      actionpack (>= 4.0.1)
+      activesupport (>= 4.0.1)
+      haml (>= 4.0.6, < 5.0)
+      html2haml (>= 1.0.1)
+      railties (>= 4.0.1)
+    html2haml (2.0.0)
+      erubis (~> 2.7.0)
+      haml (~> 4.0.0)
+      nokogiri (~> 1.6.0)
+      ruby_parser (~> 3.5)
+    http-cookie (1.0.3)
+      domain_name (~> 0.5)
+    i18n (0.7.0)
+    jquery-rails (4.2.1)
+      rails-dom-testing (>= 1, < 3)
+      railties (>= 4.2.0)
+      thor (>= 0.14, < 2.0)
+    jquery-ui-rails (5.0.5)
+      railties (>= 3.2.16)
+    json (1.8.3)
+    kaminari (0.17.0)
+      actionpack (>= 3.0.0)
+      activesupport (>= 3.0.0)
+    loofah (2.0.3)
+      nokogiri (>= 1.5.9)
+    macaddr (1.7.1)
+      systemu (~> 2.6.2)
+    mail (2.6.4)
+      mime-types (>= 1.16, < 4)
+    mime-types (2.99.3)
+    mimemagic (0.3.2)
+    mini_portile2 (2.1.0)
+    minitest (5.10.1)
+    multi_json (1.12.1)
+    mysql2 (0.4.5-x64-mingw32)
+    nested_form (0.3.2)
+    netrc (0.11.0)
+    nokogiri (1.6.8.1-x64-mingw32)
+      mini_portile2 (~> 2.1.0)
+    orm_adapter (0.5.0)
+    paper_trail (5.2.3)
+      activerecord (>= 3.0, < 6.0)
+      request_store (~> 1.1)
+    paperclip (5.1.0)
+      activemodel (>= 4.2.0)
+      activesupport (>= 4.2.0)
+      cocaine (~> 0.5.5)
+      mime-types
+      mimemagic (~> 0.3.0)
+    paperclip-storage-aliyun (0.1.1)
+      paperclip (>= 3.5.2)
+      rest-client (>= 1.6.7)
+    rack (1.6.5)
+    rack-pjax (1.0.0)
+      nokogiri (~> 1.5)
+      rack (>= 1.1)
+    rack-test (0.6.3)
+      rack (>= 1.0)
+    rails (4.2.7.1)
+      actionmailer (= 4.2.7.1)
+      actionpack (= 4.2.7.1)
+      actionview (= 4.2.7.1)
+      activejob (= 4.2.7.1)
+      activemodel (= 4.2.7.1)
+      activerecord (= 4.2.7.1)
+      activesupport (= 4.2.7.1)
+      bundler (>= 1.3.0, < 2.0)
+      railties (= 4.2.7.1)
+      sprockets-rails
+    rails-deprecated_sanitizer (1.0.3)
+      activesupport (>= 4.2.0.alpha)
+    rails-dom-testing (1.0.7)
+      activesupport (>= 4.2.0.beta, < 5.0)
+      nokogiri (~> 1.6.0)
+      rails-deprecated_sanitizer (>= 1.0.1)
+    rails-html-sanitizer (1.0.3)
+      loofah (~> 2.0)
+    rails_admin (1.1.0)
+      builder (~> 3.1)
+      coffee-rails (~> 4.0)
+      font-awesome-rails (>= 3.0, < 5)
+      haml (~> 4.0)
+      jquery-rails (>= 3.0, < 5)
+      jquery-ui-rails (~> 5.0)
+      kaminari (~> 0.14)
+      nested_form (~> 0.3)
+      rack-pjax (>= 0.7)
+      rails (>= 4.0, < 6)
+      remotipart (~> 1.3)
+      sass-rails (>= 4.0, < 6)
+    rails_admin_import (2.0.0)
+      haml (~> 4.0)
+      rails (>= 3.2)
+      rails_admin (>= 0.6.6)
+      rchardet (~> 1.6)
+      simple_xlsx_reader (~> 1.0)
+    rails_admin_nestable (0.3.2)
+      coffee-rails
+      haml-rails
+      rails_admin (>= 0.6.6)
+      sass-rails
+    railties (4.2.7.1)
+      actionpack (= 4.2.7.1)
+      activesupport (= 4.2.7.1)
+      rake (>= 0.8.7)
+      thor (>= 0.18.1, < 2.0)
+    rake (11.3.0)
+    rb-fsevent (0.9.8)
+    rb-inotify (0.9.7)
+      ffi (>= 0.5.0)
+    rchardet (1.6.1)
+    remotipart (1.3.1)
+    request_store (1.3.1)
+    responders (2.3.0)
+      railties (>= 4.2.0, < 5.1)
+    rest-client (1.8.0-x64-mingw32)
+      ffi (~> 1.9)
+      http-cookie (>= 1.0.2, < 2.0)
+      mime-types (>= 1.16, < 3.0)
+      netrc (~> 0.7)
+    ruby_parser (3.8.3)
+      sexp_processor (~> 4.1)
+    rubyzip (1.2.0)
+    safe_yaml (1.0.4)
+    sass (3.4.22)
+    sass-rails (5.0.6)
+      railties (>= 4.0.0, < 6)
+      sass (~> 3.1)
+      sprockets (>= 2.8, < 4.0)
+      sprockets-rails (>= 2.0, < 4.0)
+      tilt (>= 1.1, < 3)
+    sexp_processor (4.7.0)
+    simple_xlsx_reader (1.0.2)
+      nokogiri
+      rubyzip
+    sprockets (3.7.0)
+      concurrent-ruby (~> 1.0)
+      rack (> 1, < 3)
+    sprockets-rails (3.2.0)
+      actionpack (>= 4.0)
+      activesupport (>= 4.0)
+      sprockets (>= 3.0.0)
+    syck (1.2.0)
+    systemu (2.6.5)
+    thor (0.19.4)
+    thread_safe (0.3.5)
+    tilt (2.0.5)
+    tzinfo (1.2.2)
+      thread_safe (~> 0.1)
+    tzinfo-data (1.2016.10)
+      tzinfo (>= 1.0.0)
+    uglifier (3.0.4)
+      execjs (>= 0.3.0, < 3)
+    unf (0.1.4)
+      unf_ext
+    unf_ext (0.0.7.2-x64-mingw32)
+    uuid (2.3.8)
+      macaddr (~> 1.0)
+    warden (1.2.6)
+      rack (>= 1.0)
+    xml-simple (1.1.5)
+
+PLATFORMS
+  x64-mingw32
+
+DEPENDENCIES
+  aliyun-sdk (~> 0.4.1)
+  ancestry
+  bootstrap-sass
+  cancancan
+  chinese_pinyin
+  ckeditor
+  coffee-rails
+  coffee-script-source
+  compass
+  devise
+  jquery-rails
+  mysql2
+  paper_trail (= 5.2.3)
+  paperclip
+  paperclip-storage-aliyun
+  rails (= 4.2.7.1)
+  rails_admin
+  rails_admin_import
+  rails_admin_nestable
+  rest-client (~> 1.8.0)
+  safe_yaml
+  sass-rails
+  syck
+  therubyracer
+  tzinfo-data
+  uglifier
+  uuid
+  xml-simple
+
+BUNDLED WITH
+   1.13.3

+ 2 - 2
README.md

@@ -1,3 +1,3 @@
-# fohow_admin
+# fohow_reconstruct_admin
 
-管理后台
+fohow 后台管理系统重构

+ 261 - 0
README.rdoc

@@ -0,0 +1,261 @@
+== Welcome to Rails
+
+Rails is a web-application framework that includes everything needed to create
+database-backed web applications according to the Model-View-Control pattern.
+
+This pattern splits the view (also called the presentation) into "dumb"
+templates that are primarily responsible for inserting pre-built data in between
+HTML tags. The model contains the "smart" domain objects (such as Account,
+Product, Person, Post) that holds all the business logic and knows how to
+persist themselves to a database. The controller handles the incoming requests
+(such as Save New Account, Update Product, Show Post) by manipulating the model
+and directing data to the view.
+
+In Rails, the model is handled by what's called an object-relational mapping
+layer entitled Active Record. This layer allows you to present the data from
+database rows as objects and embellish these data objects with business logic
+methods. You can read more about Active Record in
+link:files/vendor/rails/activerecord/README.html.
+
+The controller and view are handled by the Action Pack, which handles both
+layers by its two parts: Action View and Action Controller. These two layers
+are bundled in a single package due to their heavy interdependence. This is
+unlike the relationship between the Active Record and Action Pack that is much
+more separate. Each of these packages can be used independently outside of
+Rails. You can read more about Action Pack in
+link:files/vendor/rails/actionpack/README.html.
+
+
+== Getting Started
+
+1. At the command prompt, create a new Rails application:
+       <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
+
+2. Change directory to <tt>myapp</tt> and start the web server:
+       <tt>cd myapp; rails server</tt> (run with --help for options)
+
+3. Go to http://localhost:3000/ and you'll see:
+       "Welcome aboard: You're riding Ruby on Rails!"
+
+4. Follow the guidelines to start developing your application. You can find
+the following resources handy:
+
+* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
+* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
+
+
+== Debugging Rails
+
+Sometimes your application goes wrong. Fortunately there are a lot of tools that
+will help you debug it and get it back on the rails.
+
+First area to check is the application log files. Have "tail -f" commands
+running on the server.log and development.log. Rails will automatically display
+debugging and runtime information to these files. Debugging info will also be
+shown in the browser on requests from 127.0.0.1.
+
+You can also log your own messages directly into the log file from your code
+using the Ruby logger class from inside your controllers. Example:
+
+  class WeblogController < ActionController::Base
+    def destroy
+      @weblog = Weblog.find(params[:id])
+      @weblog.destroy
+      logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
+    end
+  end
+
+The result will be a message in your log file along the lines of:
+
+  Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
+
+More information on how to use the logger is at http://www.ruby-doc.org/core/
+
+Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
+several books available online as well:
+
+* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
+* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
+
+These two books will bring you up to speed on the Ruby language and also on
+programming in general.
+
+
+== Debugger
+
+Debugger support is available through the debugger command when you start your
+Mongrel or WEBrick server with --debugger. This means that you can break out of
+execution at any point in the code, investigate and change the model, and then,
+resume execution! You need to install ruby-debug to run the server in debugging
+mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:
+
+  class WeblogController < ActionController::Base
+    def index
+      @posts = Post.all
+      debugger
+    end
+  end
+
+So the controller will accept the action, run the first line, then present you
+with a IRB prompt in the server window. Here you can do things like:
+
+  >> @posts.inspect
+  => "[#<Post:0x14a6be8
+          @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
+       #<Post:0x14a6620
+          @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
+  >> @posts.first.title = "hello from a debugger"
+  => "hello from a debugger"
+
+...and even better, you can examine how your runtime objects actually work:
+
+  >> f = @posts.first
+  => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
+  >> f.
+  Display all 152 possibilities? (y or n)
+
+Finally, when you're ready to resume execution, you can enter "cont".
+
+
+== Console
+
+The console is a Ruby shell, which allows you to interact with your
+application's domain model. Here you'll have all parts of the application
+configured, just like it is when the application is running. You can inspect
+domain models, change values, and save to the database. Starting the script
+without arguments will launch it in the development environment.
+
+To start the console, run <tt>rails console</tt> from the application
+directory.
+
+Options:
+
+* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
+  made to the database.
+* Passing an environment name as an argument will load the corresponding
+  environment. Example: <tt>rails console production</tt>.
+
+To reload your controllers and models after launching the console run
+<tt>reload!</tt>
+
+More information about irb can be found at:
+link:http://www.rubycentral.org/pickaxe/irb.html
+
+
+== dbconsole
+
+You can go to the command line of your database directly through <tt>rails
+dbconsole</tt>. You would be connected to the database with the credentials
+defined in database.yml. Starting the script without arguments will connect you
+to the development database. Passing an argument will connect you to a different
+database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
+PostgreSQL and SQLite 3.
+
+== Description of Contents
+
+The default directory structure of a generated Ruby on Rails application:
+
+  |-- app
+  |   |-- assets
+  |   |   |-- images
+  |   |   |-- javascripts
+  |   |   `-- stylesheets
+  |   |-- controllers
+  |   |-- helpers
+  |   |-- mailers
+  |   |-- models
+  |   `-- views
+  |       `-- layouts
+  |-- config
+  |   |-- environments
+  |   |-- initializers
+  |   `-- locales
+  |-- db
+  |-- doc
+  |-- lib
+  |   |-- assets
+  |   `-- tasks
+  |-- log
+  |-- public
+  |-- script
+  |-- test
+  |   |-- fixtures
+  |   |-- functional
+  |   |-- integration
+  |   |-- performance
+  |   `-- unit
+  |-- tmp
+  |   `-- cache
+  |       `-- assets
+  `-- vendor
+      |-- assets
+      |   |-- javascripts
+      |   `-- stylesheets
+      `-- plugins
+
+app
+  Holds all the code that's specific to this particular application.
+
+app/assets
+  Contains subdirectories for images, stylesheets, and JavaScript files.
+
+app/controllers
+  Holds controllers that should be named like weblogs_controller.rb for
+  automated URL mapping. All controllers should descend from
+  ApplicationController which itself descends from ActionController::Base.
+
+app/models
+  Holds models that should be named like post.rb. Models descend from
+  ActiveRecord::Base by default.
+
+app/views
+  Holds the template files for the view that should be named like
+  weblogs/index.html.erb for the WeblogsController#index action. All views use
+  eRuby syntax by default.
+
+app/views/layouts
+  Holds the template files for layouts to be used with views. This models the
+  common header/footer method of wrapping views. In your views, define a layout
+  using the <tt>layout :default</tt> and create a file named default.html.erb.
+  Inside default.html.erb, call <% yield %> to render the view using this
+  layout.
+
+app/helpers
+  Holds view helpers that should be named like weblogs_helper.rb. These are
+  generated for you automatically when using generators for controllers.
+  Helpers can be used to wrap functionality for your views into methods.
+
+config
+  Configuration files for the Rails environment, the routing map, the database,
+  and other dependencies.
+
+db
+  Contains the database schema in schema.rb. db/migrate contains all the
+  sequence of Migrations for your schema.
+
+doc
+  This directory is where your application documentation will be stored when
+  generated using <tt>rake doc:app</tt>
+
+lib
+  Application specific libraries. Basically, any kind of custom code that
+  doesn't belong under controllers, models, or helpers. This directory is in
+  the load path.
+
+public
+  The directory available for the web server. Also contains the dispatchers and the
+  default HTML files. This should be set as the DOCUMENT_ROOT of your web
+  server.
+
+script
+  Helper scripts for automation and generation.
+
+test
+  Unit and functional tests along with fixtures. When using the rails generate
+  command, template test files will be generated for you and placed in this
+  directory.
+
+vendor
+  External libraries that the application depends on. Also includes the plugins
+  subdirectory. If the app has frozen rails, those gems also go here, under
+  vendor/rails/. This directory is in the load path.

+ 7 - 0
Rakefile

@@ -0,0 +1,7 @@
+#!/usr/bin/env rake
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+AdminD5ctCom::Application.load_tasks

BIN
app/assets/images/rails.png


+ 16 - 0
app/assets/javascripts/application.js

@@ -0,0 +1,16 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// the compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require_tree .
+//= require ckeditor/init
+//= require jquery
+//= require jquery_ujs

+ 135 - 0
app/assets/javascripts/ckeditor/config.js

@@ -0,0 +1,135 @@
+/*
+ Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
+ For licensing, see LICENSE.html or http://ckeditor.com/license
+ */
+
+CKEDITOR.editorConfig = function( config )
+{
+    // Define changes to default configuration here. For example:
+    // config.language = 'fr';
+    // config.uiColor = '#AADC6E';
+
+    /* Filebrowser routes */
+    // The location of an external file browser, that should be launched when "Browse Server" button is pressed.
+    //文件上传POST请求的URL
+    config.filebrowserBrowseUrl = "/ckeditor/attachment_files";
+
+    // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Flash dialog.
+    config.filebrowserFlashBrowseUrl = "/ckeditor/attachment_files";
+
+    // The location of a script that handles file uploads in the Flash dialog.
+    config.filebrowserFlashUploadUrl = "/ckeditor/attachment_files";
+
+    // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Link tab of Image dialog.
+    config.filebrowserImageBrowseLinkUrl = "/ckeditor/pictures";
+
+    // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Image dialog.
+    config.filebrowserImageBrowseUrl = "/ckeditor/pictures";
+
+    // The location of a script that handles file uploads in the Image dialog.
+    config.filebrowserImageUploadUrl = "/ckeditor/pictures";
+
+    // The location of a script that handles file uploads.
+    config.filebrowserUploadUrl = "/ckeditor/attachment_files";
+
+    config.allowedContent = true;
+
+    //上传图片去掉预览文字
+    config.image_previewText =' ';
+    //config.maxSize = 0;
+    // 字体
+    config.font_names= '宋体/SimSun;新宋体/NSimSun;仿宋_GB2312/FangSong_GB2312;楷体_GB2312/KaiTi_GB2312;黑体/SimHei;微软雅黑/Microsoft YaHei;' + config.font_names;
+
+    //增加行距插件
+    config.extraPlugins += (config.extraPlugins ? ',lineheight' : 'lineheight');
+    //从word复制时保留格式
+    config.pasteFromWordRemoveFontStyles = false;
+    config.pasteFromWordRemoveStyles = false;
+    // Rails CSRF token
+    config.filebrowserParams = function(){
+        var csrf_token, csrf_param, meta,
+            metas = document.getElementsByTagName('meta'),
+            params = new Object();
+
+        for ( var i = 0 ; i < metas.length ; i++ ){
+            meta = metas[i];
+
+            switch(meta.name) {
+                case "csrf-token":
+                    csrf_token = meta.content;
+                    break;
+                case "csrf-param":
+                    csrf_param = meta.content;
+                    break;
+                default:
+                    continue;
+            }
+        }
+
+        if (csrf_param !== undefined && csrf_token !== undefined) {
+            params[csrf_param] = csrf_token;
+        }
+
+        return params;
+    };
+
+    config.addQueryString = function( url, params ){
+        var queryString = [];
+
+        if ( !params ) {
+            return url;
+        } else {
+            for ( var i in params )
+                queryString.push( i + "=" + encodeURIComponent( params[ i ] ) );
+        }
+
+        return url + ( ( url.indexOf( "?" ) != -1 ) ? "&" : "?" ) + queryString.join( "&" );
+    };
+
+    // Integrate Rails CSRF token into file upload dialogs (link, image, attachment and flash)
+    CKEDITOR.on( 'dialogDefinition', function( ev ){
+        // Take the dialog name and its definition from the event data.
+        var dialogName = ev.data.name;
+        var dialogDefinition = ev.data.definition;
+        var content, upload;
+
+        if (CKEDITOR.tools.indexOf(['link', 'image', 'attachment', 'flash'], dialogName) > -1) {
+            content = (dialogDefinition.getContents('Upload') || dialogDefinition.getContents('upload'));
+            upload = (content == null ? null : content.get('upload'));
+
+            if (upload && upload.filebrowser && upload.filebrowser['params'] === undefined) {
+                upload.filebrowser['params'] = config.filebrowserParams();
+                upload.action = config.addQueryString(upload.action, upload.filebrowser['params']);
+            }
+        }
+    });
+
+    // 设置初始高度
+    config.height = 600;
+    // Toolbar groups configuration.
+    config.toolbar = [
+        { name: 'document', groups: [ 'mode', 'document', 'doctools' ], items: [ 'Source'] },
+        { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
+        // { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ], items: [ 'Find', 'Replace', '-', 'SelectAll', '-', 'Scayt' ] },
+        // { name: 'forms', items: [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
+        { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
+        { name: 'insert', items: [ 'Image', 'Iframe','Table', 'HorizontalRule', 'SpecialChar' ] },
+        { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
+        '/',
+        { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize', 'lineheight' ] },
+        { name: 'colors', items: [ 'TextColor', 'BGColor' ] },
+        { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
+        { name: 'tools', items : [ 'Maximize','-','About' ] } 
+    ];
+
+    config.toolbar_mini = [
+        { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
+        { name: 'styles', items: [ 'Font', 'FontSize' ] },
+        { name: 'colors', items: [ 'TextColor', 'BGColor' ] },
+        { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
+        { name: 'insert', items: [ 'Image', 'Table', 'HorizontalRule', 'SpecialChar' ] },
+        { name: 'maximize'}
+    ];
+
+    // config.extraPlugins += (config.extraPlugins ? ',helloworld' : 'helloworld');
+};

+ 5 - 0
app/assets/javascripts/ckeditor/plugins/lineheight/lang/en.js

@@ -0,0 +1,5 @@
+CKEDITOR.plugins.setLang('lineheight', 'en', {
+    label: 'lineheight',
+    panelTitle: 'line-height',
+    panelTitle: 'line-height'
+});

+ 5 - 0
app/assets/javascripts/ckeditor/plugins/lineheight/lang/zh-cn.js

@@ -0,0 +1,5 @@
+CKEDITOR.plugins.setLang('lineheight', 'zh-cn', {
+    label: '行距',
+    panelTitle: '行距',
+    panelTitle: '行距'
+});

+ 146 - 0
app/assets/javascripts/ckeditor/plugins/lineheight/plugin.js

@@ -0,0 +1,146 @@
+/*
+Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+	function addCombo( editor, comboName, styleType, lang, entries, defaultLabel, styleDefinition )
+	{
+		var config = editor.config;
+
+		// Gets the list of fonts from the settings.
+		var names = entries.split( ';' ),
+			values = [];
+
+		// Create style objects for all fonts.
+		var styles = {};
+		for ( var i = 0 ; i < names.length ; i++ )
+		{
+			var parts = names[ i ];
+
+			if ( parts )
+			{
+				parts = parts.split( '/' );
+
+				var vars = {},
+					name = names[ i ] = parts[ 0 ];
+
+				vars[ styleType ] = values[ i ] = parts[ 1 ] || name;
+
+				styles[ name ] = new CKEDITOR.style( styleDefinition, vars );
+				styles[ name ]._.definition.name = name;
+			}
+			else
+				names.splice( i--, 1 );
+		}
+
+
+	    editor.ui.addRichCombo( comboName,
+	    	{
+	    		label : lang.lineheight.label,
+	    		title: lang.lineheight.panelTitle,
+	    		className: 'cke_' + (styleType == 'size' ? 'fontSize' : 'font'),
+	    		panel :{
+	    			css : [CKEDITOR.skin.getPath("editor")].concat( config.contentsCss ),
+	    			multiSelect : false,
+	    			attributes: { 'aria-label': lang.lineheight.panelTitle }
+	    		},  
+  
+				init : function()
+				{
+					this.startGroup( lang.lineheight.panelTitle );  
+
+					for ( var i = 0 ; i < names.length ; i++ )
+					{
+						var name = names[ i ];
+
+						// Add the tag entry to the panel list.
+						this.add( name, styles[ name ].buildPreview(), name );
+					}
+				},
+
+				onClick : function( value )
+				{
+					editor.focus();
+					editor.fire( 'saveSnapshot' );
+
+					var style = styles[ value ];
+
+					if ( this.getValue() == value )
+						style.remove( editor.document );
+					else
+						style.apply( editor.document );
+
+					editor.fire( 'saveSnapshot' );
+				},
+
+				onRender : function()
+				{
+					editor.on( 'selectionChange', function( ev )
+						{
+							var currentValue = this.getValue();
+
+							var elementPath = ev.data.path,
+								elements = elementPath.elements;
+
+							// For each element into the elements path.
+							for ( var i = 0, element ; i < elements.length ; i++ )
+							{
+								element = elements[i];
+
+								// Check if the element is removable by any of
+								// the styles.
+								for ( var value in styles )
+								{
+									if ( styles[ value ].checkElementRemovable( element, true ) )
+									{
+										if ( value != currentValue )
+											this.setValue( value );
+										return;
+									}
+								}
+							}
+
+							// If no styles match, just empty it.
+							this.setValue( '', defaultLabel );
+						},
+						this);
+				}
+			});
+	}
+
+	CKEDITOR.plugins.add('lineheight',
+	{
+	    lang: ['zh-cn'],
+		requires : [ 'richcombo'],
+
+		init : function( editor )
+		{
+			var config = editor.config;
+			addCombo(editor, 'lineheight', 'size', editor.lang, config.lineheight_sizes, config.fontSize_defaultLabel, config.lineheight_style);
+		}
+	});
+})();
+
+
+/**
+ * The text to be displayed in the Font combo is none of the available values
+ * matches the current cursor position or text selection.
+ * @type String
+ * @example
+ * // If the default site font is Arial, we may making it more explicit to the end user.
+ * config.font_defaultLabel = 'Arial';
+ */
+CKEDITOR.config.font_defaultLabel = '';
+
+
+CKEDITOR.config.lineheight_sizes = 
+	'normal;1.5em;1.75em;2em;3em;4em;5em;100%;120%;130%;150%;170%;180%;190%;200%;220%;250%;300%;400%;500%';
+
+CKEDITOR.config.lineheight_style =
+	{
+		element		: 'span',
+		styles		: { 'line-height' : '#(size)' },
+		overrides: [{ element: 'line', attributes: { 'height': null}}]
+	};

+ 7 - 0
app/assets/javascripts/rails_admin/custom/ckeditor_ajax.js.coffee

@@ -0,0 +1,7 @@
+$(document).ready ->
+  $(document).on 'mousedown', '.save-action', (e) -> # triggers also when submitting form with enter
+    for instance of CKEDITOR.instances
+      editor = CKEDITOR.instances[instance]
+      if editor.checkDirty()
+        editor.updateElement();
+    return true;

+ 1 - 0
app/assets/javascripts/rails_admin/custom/ui.js

@@ -0,0 +1 @@
+//= require rails_admin/custom/ckeditor_ajax

+ 14 - 0
app/assets/stylesheets/application.css.scss

@@ -0,0 +1,14 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+ */
+

+ 109 - 0
app/assets/stylesheets/rails_admin/rails_admin.scss.erb

@@ -0,0 +1,109 @@
+// Issue 1956 (https://github.com/sferik/rails_admin/issues/1956)
+//= depend_on_asset "rails_admin/bootstrap/glyphicons-halflings.png"
+//= depend_on_asset "rails_admin/bootstrap/glyphicons-halflings-white.png"
+//= depend_on_asset "rails_admin/aristo/images/bg_fallback.png"
+//= depend_on_asset "rails_admin/aristo/images/ui-icons_222222_256x240.png"
+//= depend_on_asset "rails_admin/aristo/images/ui-icons_454545_256x240.png"
+//= depend_on_asset "rails_admin/aristo/images/icon_sprite.png"
+//= depend_on_asset "rails_admin/aristo/images/slider_handles.png"
+//= depend_on_asset "rails_admin/aristo/images/progress_bar.gif"
+//= depend_on_asset "rails_admin/multiselect/icon_sprite.png"
+//= depend_on_asset "rails_admin/multiselect/ui-icon-circle-triangle-n-light.png"
+//= depend_on_asset "rails_admin/multiselect/ui-icon-circle-triangle-n-dark.png"
+//= depend_on_asset "rails_admin/multiselect/ui-icon-circle-triangle-s-light.png"
+//= depend_on_asset "rails_admin/multiselect/ui-icon-circle-triangle-s-dark.png"
+//= depend_on_asset "rails_admin/colorpicker/select2.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_background.png"
+//= depend_on_asset "rails_admin/colorpicker/colorpicker_overlay.png"
+//= depend_on_asset "rails_admin/colorpicker/colorpicker_select.gif"
+//= depend_on_asset "rails_admin/colorpicker/custom_indic.gif"
+//= depend_on_asset "rails_admin/colorpicker/custom_hex.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_rgb_r.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_rgb_g.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_rgb_b.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_hsb_h.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_hsb_s.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_hsb_b.png"
+//= depend_on_asset "rails_admin/colorpicker/custom_submit.png"
+
+
+@charset "UTF-8";
+
+<%
+  theme = ENV['RAILS_ADMIN_THEME'] || :default
+%>
+
+/***  Variables  ***/
+
+@import "rails_admin/custom/variables";
+@import "rails_admin/bootstrap/variables";
+@import "rails_admin/base/variables";
+@import "rails_admin/themes/<%= theme %>/variables";
+
+/***  Mixins  ***/
+
+@import "rails_admin/bootstrap/mixins";
+@import "rails_admin/base/mixins";
+@import "rails_admin/themes/<%= theme %>/mixins";
+@import "rails_admin/custom/mixins";
+
+/*** Reset ***/
+<%# @import "rails_admin/bootstrap/reset"; %>
+/***  Libraries  ***/
+
+@import "rails_admin/aristo/jquery-ui-1.8.7.custom";
+@import "rails_admin/bootstrap-datetimepicker-build";
+@import "rails_admin/ra.filtering-multiselect";
+@import "rails_admin/ra.widgets";
+@import "rails_admin/jquery.colorpicker";
+
+
+/*** Font-awesome ***/
+
+@import 'font-awesome';
+@import 'rails_admin/base/font-awesome-4-compability';
+
+/***  Bootstrap Theming  ***/
+
+@import "rails_admin/bootstrap/normalize";
+@import "rails_admin/bootstrap/scaffolding";
+@import "rails_admin/bootstrap/grid";
+<%# @import "rails_admin/bootstrap/layouts"; %>
+@import "rails_admin/bootstrap/type";
+@import "rails_admin/bootstrap/forms";
+@import "rails_admin/bootstrap/tables";
+@import "rails_admin/bootstrap/dropdowns";
+@import "rails_admin/bootstrap/wells";
+@import "rails_admin/bootstrap/component-animations";
+@import "rails_admin/bootstrap/close";
+@import "rails_admin/bootstrap/buttons";
+@import "rails_admin/bootstrap/button-groups";
+@import "rails_admin/bootstrap/input-groups";
+@import "rails_admin/bootstrap/alerts";
+@import "rails_admin/bootstrap/navs";
+@import "rails_admin/bootstrap/navbar";
+@import "rails_admin/bootstrap/breadcrumbs";
+@import "rails_admin/bootstrap/pagination";
+@import "rails_admin/bootstrap/pager";
+@import "rails_admin/bootstrap/modals";
+@import "rails_admin/bootstrap/tooltip";
+@import "rails_admin/bootstrap/popovers";
+@import "rails_admin/bootstrap/thumbnails";
+@import "rails_admin/bootstrap/labels";
+@import "rails_admin/bootstrap/panels";
+@import "rails_admin/bootstrap/badges";
+@import "rails_admin/bootstrap/progress-bars";
+<%# @import "rails_admin/bootstrap/accordion"; %>
+@import "rails_admin/bootstrap/carousel";
+<%# @import "rails_admin/bootstrap/hero-unit"; %>
+@import "rails_admin/bootstrap/utilities";
+@import "rails_admin/bootstrap/responsive-utilities";
+
+/***  RailsAdmin Theming  ***/
+
+@import "rails_admin/base/theming";
+@import "rails_admin/themes/<%= theme %>/theming";
+@import "rails_admin/custom/theming";
+
+
+

+ 17 - 0
app/controllers/application_controller.rb

@@ -0,0 +1,17 @@
+# encoding:utf-8
+class ApplicationController < ActionController::Base
+  protect_from_forgery
+  layout :layout_by_resource
+
+  rescue_from CanCan::AccessDenied do |exception|
+    redirect_to root_url, :alert => exception.message
+  end
+
+  def layout_by_resource
+    if devise_controller?
+      "devise_layout"
+    else
+      "application"
+    end
+  end
+end

+ 4 - 0
app/controllers/base_controller.rb

@@ -0,0 +1,4 @@
+#encoding:utf-8
+class BaseController < ActionController::Base
+
+end

+ 33 - 0
app/controllers/chunjie_config_stat_controller.rb

@@ -0,0 +1,33 @@
+# encoding:utf-8
+class ChunjieConfigStatController < BaseController
+  before_filter :authenticate_admin_user!
+
+  def index
+    # 活动ID
+    pid = params[:id].to_i
+
+    # 活动名称
+    @title = '春节快乐'
+
+    #已经发放的红包金额
+    @hongbaoTotalMoney = 20000
+
+    #参与人数:
+    @total_join = 50000000
+    #新增注册用户数:
+    @total_new_register = 60000000
+    #新增关注:
+    @total_new_sub = 70000
+    
+    render :layout => false
+  end
+
+  #项目投资排名
+  # def rank
+  #   pid = params[:id].to_i
+  #   @project = Project.where("id=?",pid).first
+  #   sql = "select sum(j.total_price) as investment, j.user_id, j.paied_at as invest_time,u.real_name,u.tel from d5c_project_joins j,d5c_users u where j.user_id=u.id and j.project_id = #{pid} and j.state = 1 and j.is_refunded = 0 and j.is_deleted = 0 group by j.user_id order by invest_time asc, j.created_at asc";
+  #   @items = ProjectJoin.find_by_sql(sql)
+  # end
+
+end

+ 39 - 0
app/controllers/kaijiang_controller.rb

@@ -0,0 +1,39 @@
+# encoding:utf-8
+class KaijiangController < BaseController
+  before_filter :authenticate_admin_user!
+
+  def index
+    # 项目ID
+    pid = params[:pid].to_i
+    @project = Project.where("id=?",pid).first
+    #开奖人数
+    @num = params[:num].to_i
+    #开奖人数
+    @all_num = params[:all].to_i
+    #重庆时彩号码
+    @code = params[:code].to_i
+    # 项目的投资人总数-排重
+    # sql = "select count(DISTINCT user_id) as count from d5c_project_joins where project_id = " + pid + " and state = 1 and is_deleted=0 and is_refunded = 0"
+    sql = "select FROM_UNIXTIME(paied_at,'%Y%m%d%H%i') c from d5c_project_joins where project_id = " + pid.to_s + " and state = 1 and is_deleted=0 and is_refunded = 0 group by user_id order by paied_at asc, created_at asc limit #{@all_num};"
+    @items = ProjectJoin.find_by_sql(sql)
+    @count = @items.size
+    @sum = 0
+    @items.each do |item|
+      @sum = @sum + item.c.to_i
+    end
+    if @count > 0
+      code_date = @items[1].c
+      @code_date = "#{code_date[0...4]}-#{code_date[4...6]}-#{code_date[6...8]}"
+    end
+    render :layout => false
+  end
+
+  #项目投资排名
+  def rank
+    pid = params[:id].to_i
+    @project = Project.where("id=?",pid).first
+    sql = "select sum(j.total_price) as investment, j.user_id, j.paied_at as invest_time,u.real_name,u.tel from d5c_project_joins j,d5c_users u where j.user_id=u.id and j.project_id = #{pid} and j.state = 1 and j.is_refunded = 0 and j.is_deleted = 0 group by j.user_id order by invest_time asc, j.created_at asc";
+    @items = ProjectJoin.find_by_sql(sql)
+  end
+
+end

+ 7 - 0
app/controllers/nianzhong_report_controller.rb

@@ -0,0 +1,7 @@
+# encoding:utf-8
+class NianzhongReportController < BaseController
+  # before_filter :authenticate_admin_user!
+  def show_2016
+    render :layout => false
+  end
+end

File diff suppressed because it is too large
+ 1551 - 0
app/controllers/report_controller.rb


+ 209 - 0
app/controllers/zt_report_controller.rb

@@ -0,0 +1,209 @@
+# encoding:utf-8
+class ZtReportController < BaseController
+  before_filter :authenticate_admin_user!
+  def xccj
+
+    render :layout => false
+  end
+
+  def fanhongbao
+  	time_0125 = Time.new(2017, 1, 27, 20, 0, 0)
+    #合体成功总金额单位:分
+    @success_total = 0    
+    records = ZtFanhongbaoRecord.where("state=?", 1)
+
+    records.each do |record|
+      @success_total +=  record.first_num*100 + record.last_num*10
+    end
+
+    #合体总次数
+    @total_times  = records.length#ZtFanhongbaoRecord.where("state=?", 1).length
+
+    #绑定金额 balance
+    @total_balance =  Balance.where("source=? or source=?", "new_year_fanhongbao_", "new_year_fhb_2017").sum("count")        
+
+    #提现金额(金额小于50元的)
+    @take_cash_total =  Balance.where("source=? and count > -10000 and created_at > ?", "extract", time_0125).sum("count")
+
+    #新增关注用户
+    @new_wx_sub_users = WxUser.where("created_at > ? and subscribe = ?", time_0125, true).length
+    #新注册用户
+    @new_users = User.where("created_at>? and tel != ''", time_0125).length
+    #新增绑定身份证用户
+    @binding_id = User.where("created_at>? and identity_card != ''", time_0125).length
+    #新增绑卡用户
+    @binding_card = UserBankcard.where("created_at>?", time_0125).length
+
+  	render :layout => false
+  end
+
+  def share_info    
+
+    # sql = "select sum(first_num*100 + last_num*10) as total from d5c_zt_fanhongbao_records where state=1"
+    # @success_total = ZtFanhongbaoRecord.find_by_sql(sql).first.total
+
+
+    time_0125 = Time.new(2017, 1, 27, 20, 0, 0)
+
+    #参与总人数
+    @total_size  = ZtFanhongbaoRecord.group("launcher_id").all.length
+    #成功人数
+    @success_size = ZtFanhongbaoRecord.where("state=?", 1).group("launcher_id").length
+    
+    #合体次数用满的人数
+    # @full_time_people = ZtFanhongbaoRecord.where("state=?", 1).group("")    
+    #分享朋友圈
+    @share_timeline = 0 #ShareInfo.where("share_code=? and share_to=?", "spring_szhb", "timeline").length
+    #分享人或群
+    @share_group = 0#ShareInfo.where("share_code=? and share_to=?", "spring_szhb", "group").length
+    ShareInfo.where("share_code=?", "spring_szhb").each do |item|
+      if item.share_to == "group"
+        @share_group += 1    
+      elsif item.share_to == "timeline"
+        @share_timeline += 1
+      end
+    end
+
+    #分享人数
+    @share_people = ShareInfo.where("share_code=?", "spring_szhb").group("wx_user_id").length
+  end
+
+  def top10
+    #发起用户合体次数top10
+    sql = "select count(*) as c, launcher_id, d5c_wx_users.nickname, d5c_wx_users.user_id from d5c_zt_fanhongbao_records 
+           left join d5c_wx_users on d5c_wx_users.id = launcher_id
+           where state=1 group by launcher_id order by c DESC limit 10"
+    @launch_top_10 = ZtFanhongbaoRecord.find_by_sql(sql)
+    #被邀请合体次数top10
+    sql = "select count(*) as c, partner_id, d5c_wx_users.nickname, d5c_wx_users.user_id from d5c_zt_fanhongbao_records 
+           left join d5c_wx_users on d5c_wx_users.id = partner_id
+           where state=1 group by partner_id order by c DESC limit 10"
+    @partner_top_10 = ZtFanhongbaoRecord.find_by_sql(sql)
+        
+    @money_top_10 = []
+    sql = "select sum(count) as total, d5c_balances.user_id, d5c_users.nickname, d5c_users.tel from d5c_balances left join d5c_users on d5c_users.id = d5c_balances.user_id  where (source='new_year_fanhongbao_' or source='new_year_fhb_2017') group by user_id order by total DESC limit 50"
+    @money_top_10 = Balance.find_by_sql(sql)
+  end
+
+  def fhb_day
+    @list = []
+    ZtFanhongbaoRecord.select("date_format(open_time, '%Y-%m-%d') date, date_format(open_time, '%d') day, count(*) as c, sum(last_num*10 + first_num*100)/100 as total")
+    .where("state=1")
+    .group("day").order("day").each do |item| 
+      # p "*********** #{item.day}, #{item.c}, #{item.total}" 
+      @list << {:day => item.date, :count => item.c, :total => item.total}
+    end
+
+    @bk_list = []
+    UserBankcard.select("date_format(created_at, '%Y-%m-%d') date, date_format(created_at, '%d') day, count(*) as c")
+    .where("created_at > '2017-01-27'")
+    .group("day").order("day").each do |item|       
+      @bk_list << {:day => item.date, :count => item.c}
+    end
+
+  end
+
+  def kj_infos
+    id = params[:id] || 0
+    @act_infos =[]
+    if id == 0
+      # sql = "select id, title, purchase_price, open_ad_code, banner_ad_code, stock from d5c_zt_kj_infos where state = 1"
+      sql = "select id,title from d5c_zt_kj_infos where state = 1"
+      acts = ZtKjInfo.find_by_sql(sql)
+      # p "----------------------------------------------------------------------------"
+      # # p acts
+      # p "----------------------------------------------------------------------------"
+      acts.each do |u|
+        act_info = get_act_statistic_info_by_act_id(u.id)
+        @act_infos << act_info
+      end
+
+    else
+      act_id = id.to_i
+      act_info = get_act_statistic_info_by_act_id(act_id)
+      @act_infos << act_info     
+    end
+    render :layout => false
+  end
+  # 通过活动id 获取该活动统计信息
+  def get_act_statistic_info_by_act_id(act_id)
+    act = ZtKjInfo.where("id = ?", act_id).first
+    if !act.blank?
+      order_sql = "select id from d5c_zt_kj_orders where act_id = #{act_id}"
+      join_user_count = ZtKjOrder.find_by_sql(order_sql).count()
+      reduce_sql = "select id from d5c_zt_kj_reduces where act_id = #{act_id}"
+      kj_count = ZtKjReduce.find_by_sql(reduce_sql).count()
+      unit_price = 0
+      success_kj_sql = "select id from d5c_zt_kj_orders where act_id = #{act_id} and left_price = #{act.min_price}"
+      success_kj_count = ZtKjOrder.find_by_sql(success_kj_sql).count()
+      # 成功下单数
+      success_order_sql = "select id from d5c_zt_kj_orders where act_id = #{act_id} and left_price = #{act.min_price} and (status = 'processing' or status = 'complete' or status = 'dispatch')"
+      success_order_count = ZtKjOrder.find_by_sql(success_order_sql).count()
+      # 总成本
+      cost = act.purchase_price * success_order_count
+      # 分享朋友圈统计
+      share_timeline_count = ShareInfo.where("relate_parent = ? and share_to = ? and share_code = ?", act.id, "timeline", "bargain_activity").count()
+      share_group_count = ShareInfo.where("relate_parent = ? and share_to = ? and share_code = ?", act.id, "group", "bargain_activity").count()
+
+      click_open_ad_count = 0
+      show_open_ad_count = 0
+      if !act.open_ad_code.blank?
+        ad_items = get_ad_items_by_ad_position_code(act.open_ad_code)
+        if !ad_items.blank?
+          ad_items.each do |ad_item|
+            click_count = get_click_times_by_ad_item(ad_item)
+            click_open_ad_count = click_open_ad_count + click_count
+
+            show_count = get_show_times_by_ad_item(ad_item)
+            show_open_ad_count = show_open_ad_count + show_count
+          end
+        end
+      end
+
+      click_banner_ad_count = 0
+      if !act.banner_ad_code.blank?
+        ad_items = get_ad_items_by_ad_position_code(act.banner_ad_code)
+        if !ad_items.blank?
+          ad_items.each do |ad_item|
+            click_count = get_click_times_by_ad_item(ad_item)
+            click_banner_ad_count = click_banner_ad_count + click_count
+          end
+        end
+      end
+
+      unit_price = cost/((click_open_ad_count + click_banner_ad_count) * 1.0)
+      unit_price = format("%.2f",unit_price).to_f
+      act_info = Hash.new
+      act_info = Hash[:title => act.title, :count => act.stock, :join_user_count => join_user_count, :kj_count =>kj_count, :show_open_ad_count => show_open_ad_count, :click_open_ad_count => click_open_ad_count, :click_banner_ad_count => click_banner_ad_count, :cost => cost, :unit_price => unit_price, :success_kj_count => success_kj_count, :success_order_count => success_order_count, :share_timeline_count => share_timeline_count, :share_group_count => share_group_count]
+      return act_info
+    end
+  end
+  # 通过广告位标识符获取所有广告项
+  def get_ad_items_by_ad_position_code(code)
+    ad_position = AdPosition.where("code = ?", code).first
+    if !ad_position.blank?
+      id = ad_position.id
+      sql = "select id from d5c_ad_items where ad_position_id = #{id}"
+      ad_items = AdItem.find_by_sql(sql)
+      if !ad_items.blank?
+        return ad_items
+      end
+    end
+  end
+  #通过广告项获取点击次数
+  def get_click_times_by_ad_item(item)
+    count = 0
+    AdItemClickStatistic.select("ad_item_id, click_times").where("ad_item_id = ?", item.id).each do |u|
+      count = count + u.click_times
+    end
+    return count
+  end
+  # 通过广告项获取展示次数
+  def get_show_times_by_ad_item(item)
+    count = 0
+    AdItemShowStatistic.select("ad_item_id, show_times").where("ad_item_id = ?", item.id).each do |u|
+      count = count + u.show_times
+    end
+    return count   
+  end
+end

+ 16 - 0
app/helpers/application_helper.rb

@@ -0,0 +1,16 @@
+module ApplicationHelper
+
+  #昨天凌晨
+  def yestoday_zero
+    return today_zero - 1.day
+  end
+  #今日凌晨
+  def today_zero
+    now = Time.now
+    return Time.new(now.year, now.month, now.day)
+  end
+  #明日凌晨
+  def tomorrow_zero
+    return today_zero + 1.day
+  end
+end

+ 0 - 0
app/mailers/.gitkeep


+ 68 - 0
app/models/ability.rb

@@ -0,0 +1,68 @@
+class Ability
+  include CanCan::Ability
+
+  def initialize(user)
+    # Define abilities for the passed in user here. For example:
+    #
+    #   user ||= User.new # guest user (not logged in)
+    #   if user.admin?
+    #     can :manage, :all
+    #   else
+    #     can :read, :all
+    #   end
+    if user
+      can :dashboard # allow access to dashboard
+      can :access, :rails_admin # only allow admin users to access Rails Admin
+      cannot :history, :all
+      cannot :import, :all
+      cannot :export, :all
+      cannot :destroy, :all
+      if user.email == AdminUser::SUPER_ADMIN
+        can :manage, :all
+        # can :export, :all
+        # can :read, :all
+        # can :destroy, :all
+        # can :create, :all
+        # can :update, :all
+      else
+        user.permissions.each do |permission|
+           eval "can :#{permission.can}, #{permission.model}"
+        end 
+                     
+        can :update, AdminUser, :id => user.id
+        can :read, AdminUser, :id => user.id
+        cannot :history, :all
+        # cannot :destroy, ChannelQrcode        
+        # cannot :refund_at_once, Project
+        # cannot :destroy, ["ProductAttr", "ProductAttrKey", "ProductAttrValue"]
+        # cannot :delete, ["ProductAttr", "ProductAttrKey", "ProductAttrValue"]
+        # cannot :export, ["ProductAttr", "ProductAttrKey", "ProductAttrValue"]
+      end
+      #cannot :destroy, DianshiOrder
+      # cannot :new, DianbiOrder
+      # cannot :new, VipOrder
+      # cannot :new, DianshiOrder
+      # cannot :update, User
+      # cannot :generate_analyze_report_record, AnalyzeReport
+      # can :generate_analyze_report_record, AnalyzeReport, :remark => "当前汇总"
+    end
+    #
+    # The first argument to `can` is the action you are giving the user
+    # permission to do.
+    # If you pass :manage it will apply to every action. Other common actions
+    # here are :read, :create, :update and :destroy.
+    #
+    # The second argument is the resource the user can perform the action on.
+    # If you pass :all it will apply to every resource. Otherwise pass a Ruby
+    # class of the resource.
+    #
+    # The third argument is an optional hash of conditions to further filter the
+    # objects.
+    # For example, here the user can only update published articles.
+    #
+    #   can :update, Article, :published => true
+    #
+    # See the wiki for details:
+    # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
+  end
+end

+ 120 - 0
app/models/ad_item.rb

@@ -0,0 +1,120 @@
+# encoding: utf-8
+class AdItem < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "ad_items"
+  belongs_to :ad_position
+  after_destroy :after_destroy
+  validates :ad_position_id, :name, :img, presence: true
+  attr_accessor  :v_img
+
+  IMG_STORE_PATH = "ad_item" 
+
+  URL_TYPE_ENUM = [["内部链接",0],["外部链接",1]]
+  
+  rails_admin do
+    navigation_label '广告渠道管理'
+    weight -500
+    parent AdPosition
+    list do
+      filters [:ad_position,:name, :state,:expired_at]
+      field :id
+      field :ad_position
+      field :name
+      field :img do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_img,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_img}')"})
+          
+        end
+      end
+      field :click_url
+      field :url
+      field :url_type, :enum do
+          enum do 
+              URL_TYPE_ENUM
+          end
+      end
+      field :click_times
+      field :show_times      
+      field :expired_at
+      field :state
+      field :sort
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :ad_position
+      field :name
+      field :img do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_img,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_img}')"})
+          
+        end
+      end
+      field :click_url
+      field :url
+      field :url_type, :enum do
+          enum do 
+              URL_TYPE_ENUM
+          end
+      end
+      field :click_times
+      field :show_times      
+      field :expired_at
+      field :state
+      field :sort
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :ad_position
+      field :name
+      field :v_img, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img, :class => 'preview'})
+        end        
+      end
+      field :click_url
+      field :url
+      field :url_type, :enum do
+          enum do 
+              URL_TYPE_ENUM
+          end
+      end
+      field :expired_at
+      field :state
+      field :sort            
+    end
+  end
+
+  def v_img=file
+    unless file.blank?
+      clear_img
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.img = file_path
+      self.save
+    end
+  end
+
+  def clear_img
+    file_path = "#{self.img}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_img
+    url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.img}"
+    return url
+  end
+
+  def after_destroy
+    clear_img    
+  end
+end

+ 51 - 0
app/models/ad_item_click_statistic.rb

@@ -0,0 +1,51 @@
+# encoding:utf-8
+class AdItemClickStatistic < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "ad_item_click_statistics"
+  validates_presence_of :ad_item_id, :wx_uid, :click_times
+
+  belongs_to :wx_user, :foreign_key => :wx_uid
+  belongs_to :ad_item, :foreign_key => :ad_item_id
+
+  rails_admin do
+    navigation_label '广告渠道管理'
+    weight -500
+    parent AdPosition
+
+    list do
+      filters [:id, :wx_user, :ad_item]
+      field :id
+      field :ad_item_id
+      field :ad_item
+      field :wx_uid
+      field :wx_user
+      field :ip
+      field :click_times
+      field :click_last_time
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :ad_item_id
+      field :ad_item
+      field :wx_uid
+      field :wx_user
+      field :ip
+      field :click_times
+      field :click_last_time
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      # field :ad_item_id
+      field :ad_item
+      field :wx_uid
+      field :ip
+      field :click_times
+      field :click_last_time
+    end
+  end
+end

+ 51 - 0
app/models/ad_item_show_statistic.rb

@@ -0,0 +1,51 @@
+# encoding:utf-8
+class AdItemShowStatistic < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "ad_item_show_statistics"
+  validates_presence_of :ad_item_id, :wx_uid, :show_times
+
+  belongs_to :wx_user, :foreign_key => :wx_uid
+  belongs_to :ad_item, :foreign_key => :ad_item_id
+
+  rails_admin do
+    navigation_label '广告渠道管理'
+    weight -500
+    parent AdPosition
+
+    list do
+      filters [:id, :wx_user, :ad_item]
+      field :id
+      field :ad_item_id
+      field :ad_item
+      field :wx_uid
+      field :wx_user
+      field :ip
+      field :show_times
+      field :show_last_time
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :ad_item_id
+      field :ad_item
+      field :wx_uid
+      field :wx_user
+      field :ip
+      field :show_times
+      field :show_last_time
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      # field :ad_item_id
+      field :ad_item
+      field :wx_uid
+      field :ip
+      field :show_times
+      field :show_last_time
+    end
+  end
+end

+ 51 - 0
app/models/ad_position.rb

@@ -0,0 +1,51 @@
+# encoding: utf-8
+class AdPosition < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "ad_positions"
+  has_many :ad_items
+  validates :code,:name,:remark,presence: true
+
+  rails_admin do
+    navigation_label '广告渠道管理'
+    weight -500
+    list do
+      filters [:name,:state]
+      field :id
+      field :code
+      field :ad_items
+      field :name
+      # field :img
+      field :click_url
+      field :click_times
+      field :state
+      field :remark
+      field :created_at
+      # field :updated_at
+    end
+    show do
+      field :id
+      field :code
+      field :ad_items
+      field :name
+      field :img
+      field :click_url
+      field :click_times
+      field :state
+      field :remark
+      field :created_at
+      # field :updated_at
+    end
+    edit do
+      field :code
+      field :ad_items
+      field :name
+      field :img
+      field :click_url
+      # field :click_times
+      field :state
+      field :remark    
+    end
+
+  end
+
+end

+ 68 - 0
app/models/address.rb

@@ -0,0 +1,68 @@
+# encoding:utf-8
+class Address < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "addresses"
+  belongs_to :user, :foreign_key => :user_id
+  belongs_to :wx_user, :foreign_key => :wx_user_id
+
+  def address_format
+    return self.province + self.city + self.district + self.address
+  end
+
+  rails_admin do
+    navigation_label '用户信息管理'
+    weight -55
+    
+    list do   
+      filters [:user,:tel,:province,:city]
+      field :id
+      # field :user_id
+      field :user
+      field :wx_user
+      field :contact
+      field :tel
+      field :province
+      field :city
+      field :district
+      field :address
+      field :address_format
+      field :postcode
+      field :state
+      field :remark
+      # field :created_at
+      field :updated_at
+    end
+    show do   
+      field :id
+      field :user_id
+      field :user
+      field :wx_user_id
+      field :wx_user
+      field :tel
+      field :contact
+      field :address
+      field :province
+      field :city
+      field :district
+      field :postcode
+      field :state
+      field :remark
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :user_id
+      field :wx_user_id
+      field :tel
+      field :contact
+      field :address
+      field :province
+      field :city
+      field :district
+      field :postcode
+      field :state
+      field :remark
+    end
+  end
+end

+ 44 - 0
app/models/admin_permission.rb

@@ -0,0 +1,44 @@
+# encoding:utf-8
+class AdminPermission < ActiveRecord::Base
+  has_paper_trail
+  CAN_OPTIONS = %w(manage create update read write import export history)
+  # attr_accessible :model, :can
+  validates_inclusion_of :can, in: CAN_OPTIONS
+  validates :model, :can, presence: true
+
+  has_and_belongs_to_many :admin_roles, join_table: :admin_permissions_admin_roles
+
+
+  rails_admin do
+    navigation_label '系统管理'
+    weight -20
+    configure :admin_roles do
+      inverse_of :admin_permissions
+    end
+    list do
+      filters [:model,:can]
+    end
+    edit do
+      field :model, :enum do
+        enum do
+          RailsAdmin::Config.models.collect do |model|
+            model_name = model.abstract_model.model_name
+            [eval("#{model_name}.model_name.human"), model_name]
+          end
+        end
+      end
+      field :can, :enum do
+        enum do
+          CAN_OPTIONS.collect do |can|
+            [I18n.t(can), can]
+          end
+        end
+      end
+    end
+  end
+
+  def name
+    model_name = model.present? ? eval("#{model}.model_name.human") : ''
+    "#{I18n.t(self.can)}_#{model_name}"
+  end
+end

+ 19 - 0
app/models/admin_permissions_admin_role.rb

@@ -0,0 +1,19 @@
+# encoding:utf-8
+class AdminPermissionsAdminRole < ActiveRecord::Base
+  has_paper_trail
+
+  rails_admin do
+    navigation_label '系统管理'
+    weight -20
+
+    list do
+    	filters [:admin_role_id]
+    	field :id
+    	field :admin_role_id
+    	field :admin_permission_id
+    end
+
+    edit do
+    end
+  end
+end

+ 36 - 0
app/models/admin_role.rb

@@ -0,0 +1,36 @@
+# encoding:utf-8
+class AdminRole < ActiveRecord::Base
+  has_paper_trail
+  has_and_belongs_to_many :admin_users, join_table: :admin_roles_admin_users
+  has_and_belongs_to_many :admin_permissions, join_table: :admin_permissions_admin_roles
+
+  validates :name, presence: true
+
+  rails_admin do
+    navigation_label '系统管理'
+    weight -20
+    
+    #    parent User
+    configure :admin_permissions do
+      inverse_of :admin_roles
+    end
+
+    configure :admin_users do
+      hide
+    end
+
+    list do
+      filters [:name]
+      field :id
+      field :name
+      field :admin_users
+      field :admin_permissions
+      field :description
+      # field :created_at
+      # field :updated_at
+    end
+
+    edit do
+    end
+  end
+end

+ 19 - 0
app/models/admin_roles_admin_user.rb

@@ -0,0 +1,19 @@
+# encoding:utf-8
+class AdminRolesAdminUser < ActiveRecord::Base
+  has_paper_trail
+
+  rails_admin do
+    navigation_label '系统管理'
+    weight -20
+
+    list do
+    	filters [:admin_role_id,:admin_user_id]
+    	field :id
+    	field :admin_role_id
+    	field :admin_user_id
+    end
+
+    edit do
+    end
+  end
+end

+ 96 - 0
app/models/admin_user.rb

@@ -0,0 +1,96 @@
+# encoding: utf-8
+class AdminUser < ActiveRecord::Base
+  has_paper_trail
+
+  SUPER_ADMIN = Rails.env == "production" ? "super@fh666.com" : "super@fohow.com"
+
+  # Include default devise modules. Others available are:
+  # :confirmable, :lockable, :timeoutable, :recoverable and :omniauthable
+  devise :database_authenticatable,
+    :rememberable, :trackable, :validatable
+
+  # Setup accessible (or protected) attributes for your model
+
+  has_and_belongs_to_many :admin_roles, :join_table => :admin_roles_admin_users
+
+  rails_admin do
+    navigation_label '系统管理'
+    weight -20
+    configure :admin_roles do
+      inverse_of :admin_users
+    end
+
+    list do
+      filters [:name]
+      field :id
+      field :name
+      field :admin_roles
+      field :email
+      # field :password
+      # field :password_confirmation
+      # field :company
+      field :created_at
+      # field :created_at do
+      #   formatted_value do
+      #     value.strftime("%Y-%m-%d %H:%m:%S") unless value == 0
+      #   end
+      # end
+      field :updated_at
+      field :sign_in_count
+      # field :current_sign_in_at
+      # field :last_sign_in_at
+      # field :current_sign_in_ip
+      # field :last_sign_in_ip
+    end
+
+    edit do
+      field :email, :string
+      field :name, :string
+      field :password, :password
+      field :password_confirmation, :password
+      field :admin_roles do
+        # 当管理员为超管或有manage_Role权限才能操作 角色列表
+        visible do
+          perms = bindings[:view].current_admin_user.permissions.collect{ |perm| "#{perm.can}_#{perm.model}"}
+          perms.include?("manage_AdminRole") or bindings[:view].current_admin_user.email == SUPER_ADMIN
+        end
+      end
+    end
+
+    show do
+      configure :remember_created_at do
+        formatted_value do
+          value.strftime("%Y-%m-%d %H:%m:%S") unless value == 0
+        end
+      end
+      configure :current_sign_in_at do
+        formatted_value do
+          value.strftime("%Y-%m-%d %H:%m:%S") unless value == 0
+        end
+      end
+      configure :last_sign_in_at do
+        formatted_value do
+          value.strftime("%Y-%m-%d %H:%m:%S") unless value == 0
+        end
+      end
+    end
+  end
+
+
+
+  #def name
+  #  email
+  #end
+
+  def permissions
+    _permissions = []
+    self.admin_roles.each do |role|
+      role.admin_permissions.each do |permission|
+        _permissions << permission
+      end
+    end
+    _permissions
+  end
+
+
+end

+ 213 - 0
app/models/ali.rb

@@ -0,0 +1,213 @@
+# encoding:utf-8
+require 'open-uri'
+require 'net/http'
+require 'uri'
+require 'json'
+require 'digest/md5'
+require 'digest/sha1'
+
+require 'aliyun/oss'
+
+module Ali
+
+  class Oss
+    BUCKET_NAME_PUBLIC_READ = CONFIG_FILE["ali_oss_bucket"] 
+    URL_FOR_HOST = "#{CONFIG_FILE["ali_oss_bucket"]}.#{CONFIG_FILE["ali_oss_data_center"]}.aliyuncs.com"
+    CDN_URL_FOR_HOST = URL_FOR_HOST
+
+    @client = Aliyun::OSS::Client.new(
+            :endpoint => "#{CONFIG_FILE["ali_oss_data_center"]}.aliyuncs.com",
+            :access_key_id => CONFIG_FILE["ali_access_id"],
+            :access_key_secret => CONFIG_FILE["ali_access_secret"])
+
+    class << self
+
+      def create_bucket(name, access = Aliyun::OSS::ACL::PUBLIC_READ)
+        begin                  
+          bucket = @client.create_bucket(name)          
+          bucket.acl = access        
+        rescue => e
+          p e
+        end
+        return bucket
+      end
+
+      def get_bucket(name)        
+        buckets = @client.list_buckets        
+        buckets.each do |item|
+          if item.name == name                  
+            return item
+          end
+        end        
+        return nil
+      end
+
+      def store(bucket_name, object_key, data)        
+        bucket = self.get_bucket(bucket_name)        
+        if bucket.blank?          
+          bucket = self.create_bucket(bucket_name)          
+        end        
+        bucket.put_object(object_key){ |stream| stream << data }        
+      end 
+
+      def object_exist?(bucket_name, object_key)
+        bucket = self.get_bucket(bucket_name)
+        if not bucket.blank?
+          objects = bucket.list_objects
+          objects.each do |obj|
+            if obj.key == object_key
+              return true
+            end 
+          end
+          return false   
+        else
+          raise "Bucket is not found with name: #{bucket_name}"
+        end
+      end      
+
+      def delete_object(bucket_name, object_key)
+        bucket = self.get_bucket(bucket_name)
+        if not bucket.blank?
+          begin
+            bucket.delete_object(object_key)  
+          rescue Exception => e
+            p e
+          end          
+        else
+          raise "Bucket is not found with name: #{bucket_name}"
+        end
+      end
+
+    end
+  end
+
+
+  class Css
+    #    attr_reader :version, :host
+    #    attr_accessor :client_id, :secret_key
+
+    ACCESS_KEY_ID = "HNPD1U7r1eWPzB82"
+    SECRET_ACCESS_KEY = "yhmPqp3jBndWf8D9b5p40BRyNyqYG6"
+    #内网
+    #    HOST = "http://intranet.opensearch-cn-hangzhou.aliyuncs.com"
+    #外网
+    HOST = {
+      "production" => "http://opensearch-cn-hangzhou.aliyuncs.com",
+      "development" => "http://opensearch-cn-qingdao.aliyuncs.com"
+    }
+
+    class << self
+
+      #根据参数创建签名信息
+      def _signature(params, method)
+        _params = {}
+        params.each do |k,v|
+          _params[k.to_s] = v
+        end
+        _params = _params.sort
+        data = []
+        _params.each do |p|
+          next if p[1].size <= 0
+          # p "before encode:#{p[1]}" if p[0] == "items"
+          _p = URI.encode_www_form_component(p[1])
+          _p = _p.gsub("+","%20").gsub("*","%2A").gsub("%7E","~")
+          # p "after encode:#{_p}" if p[0] == "items"
+          data << "#{URI.encode_www_form_component(p[0])}=#{_p}"
+        end
+        data = URI.encode_www_form_component(data.join("&"))
+        data = [method.upcase, URI.encode_www_form_component("/"), data].join("&")
+        # p "stringtosign=#{data}"
+        data = data.gsub("%7E","~")
+        signature = Base64::encode64(HMAC::SHA1.digest("#{SECRET_ACCESS_KEY}&", data))
+        # p "signature=#{signature[0..-2]}"
+        return signature[0..-2]
+      end
+
+      def _api_call(url, method = 'GET', params = {})
+        begin
+          params['Version'] = "v2"
+          params['AccessKeyId'] = ACCESS_KEY_ID
+          params['SignatureMethod'] = "HMAC-SHA1"
+          t = Time.now.to_i - 8*3600
+          params['Timestamp'] =  "#{Time.at(t).strftime("%Y-%m-%dT%H:%M:%SZ")}"
+          params['SignatureVersion'] = "1.0"
+          params['SignatureNonce'] = "#{Time.now.to_i}#{'%04d'%rand(9999)}"
+          params['Signature'] = _signature(params, method)
+          url = self::HOST[Rails.env] + url
+          if method.upcase == 'GET'
+            response = RestClient.get url, {:params => params}
+          else
+            response = RestClient.post url, params
+          end
+          return JSON.parse(response.body)
+        rescue => e
+          p e
+        end
+      end
+
+      def list_index()
+        uri = "/index"
+        _api_call(uri, "get",{})
+      end
+
+      def create_index(index_name, template = "xikego_product")
+        uri = "/index/#{index_name}"
+        _api_call(uri, "post", {:action => "create", :template => template})
+      end
+
+      def delete_index(index_name)
+        uri = "/index/#{index_name}"
+        _api_call(uri, "post",{:action => "delete"})
+      end
+
+      def show_index(index_name)
+        uri = "/index/#{index_name}"
+        _api_call(uri, "get",{:action => "status"})
+      end
+
+      #items是个数组
+      def create_doc(index_name, table_name, fields)
+        uri = "/index/doc/#{index_name}"
+        # t = (Time.now.to_i - 8*3600)*1000
+        # items = [{"cmd" => "add", "timestamp" => t, "fields" => fields}]
+        items = [{"cmd" => "add",  "fields" => fields}]
+        items = items.to_json
+        ret = _api_call(uri, "post",{"action" => "push", "table_name" =>  table_name, "items" => items})
+        return ret
+      end
+
+      def delete_doc(index_name, table_name, id)
+        uri = "/index/doc/#{index_name}"
+        items = [{"cmd" => "delete", "fields" => {"id" => id.to_s}}]
+        items = items.to_json
+        _api_call(uri, "post",{"action" => "push", "table_name" =>  table_name, "items" => items})
+      end
+
+      def update_doc(index_name, table_name, fields)
+        uri = "/index/doc/#{index_name}"
+        # t = (Time.now.to_i - 8*3600)*1000
+        # items = [{"cmd" => "update", "timestamp" => t, "fields" => fields}]
+        items = [{"cmd" => "update", "fields" => fields}]
+        items = items.to_json
+        _api_call(uri, "post",{"action" => "push","table_name" =>  table_name,  "items" => items})
+      end
+
+      def search_doc(index_names, query)
+        if index_names.class == Array
+          index_name = index_names.join(";")
+        else index_names.class == String
+          index_name = index_names
+        end
+        uri = "/search"
+        _api_call(uri,"get",{:query => query, :index_name => index_name, :summary_field => "title" })
+      end
+
+    end
+  end
+
+
+end
+
+if __FILE__ == $0
+
+end

+ 252 - 0
app/models/article.rb

@@ -0,0 +1,252 @@
+# encoding:utf-8
+require 'uuid'
+class Article < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "articles"
+  after_destroy :after_destroy
+  belongs_to :article_cat
+  validates :title,:content,:article_cat_id,presence: true
+  attr_accessor :v_cover 
+  attr_accessor :v_s_img
+   
+  IMG_STORE_PATH = "articles" 
+
+  STATE_ENUM = [["是",1],["否",0]]
+  DISPLAY_COVER_ENUM = [["显示",1],["不显示",0]]
+
+  rails_admin do
+    navigation_label '文章栏目管理'
+    weight -240
+
+    list do
+      filters [:id,:source,:title]
+      # include_all_fields
+      field :id                                                                                         
+      field :title
+      field :subtitle
+      field :about
+      # field :content
+      field :cover do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_img,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_img}')"})
+          
+        end
+      end
+      field :s_img do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_s_img,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_s_img}')"})
+          
+        end
+      end
+      field :source
+      field :editor
+      field :click
+      field :sort
+      field :recommend
+      field :state
+      field :show_cs_qrcode
+      field :created_by
+      # # field :category_id
+      field :article_cat
+      # field :agree
+      # field :disagree
+      # # field :comments_count
+      # field :v_cover
+      field :tags
+      field :display_cover, :enum do
+        enum do
+          DISPLAY_COVER_ENUM
+        end
+      end      
+      field :url
+      field :share_benefit_desc
+      # field :is_recommand
+      field :created_at
+      # field :updated_at
+    end
+
+    show do
+      field :id                                                                                                              
+      field :title
+      field :subtitle
+      field :about
+      field :s_title 
+      field :cover do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_img,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_img}')"})   
+        end
+      end
+      field :s_img do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_s_img,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_s_img}')"})
+          
+        end
+      end
+      field :source
+      field :editor
+      field :click
+      field :sort
+      field :recommend
+      field :state
+      field :show_cs_qrcode
+      field :created_by
+      field :article_cat
+      field :seo_title
+      field :seo_keyword
+      field :seo_desc
+      field :tags
+      field :display_cover, :enum do
+        enum do
+          DISPLAY_COVER_ENUM
+        end
+      end
+      field :url      
+      field :share_benefit_desc
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :title
+      field :subtitle
+      field :about
+      field :s_title
+      field :display_cover, :enum do
+        enum do
+          DISPLAY_COVER_ENUM
+        end
+      end
+      field :url
+      field :source
+      field :editor
+      field :sort
+      field :recommend
+      field :state
+      field :show_cs_qrcode
+      field :created_by
+      field :article_cat
+      field :seo_title
+      field :seo_keyword
+      field :seo_desc
+      field :tags
+      field :content, :ck_editor
+      # field :cover
+      field :v_cover, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img, :class => 'preview'})
+        end        
+      end
+      field :v_s_img, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_s_img, :class => 'preview'})
+        end        
+      end
+      #field :share_benefit_min
+      #field :share_benefit_max
+      #field :share_benefit_must_follow
+      #field :benefit_max
+      #field :single_benefit_max
+      #field :same_ip_limit
+ 
+      # field :click
+      # field :status
+      # field :category_id
+      # field :agree
+      # field :disagree
+      # field :comments_count
+      # field :is_recommand
+      field :url_guide, :ck_editor
+      field :share_benefit_desc
+    end
+  end
+
+  def v_cover=file
+    unless file.blank?
+      clear_img
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.cover = file_path
+      self.save
+    end
+  end
+
+  def v_s_img=file
+    unless file.blank?
+      clear_s_img
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.s_img = file_path
+      self.save
+    end
+  end
+
+  def clear_img
+    file_path = "#{self.cover}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def clear_s_img
+    file_path = "#{self.s_img}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_img
+    url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.cover}"
+    return url
+  end
+
+  def get_s_img
+    url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.s_img}"
+    return url
+  end
+
+  def after_destroy
+    clear_img   
+    clear_s_img     
+  end
+
+  # def cover=(file)
+  #   unless file.blank?
+  #     clear_cover
+  #     _ = UUID.new.generate[0...8]
+  #     Ali::Oss.store_article_cover(_, file.read)
+  #     write_attribute :cover, _
+  #   end
+  # end
+
+
+  # def cover(size='')
+  #   _ = read_attribute(:cover)
+  #   _.blank? ? '' : Ali::Oss.url_for_article_cover(_, size)
+  # end
+
+  # def clear_cover
+  #   Ali::Oss.del_file_article_cover(read_attribute(:cover))
+  # end
+
+  # private
+
+  # def resource_url
+  #   self.cover
+  # end
+
+  # def after_create
+  #   Search.create_index(Search::INDEX_NAME_OF_ARTICLES, self.id, self.title,
+  #                       self.about, self.editor, self.source, self.created_at.to_i, "#{CONFIG_FILE["host"]}/article/#{self.id}?from=search", "文章")
+  # end
+
+  # def after_destroy
+  #   #删除在阿里的索引
+  #   Ali::Css.delete_doc(Search::INDEX_NAME_OF_ARTICLES, self.id)
+  # end
+end

+ 44 - 0
app/models/article_cat.rb

@@ -0,0 +1,44 @@
+# encoding:utf-8
+class ArticleCat < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "article_cats"
+  has_ancestry
+  has_many :articles #, :dependent  => :destroy
+  validates :name, presence: true
+
+  rails_admin do
+    navigation_label '文章栏目管理'
+    weight -240
+    nestable_tree({
+                    position_field: :position,
+                    max_depth: 2
+    })
+    
+    list do
+      filters [:name,:ancestry,:position]
+      # include_all_fields
+      field :id
+      field :name
+      field :position
+      field :ancestry
+      field :state
+      field :articles
+      # field :url
+    end
+
+    show do
+      field :id
+      field :name
+      field :position
+      field :ancestry
+      field :state
+      field :articles
+    end
+
+    edit do
+      field :name
+      field :state
+      field :articles
+    end
+  end
+end

+ 99 - 0
app/models/balance.rb

@@ -0,0 +1,99 @@
+# encoding:utf-8
+class Balance < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "balances"
+  belongs_to :user
+  belongs_to :wx_user
+  validates_presence_of :user_id, :count, :relate_id, :source
+  attr_accessor :remain_sum
+
+  SOURCE_ENUM = [["企业大使兑换", "platform_exchange"],
+                 ["兑换商品", "exchange_product"],
+                 ["充值", "recharge"],
+                 ["群员购物扣除", "frend_buy"],
+                 ["全额退款", "all_refunded"],
+                 ["部分退款", "part_refunded"],
+                 ["扣除","deduct"]]
+
+  def remain_sum
+    b = Balance.where("wx_user_id = ? and id < ?", self.wx_user_id, self.id).last
+    if !b.blank?
+      return self.count + b.remain_sum
+    else
+      return self.count
+    end
+  end
+  rails_admin do
+    navigation_label '资金管理'
+    weight -920
+
+    list do
+      items_per_page 10
+      filters [:id, :source, :user, :relate_id,:wx_user,:created_at]
+      # include_all_fields
+      field :id
+      field :user
+      field :user_id
+      field :wx_user
+      field :wx_user_id
+      field :count do
+        formatted_value do
+          value.to_f / 100.0
+        end
+      end
+      field :remain_sum do
+        formatted_value do
+          value.to_f / 100.0
+        end
+      end
+      field :relate_id
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :remark
+      field :created_at
+      # field :updated_at
+    end
+
+    show do
+      field :user_id
+      field :wx_user
+      field :wx_user_id
+      field :count do
+        formatted_value do # used in form views
+          value.to_f / 100.0
+        end
+      end
+      field :remain_sum do
+        formatted_value do
+          value.to_f / 100.0
+        end
+      end
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :relate_id
+      field :remark
+      field :created_at
+    end
+
+    edit do
+      field :user_id
+      field :wx_user_id
+      field :count do
+        label "变动金额,单位(分)"
+      end
+      field :relate_id
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :remark
+    end
+  end
+end

+ 112 - 0
app/models/balance_order.rb

@@ -0,0 +1,112 @@
+# encoding:utf-8
+class BalanceOrder < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "balance_orders"
+  belongs_to :user
+  belongs_to :wx_user
+  validates :order_id,:user_id,:total_price,presence: true
+
+  PAY_WAY_ENUM = [
+    ["Web网银连连支付","webbankllpay"],
+    ["Web认证连连支付","webauthllpay"],
+    ["Wap认证连连支付","wapauthllpay"],
+    ["微信支付","service_wxpay"],
+    ["统统微信支付","wx_sumpay"],
+    ["统统Web网银支付","webbanksumpay"],
+  ]
+
+  rails_admin do
+    navigation_label '资金管理'
+    parent Balance
+    weight -920
+
+    list do
+      filters [:order_id,:state,:wx_user,:created_at]
+      field :id
+      field :wx_user_id
+      field :wx_user
+      field :pay_way ,:enum do
+        enum do
+          PAY_WAY_ENUM
+        end
+      end
+      field :paied_at do
+        visible false
+        formatted_value do
+          (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+        end
+      end
+      field :order_id
+      field :trade_no do 
+        visible false
+      end
+      field :total_price do
+        label "总额(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :paied_price do
+        label "支付总额(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :state
+      field :created_at
+      field :updated_at
+      field :balance_bank_card_no
+      field :remark
+    end
+
+    show do
+      field :order_id
+      field :user
+      field :wx_user
+      field :pay_way ,:enum do
+        enum do
+          PAY_WAY_ENUM
+        end
+      end
+      field :paied_at do
+        formatted_value do
+          (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+        end
+      end
+      field :total_price do
+        label "总额(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :paied_price do
+        label "支付总额(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :balance_bank_card_no
+      field :remark
+      field :created_at
+    end
+
+    edit do
+      field :order_id
+      field :user_id
+      field :wx_user_id
+      field :pay_way ,:enum do
+        enum do
+          PAY_WAY_ENUM
+        end
+      end
+      # field :paied_at
+      field :trade_no
+      field :total_price do
+        label "总额(分)"
+      end
+      field :state
+      field :balance_bank_card_no
+      field :remark
+    end
+  end
+end

+ 108 - 0
app/models/cash_balance.rb

@@ -0,0 +1,108 @@
+# encoding:utf-8
+class CashBalance < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "cash_balances"
+  belongs_to :wx_user, :foreign_key => :wx_uid
+  validates_presence_of :wx_uid, :count, :relate_id, :source
+  attr_accessor :remain_sum
+
+  SOURCE_ENUM = [["代金券充值佣金", "balance_benefit"],
+                 ["商品佣金", "product_benefit"],
+                 ["好友购物佣金", "fx_product_benefit"],
+                 ["提现", "take_cash"],
+                 ["拒绝提现", "extract_reject"],
+                 ["销售奖金","sale_reward_monthly"],
+                 ["商品代销金", "product_sale"],
+                 ["助农项目", "project_invest"],
+                 ["充值","recharge"],
+                 ["预定活动","reserve_act_return"],
+                 ["项目回款","receive_buyback"],
+                 ["扣款","deduct"],
+                 ["借款","loan"],
+                 ["项目退款","project_refund"],
+                 ["商品退款","product_refund"],
+                 ["商品部分退款","product_part_refund"],
+                 ["冲正","correct"],
+                 ["项目放款","project_loan"],
+                 ["货款","good_payment"],
+                 ["活动退款","dollar_win_return"],
+                 ["活动报名","dollar_win"],
+               ]
+
+  def remain_sum
+    b = CashBalance.where("wx_uid = ? and id < ?", self.wx_uid, self.id).last
+    if !b.blank?
+      return self.count + b.remain_sum
+    else
+      return self.count
+    end
+  end
+  rails_admin do
+    navigation_label '资金管理'
+    weight -920
+
+    list do
+      items_per_page 10
+      filters [:id, :source, :wx_user, :relate_id, :created_at]
+      # include_all_fields
+      field :id
+      field :wx_user
+      field :wx_uid
+      field :count do
+        formatted_value do
+          value.to_f / 100.0
+        end
+      end
+      field :remain_sum do
+        formatted_value do
+          value.to_f / 100.0
+        end
+      end
+      field :relate_id
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :remark
+      field :created_at
+      # field :updated_at
+    end
+
+    show do
+      field :wx_uid
+      field :count do
+        formatted_value do # used in form views
+          value.to_f / 100.0
+        end
+      end
+      field :remain_sum do
+        formatted_value do
+          value.to_f / 100.0
+        end
+      end
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :relate_id
+      field :remark
+      field :created_at
+    end
+
+    edit do
+      field :wx_uid
+      field :count do
+        label "变动金额,单位(分)"
+      end
+      field :relate_id
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :remark
+    end
+  end
+end

+ 134 - 0
app/models/channel_qrcode.rb

@@ -0,0 +1,134 @@
+# encoding:utf-8
+class ChannelQrcode < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "channel_qrcodes"
+  belongs_to :wx_gongzhonghao
+  belongs_to :parent_signup_channel, :foreign_key => :parent_sign_up_channel_id
+  belongs_to :push_after_sub
+  validates :remark, :wx_gongzhonghao, presence: true
+  attr_accessor :v_qrcode_img
+
+  IMG_STORE_PATH = "channelqrcode"
+
+  after_destroy :after_destroy
+  after_create :after_create
+  # after_update :after_update
+
+  validate :generate_validation
+  def generate_validation
+    if (self.is_permanent == true) && (!self.expired_at.blank? && self.expired_at.to_i > 0)
+      self.errors.add(:expired_at,"永久性和过期时间不能同时填写")
+    elsif (self.is_permanent == false) && (self.expired_at.blank?) 
+      self.errors.add(:expired_at,"永久性和过期时间不能同时为空")
+    end
+  end
+
+  def v_qrcode_img=file
+    unless file.blank?
+      clear_qrcode_img
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/thumb/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.qrcode_img = file_path
+      self.save
+    end
+  end
+
+  def clear_qrcode_img
+    file_path = "#{self.qrcode_img}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_qrcode_img
+    return self.qrcode_img
+  end
+
+  def after_destroy
+    clear_qrcode_img
+  end
+
+  rails_admin do
+    navigation_label '二维码管理'
+    weight -500
+    
+    list do
+      filters [:wx_gongzhonghao, :is_permanent, :remark]
+      field :id
+      field :wx_gongzhonghao
+      field :scene_id
+      field :scene_str
+      field :remark
+      field :qrcode_img do
+        formatted_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_qrcode_img, :style => 'width:50px;cursor:pointer', :onClick => "javascript:window.open('#{bindings[:object].get_qrcode_img}')"})
+        end
+      end
+      field :qrcode_img_url
+      field :push_after_sub
+      field :is_permanent
+      field :scan_times
+      field :parent_signup_channel
+      field :expired_at
+      field :ad_cost do
+        label "投放广告费"
+      end
+
+    end
+
+    show do
+      field :id
+      field :wx_gongzhonghao
+      field :scene_id
+      field :scene_str do
+        label "渠道场景标识符"
+      end
+      field :remark
+      field :qrcode_img do
+        formatted_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_qrcode_img, :style => 'width:50px;cursor:pointer', :onClick => "javascript:window.open('#{bindings[:object].get_qrcode_img}')"})
+        end
+      end
+      field :qrcode_img_url
+      field :push_after_sub
+      field :is_permanent
+      field :scan_times
+      field :parent_signup_channel
+      field :expired_at
+      field :created_at
+    end
+
+    edit do
+      field :wx_gongzhonghao
+      field :scene_str do
+        label "渠道场景标识符"
+      end
+      field :remark
+      field :v_qrcode_img, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_qrcode_img, :class => 'preview'})
+        end
+      end
+      field :push_after_sub
+      field :is_permanent
+      field :parent_signup_channel
+      field :expired_at   
+      field :ad_cost
+    end
+  end
+
+  def qrcode_img_url
+    url = "#{CONFIG_FILE["api_host"]}/railsadmin/create_qrcode/#{self.id}"
+    if !self.scene_str.blank?
+      url = "#{CONFIG_FILE["api_host"]}/railsadmin/create_qrcode/scene_str/#{self.id}"
+    end 
+    if self.qrcode_img.blank?
+      open(url)
+    end
+    return url
+  end
+
+  def after_create
+    self.scene_id = self.id
+    self.save
+  end
+end

+ 69 - 0
app/models/channel_qrcode_result.rb

@@ -0,0 +1,69 @@
+# encoding:utf-8
+class ChannelQrcodeResult < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "channel_qrcode_results"
+  belongs_to :channel_qrcode
+  # belongs_to :wx_user, :foreign_key => :mp_openid
+  validates_presence_of :mp_openid,:channel_qrcode
+
+  def wx_user_nickname
+    return "-" if self.blank?
+    wx_user_gzh = WxUserGongzhonghao.where("gzh_open_id = ?", self.mp_openid).first
+    return "-" if wx_user_gzh.blank?
+    wx_user = WxUser.where("id = ?", wx_user_gzh.wx_user_id).first
+    return "-" if wx_user.blank?
+    return wx_user.nickname
+  end
+
+  def wx_user_id
+    return "-" if self.blank?
+    wx_user_gzh = WxUserGongzhonghao.where("gzh_open_id = ?", self.mp_openid).first
+    if !wx_user_gzh.blank?
+      return wx_user_gzh.wx_user_id
+    end
+  end
+
+  def user_tel
+    return "-" if self.blank?
+    wx_user_gzh = WxUserGongzhonghao.where("gzh_open_id = ?", self.mp_openid).first
+    return "-" if wx_user_gzh.blank?
+    wx_user = WxUser.where("id = ?", wx_user_gzh.wx_user_id).first
+    return "-" if wx_user.blank?
+    user = User.where("id = ?", wx_user.user_id).first
+    return "-" if user.blank?
+    return user.tel
+  end
+
+  rails_admin do
+    navigation_label '二维码管理'
+    parent ChannelQrcode
+    weight -500
+
+    list do
+      filters [:channel_qrcode, :id]
+      field :id
+      field :channel_qrcode
+      field :channel_qrcode_id
+      # field :mp_openid
+      field :user_tel
+      field :wx_user_nickname
+      field :wx_user_id
+      field :created_at
+    end
+    show do
+      field :id
+      field :channel_qrcode
+      field :channel_qrcode_id
+      field :mp_openid
+      field :user_tel
+      field :wx_user_nickname
+      field :wx_user_id
+      field :created_at
+    end
+
+    edit do
+      field :mp_openid
+      field :channel_qrcode
+    end
+  end
+end

+ 5 - 0
app/models/ckeditor/asset.rb

@@ -0,0 +1,5 @@
+class Ckeditor::Asset < ActiveRecord::Base
+  include Ckeditor::Orm::ActiveRecord::AssetBase
+  include Ckeditor::Backend::Paperclip
+  Rails.application.config.assets.precompile += %w( ckeditor/filebrowser/images/gal_del.png )
+end

+ 13 - 0
app/models/ckeditor/attachment_file.rb

@@ -0,0 +1,13 @@
+class Ckeditor::AttachmentFile < Ckeditor::Asset
+  has_attached_file :data,
+                    url: '/ckeditor_assets/attachments/:id/:filename',
+                    path: ':rails_root/public/ckeditor_assets/attachments/:id/:filename'
+
+  validates_attachment_presence :data
+  validates_attachment_size :data, less_than: 100.megabytes
+  do_not_validate_attachment_file_type :data
+
+  def url_thumb
+    @url_thumb ||= Ckeditor::Utils.filethumb(filename)
+  end
+end

+ 31 - 0
app/models/ckeditor/picture.rb

@@ -0,0 +1,31 @@
+class Ckeditor::Picture < Ckeditor::Asset
+  before_create :before_create
+
+  has_attached_file :data,{
+    storage: :aliyun,    
+    # path: 'ckeditor/detail/:id/:hash.:extension',
+    path: 'ckeditor/detail/:id/:style.:filename',
+    url: ':aliyun_upload_url',
+    styles: { content: '780>', thumb: '100>'}    
+    # hash_secret:'3c6acb54d3c7b788d853304142d669a9de78780ee672226009a35192d00d1dbc34f39e81f0f7f5248ce5f8e69c6e26d680bd0af9e8998b40333052ae7159d26e'
+  }
+
+  validates_attachment_presence :data
+  validates_attachment_size :data, less_than: 2.megabytes
+  validates_attachment_content_type :data, content_type: /\Aimage/
+
+  #解决中文文件名不能正常上传问题,上传之前重命名
+  def before_create    
+    extension = File.extname(filename).downcase      
+    extension = ".png" if extension.blank?
+    self.data.instance_write(:file_name, "#{Time.now.strftime("%Y%m%d%H%M%S")}#{rand(1000)}#{extension}")          
+  end 
+
+  def url_content    
+    url(:content)
+  end
+
+  rails_admin do
+    weight -20
+  end
+end

+ 36 - 0
app/models/common_use_limit.rb

@@ -0,0 +1,36 @@
+# encoding:utf-8
+class CommonUseLimit < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "common_use_limits"
+  belongs_to :wx_user, :foreign_key => :wx_uid
+
+  rails_admin do
+    navigation_label '资金管理'
+    weight -60
+    
+    list do   
+      filters [:is_limit_up_benefit_list, :is_effect]
+      field :id
+      field :wx_uid
+      field :wx_user
+      field :is_limit_up_benefit_list
+      field :is_effect
+      field :created_at
+    end
+    show do   
+      field :id
+      field :wx_uid
+      field :wx_user
+      field :is_limit_up_benefit_list
+      field :is_effect
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :wx_uid
+      field :is_limit_up_benefit_list
+      field :is_effect
+    end
+  end
+end

+ 113 - 0
app/models/invite_benefit_order.rb

@@ -0,0 +1,113 @@
+# encoding: utf-8
+class InviteBenefitOrder < ActiveRecord::Base
+  has_paper_trail
+  belongs_to :wx_user, :foreign_key => :benefit_wx_uid
+  self.table_name = "invite_benefit_orders"  
+  attr_accessor :wx_user_name, :ind_wx_user_name
+
+  SOURCE_ENUM = [["代金券充值佣金","balance_benefit"],["邀请绑定","binding"],["直推商品佣金","product_benefit"],["分享商品佣金","fx_product_benefit"],["项目佣金","project_benefit"]]
+
+  def wx_user_name
+    u = WxUser.where(" id = ?", self.wx_uid).first
+    if !u.blank?
+      return u.nickname
+    end
+    return "-"
+  end
+
+  def wx_user_copartner
+    u = WxUser.where(" id = ?", self.benefit_wx_uid).first
+    if !u.blank?
+      return u.copartner_state
+    end
+    return "0"
+  end
+
+  def ind_wx_user_name
+    u = WxUser.where(" id = ?", self.ind_wx_uid).first
+    if !u.blank?
+      return u.nickname
+    end
+    return "-"
+  end
+  
+  rails_admin do
+    navigation_label '资金管理'
+    weight -500
+    list do
+      filters [:wx_user, :source,:relate_id]
+      field :id
+      field :benefit_wx_uid
+      field :wx_user
+      field :ind_wx_uid
+      field :ind_wx_user_name
+      field :count do
+        label "佣金金额(元)"
+        formatted_value do 
+          value.to_f / 100
+        end
+      end
+      field :amount do
+        label "订单价格(元)"
+        formatted_value do 
+          value.to_f / 100
+        end
+      end
+      field :source, :enum do
+          enum do 
+              SOURCE_ENUM
+          end
+      end
+      field :relate_id
+      field :is_enter_balance
+      field :enter_time
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :benefit_wx_uid
+      field :wx_user
+      field :ind_wx_uid
+      field :ind_wx_user_name
+      field :count do
+        label "佣金金额(元)"
+        formatted_value do 
+          value.to_f / 100
+        end
+      end
+      field :amount do
+        label "订单价格(元)"
+        formatted_value do 
+          value.to_f / 100
+        end
+      end
+      field :source, :enum do
+          enum do 
+              SOURCE_ENUM
+          end
+      end
+      field :relate_id
+      field :is_enter_balance
+      field :enter_time
+      field :created_at
+      field :updated_at
+    end
+
+    edit do       
+      field :benefit_wx_uid
+      field :ind_wx_uid
+      field :count
+      field :amount
+      field :source, :enum do
+          enum do 
+              SOURCE_ENUM
+          end
+      end
+      field :relate_id      
+      field :is_enter_balance
+      field :enter_time
+    end
+  end  
+end

+ 68 - 0
app/models/key_word_push.rb

@@ -0,0 +1,68 @@
+# encoding:utf-8
+class KeyWordPush< ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "key_word_pushs"
+  validates_presence_of :key_word, :push_type, :remark
+  belongs_to :wx_gongzhonghao
+  PUSH_TYPE_ENUM = [["图片","image"], ["文字","text"], ["图文","article"]]
+
+  rails_admin do
+    navigation_label '公众号管理'
+    weight -350
+
+    list do
+      filters [:id, :key_word]
+      field :id
+      field :key_word
+      field :push_title
+      field :push_type, :enum do
+        enum do
+          PUSH_TYPE_ENUM
+        end
+      end
+      field :cover
+      field :word
+      field :url
+      field :remark
+      field :wx_gongzhonghao_id
+      field :wx_gongzhonghao
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :key_word
+      field :push_title
+      field :push_type, :enum do
+        enum do
+          PUSH_TYPE_ENUM
+        end
+      end
+      field :cover
+      field :word
+      field :url
+      field :remark
+      field :wx_gongzhonghao_id
+      field :wx_gongzhonghao
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :key_word
+      field :push_title
+      field :push_type, :enum do
+        enum do
+          PUSH_TYPE_ENUM
+        end
+      end
+      field :cover
+      field :word
+      field :url
+      field :remark
+      field :wx_gongzhonghao
+    end
+  end
+
+end

+ 84 - 0
app/models/merchant.rb

@@ -0,0 +1,84 @@
+class Merchant < ActiveRecord::Base
+    has_paper_trail
+    self.table_name = "merchants"
+    belongs_to :user, :foreign_key => :user_id
+    validates :user_id, presence: true
+
+    VOUCHER_TYPE = [
+    ['普通发票', 'ordinary'],
+    ['增值发票', 'appreciation'],
+    ['收据', 'receipt']
+    ]
+
+    def wx_user
+      wxUser = WxUser.where("user_id = ?", self.user_id).first
+      if !wxUser.blank?
+        return wxUser.nickname
+      else
+        return "不存在"
+      end
+    end
+
+    rails_admin do 
+
+        navigation_label '商品管理'
+        weight -100
+
+        list do 
+          filters [:id,:name]
+          field :id      
+          field :name 
+          # field :user_id
+          # field :user
+          # field :wx_user
+          # field :contact
+          # field :tel
+          field :payee
+          field :bank_card_no
+          field :bank_name
+          field :back_voucher, :enum do 
+            enum do 
+              VOUCHER_TYPE
+            end
+          end
+          field :created_at
+
+        end
+
+        show do
+          field :id      
+          field :name 
+          # field :user_id
+          # field :user
+          # field :wx_user
+          # field :contact
+          # field :tel
+          field :payee
+          field :bank_card_no
+          field :bank_name
+          field :back_voucher, :enum do 
+            enum do 
+              VOUCHER_TYPE
+            end
+          end
+          field :created_at
+          field :updated_at
+        end
+
+        edit do     
+          field :name 
+          field :user_id
+          field :contact
+          field :tel
+          field :payee
+          field :bank_card_no
+          field :bank_name
+          field :back_voucher
+          field :back_voucher, :enum do 
+            enum do 
+              VOUCHER_TYPE
+            end
+          end
+        end
+    end
+end

+ 80 - 0
app/models/merchant_user_relation.rb

@@ -0,0 +1,80 @@
+class MerchantUserRelation < ActiveRecord::Base
+    has_paper_trail
+    self.table_name = "merchant_user_relations"
+    belongs_to :user, :foreign_key => :user_id
+    belongs_to :merchant, :foreign_key => :merchant_id
+    validates :user_id, :merchant_id, :manage_product_ids, presence: true
+
+    validate :check_user_no_more_merchant, :on => :create
+    validate :check_merchant_is_exist
+
+    def check_user_no_more_merchant
+      sql = "select * from merchant_user_relations where user_id = #{self.user_id} and is_effect = 1"
+      cs = MerchantUserRelation.find_by_sql(sql).first
+      if !cs.blank?
+          self.errors.add(:user_id,"暂不支持一个用户对应多个商家")
+      end
+    end
+
+    def check_merchant_is_exist
+      sql = "select * from merchants where id = #{self.merchant_id}"
+      merchant = Merchant.find_by_sql(sql).first
+      if merchant.blank?
+        self.errors.add(:merchant_id,"该商家信息不存在")
+      end
+    end
+
+    def wx_user
+      wxUser = WxUser.where("user_id = ?", self.user_id).first
+      if !wxUser.blank?
+        return wxUser.nickname
+      else
+        return "不存在"
+      end
+    end
+
+
+    rails_admin do 
+
+        navigation_label '商品管理'
+        weight -100
+
+        list do 
+          filters [:id,:user,:merchant]
+          field :id      
+          field :user_id
+          field :user
+          field :wx_user
+          field :merchant_id
+          field :merchant 
+          field :is_effect  
+          field :is_super_admin
+          field :manage_product_ids  
+          field :created_at
+        end
+
+        show do
+          field :id      
+          field :user_id
+          field :user
+          field :wx_user
+          field :merchant_id
+          field :merchant
+          field :is_effect  
+          field :is_super_admin
+          field :manage_product_ids   
+          field :created_at
+          field :updated_at
+        end
+
+        edit do     
+          field :user_id
+          field :merchant_id
+          field :is_effect
+          field :is_super_admin
+          field :manage_product_ids do
+            label "管理的商品ids(0表示所有商品,不填0则商品id之间用逗号隔开)"
+          end
+        end
+    end
+end

+ 110 - 0
app/models/navigate_icon_config.rb

@@ -0,0 +1,110 @@
+require 'uuid'
+class NavigateIconConfig < ActiveRecord::Base
+    has_paper_trail
+    self.table_name = 'navigate_icon_configs'
+    attr_accessor :v_cover
+    validates :name,:sort,:url, presence: true
+
+    IMG_STORE_PATH = "navigate_icon_config" 
+
+    URL_TYPE_ENUM = [["内部链接",0],["外部链接",1]]
+
+    rails_admin do
+        navigation_label '平台栏目管理'
+        weight -240
+
+        list do
+            filters [:name,:url_type]
+            field :id
+            field :name
+            field :sort 
+            field :url
+            field :url_type, :enum do
+                enum do 
+                    URL_TYPE_ENUM
+                end
+            end
+
+            field :cover do
+                formatted_value do
+                bindings[:view].tag(:img, {:src => bindings[:object].get_cover,
+                :style => 'width: 100px;height: 100px;cursor: pointer;display:  block;max-width: 100px;',
+                :onClick => "javascript:window.open('#{bindings[:object].get_cover}')"})
+          
+                end
+            end
+            field :product_cat_index
+            field :state
+            field :remark
+        end 
+
+        show do 
+            field :id
+            field :name
+            field :sort
+            field :url
+            field :url_type, :enum do
+                enum do 
+                    URL_TYPE_ENUM
+                end
+            end
+            field :cover do
+                formatted_value do
+                bindings[:view].tag(:img, {:src => bindings[:object].get_cover,
+                :style => 'width: 100px;height: 100px;cursor: pointer;display:  block;max-width: 100px;',
+                :onClick => "javascript:window.open('#{bindings[:object].get_cover}')"})
+          
+                end
+            end
+            field :product_cat_index
+            field :state
+            field :remark
+        end
+
+        edit do 
+            field :name
+            field :sort 
+            field :url
+            field :url_type, :enum do
+                enum do 
+                    URL_TYPE_ENUM
+                end
+            end
+            field :v_cover,:file_upload do 
+                pretty_value do 
+                    bindings[:view].tag(:img, {:src => bindings[:object].get_cover, :class => 'preview'})
+                end        
+            end
+            field :product_cat_index
+            field :state
+            field :remark
+        end
+
+    end
+
+    def v_cover=file
+        unless file.blank?
+          clear_cover
+          file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+          file_path = "#{IMG_STORE_PATH}/#{file_name}"
+          Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+          self.cover = file_path
+          self.save
+        end
+    end
+
+    def clear_cover
+        file_path = "#{self.cover}"
+        Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+    end
+
+    def get_cover
+      url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.cover}"
+      return url
+    end
+
+    def after_destroy
+      clear_cover       
+    end
+
+end

+ 303 - 0
app/models/order.rb

@@ -0,0 +1,303 @@
+#encoding=UTF-8
+require 'json'
+require 'rest-client'
+class Order < ActiveRecord::Base
+    has_paper_trail
+    self.table_name = 'orders'
+    validates_presence_of :user_id,:total_price,:order_id
+    #belongs_to :user, :foreign_key => :user_id
+    belongs_to :wx_user, :foreign_key => :wx_user_id
+    has_many :order_details
+
+    STATUS_ENUM = [["未支付","unpay"],["已关闭","closed"],["待确认","unconfirmed"],["处理中","processing"],["已完成","complete"],["待收货","dispatch"],["已退款","refunded"]]
+    TYPE_ENUM = [["普通",0],["自用",2],["代销",1],["牛就对了(购买)",3],["牛就对了(兑奖)",4]]
+
+    PAY_WAY_ENUM = [
+
+    ["微信支付","weixinpay"],
+    ["代金券支付","balance"],
+    ]
+
+    SOURCE_ENUM = [["小程序","xcx"],["公众号","gzh"],["第五创系统","d5c_sys"]]
+
+    def user_tel
+      linkUser = User.where("id = ?", self.user_id).first
+      if !linkUser.blank?
+        if linkUser.is_black_user
+            return linkUser.tel + " 【黑名单】"
+        else
+            return linkUser.tel
+        end
+      else
+        return "不存在"
+      end
+    end
+
+    def w_user
+        if !wx_user.blank?
+                return wx_user.nickname
+        else
+            return "--"
+        end
+    end
+
+
+    def merchant 
+
+        tmp = "-"
+        prod = Product.where("id = ?", self.product_id).first
+        if !prod.blank?
+
+            merchant = Merchant.where("id = ?", prod.merchant_id).first
+            if !merchant.blank?
+                tmp = merchant.name
+            end
+        end
+        return tmp
+
+    end
+
+
+
+    def total_price_format
+        case self.pay_way
+        when "weixinpay"
+            total_price_f = self.total_price!=0 ? (self.total_price/100.0) :0
+            return total_price_f.to_s #+ "元"
+        when "balance"
+            total_price_f = self.total_price!=0 ? (self.total_price/100.0) :0
+            return total_price_f.to_s #+ "代金券"
+        when "integral"
+            total_price_f = self.total_price!=0 ? (self.total_price/100.0) :0
+            return total_price_f.to_s #+ "代金券"
+        end
+    end
+
+    def paied_price_format
+        case self.pay_way
+        when "weixinpay"
+            paied_price_f = self.paied_price!=0 ? ((self.paied_price+self.freight)/100.0) :0
+            return paied_price_f.to_s # + "元"
+        when "balance"
+            paied_price_f = self.paied_price!=0 ? ((self.paied_price+self.freight)/100.0) :0
+            return paied_price_f.to_s #+ "代金券"
+        when "integral"
+            paied_price_f = self.paied_price!=0 ? ((self.paied_price+self.freight)/100.0) :0
+            return paied_price_f.to_s #+ "代金券"
+        end
+    end
+
+
+    rails_admin do 
+        navigation_label '商品管理'
+        weight -240
+
+        list do 
+            filters [:order_id,:status,:pay_way,:receive_time,:wx_user_id,:paied_time]
+            field :id do
+               visible false
+            end
+            field :order_id
+            field :order_type, :enum do 
+                filterable true
+                enum do 
+                    TYPE_ENUM
+                end
+            end
+            field :user_id do
+              visible false
+              filterable true
+            end
+            field :wx_user_id do
+                filterable true
+            end
+            field :w_user do
+                # visible false
+            end
+            field :user_tel do
+                # visible false
+            end
+            field :total_price do
+                visible false
+            end
+
+            field :freight do
+                visible true
+                label "运费(元)"
+                formatted_value do
+                    value!=0 ? (value/100.0):0
+                end
+            end
+            field :total_price_format do
+                visible true
+            end
+            field :paied_price_format do
+                visible true
+            end
+            field :trade_no do
+                visible false
+            end
+            field :status, :enum do
+                enum do 
+                    STATUS_ENUM
+                end
+            end
+
+            field :pay_way, :enum do 
+                enum do 
+                    PAY_WAY_ENUM
+                end
+            end
+            field :source, :enum do
+                visible false
+                enum do
+                    SOURCE_ENUM
+                end
+            end
+            field :paied_at do
+                formatted_value do
+                    (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+                end
+            end
+            field :paied_time do
+                visible false
+            end
+            field :contact
+            field :tel 
+            field :address
+            field :express_company
+            field :express_order_no
+            field :dispatch_time
+            field :receive_time do
+                # visible false
+            end
+            field :order_remark do
+                visible false
+            end
+            field :order_details
+            field :remark
+            field :created_at do
+                visible false
+            end
+        end
+
+        show do 
+            field :id 
+            field :order_id
+            field :wx_user
+            field :wx_user_id
+            field :freight do
+                visible true
+                label "运费(元)"
+                formatted_value do
+                    value!=0 ? (value/100.0):0
+                end
+            end
+            field :total_price_format
+            field :paied_price_format
+            field :buy_price
+            field :trade_no
+            field :status, :enum do
+                enum do 
+                    STATUS_ENUM
+                end
+            end
+            field :pay_way, :enum do 
+                enum do 
+                    PAY_WAY_ENUM
+                end
+            end
+            field :source, :enum do
+                enum do
+                    SOURCE_ENUM
+                end
+            end
+            field :paied_at do
+                formatted_value do
+                    (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+                end
+            end
+            field :tel 
+            field :address
+            field :contact
+            field :express_company
+            field :express_order_no
+            field :remark
+            field :order_remark
+            field :dispatch_time
+            field :receive_time
+            field :order_details
+            field :created_at
+            field :updated_at
+        end 
+        
+         edit do 
+            field :order_id
+            field :wx_user_id
+            field :total_price
+            field :paied_price
+            field :paied_at
+            field :buy_price
+            field :freight
+            field :trade_no
+            field :status, :enum do
+                enum do 
+                    STATUS_ENUM
+                end
+            end
+            field :pay_way, :enum do 
+                enum do 
+                    PAY_WAY_ENUM
+                end
+            end
+            field :source, :enum do
+                enum do
+                    SOURCE_ENUM
+                end
+            end
+            field :tel 
+            field :address
+            field :contact
+            field :express_company
+            field :express_order_no
+            field :remark
+            field :order_remark
+            field :dispatch_time
+         end
+
+        export do
+            include_all_fields
+            field :freight do
+                visible true
+                label "运费(元)"
+                formatted_value do
+                    value!=0 ? (value/100.0):0
+                end
+            end
+            field :status, :enum do
+                enum do
+                    STATUS_ENUM
+                end
+            end
+            field :pay_way, :enum do
+                enum do
+                    PAY_WAY_ENUM
+                end
+            end
+            field :source, :enum do
+                enum do
+                    SOURCE_ENUM
+                end
+            end
+            field :paied_at do
+                formatted_value do
+                    (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+                end
+            end
+        end
+
+    end 
+
+end
+
+

+ 114 - 0
app/models/order_detail.rb

@@ -0,0 +1,114 @@
+# encoding:utf-8
+class OrderDetail < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "order_details"
+  belongs_to :product, :foreign_key => :product_id
+  belongs_to :order, :foreign_key => :order_id
+
+  def order_state
+    order = Order.where("id = ?", self.order_id).first
+    if !order.blank?
+      return order.status
+    end
+  end
+
+  def paid_time
+    paidTime = 0
+    order = Order.where("id = ?", self.order_id).first
+    if !order.blank?
+      paidTime=order.paied_at
+    end
+    return paidTime
+  end
+
+  def pay_way
+    payWay = ""
+    order = Order.where("id = ?", self.order_id).first
+    if !order.blank?
+      payWay=order.pay_way
+    end
+    return payWay
+  end
+
+  STATUS_ENUM = [["未支付","unpay"],["已关闭","closed"],["待确认","unconfirmed"],["处理中","processing"],["已完成","complete"],["待收货","dispatch"],["已退款","refunded"]]
+  PAY_WAY_ENUM = [
+      # ["Web网银连连支付","webbankllpay"],
+      # ["Web认证连连支付","webauthllpay"],
+      # ["Wap认证连连支付","wapauthllpay"],
+      ["微信支付","weixinpay"],
+      ["代金券支付","balance"],
+      # ["公众号微信支付","gzhwxpay"],
+      # ["公众号代金券支付","gzhbalance"],
+      # ["统统微信支付","wx_sumpay"],
+      # ["统统Web网银支付","webbanksumpay"],
+  ]
+  rails_admin do
+    navigation_label '商品管理'
+    weight -240
+    parent Order
+    
+    list do   
+      filters [:product,:order_no,:nums,:price,:order_state]
+      field :id
+      field :order_no do
+        filterable true
+      end
+      field :product
+      field :nums
+      field :price do
+        visible true
+        label "单价(元)"
+        formatted_value do
+          value!=0 ? (value/100.0):0
+        end
+      end
+      field :product_name
+      field :order_state, :enum do
+        filterable true
+        enum do
+          STATUS_ENUM
+        end
+      end
+      field :paid_time do
+        formatted_value do
+          (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+        end
+      end
+      field :pay_way, :enum do
+        filterable true
+        enum do
+          PAY_WAY_ENUM
+        end
+      end
+      field :is_zeng
+      field :created_at
+      field :updated_at
+    end
+    show do   
+      field :id
+      field :order_no
+      field :product
+      field :nums
+      field :is_zeng
+      field :price do
+        visible true
+        label "单价(元)"
+        formatted_value do
+          value!=0 ? (value/100.0):0
+        end
+      end
+      field :product_name
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :order_no
+      field :product_id
+      field :nums
+      field :is_zeng
+      field :price
+      field :product_name
+    end
+  end
+end

+ 26 - 0
app/models/parent_signup_channel.rb

@@ -0,0 +1,26 @@
+# encoding:utf-8
+#注册渠道
+class ParentSignupChannel < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "parent_signup_channels"    
+
+  rails_admin do
+    navigation_label '用户管理'
+    weight -300
+
+    list do
+      filters [:id, :name]   
+      field :id
+      field :name
+      field :desc      
+      field :created_at    
+    end
+
+
+    edit do
+      field :name
+      field :desc 
+    end
+  end
+
+end

+ 118 - 0
app/models/poster_qrcode_record.rb

@@ -0,0 +1,118 @@
+# encoding:utf-8
+class PosterQrcodeRecord < ActiveRecord::Base
+  has_paper_trail  
+  self.table_name = "poster_qrcode_records"
+  belongs_to :wx_user , :foreign_key => :wx_uid
+  attr_accessor :v_qrcode_url
+  attr_accessor :relate_title
+
+  after_destroy :after_destroy
+
+  IMG_STORE_PATH = "poster_qrcode_record"
+
+  PTYPE_ENUM = [["商品","project"],["项目","poster"]]
+
+  def relate_title
+    return "-" if self.ptype != "project" && self.ptype != "poster"
+    if self.ptype == "project"
+      item = Product.where(" id = ?" , self.relate_id).first
+      return "-" if item.blank?
+      return item.name
+    elsif self.ptype == "poster"
+      item = Project.where(" id = ?" , self.relate_id).first
+      return "-" if item.blank?
+      return item.title
+    end
+  end
+
+  def v_qrcode_url=file
+    unless file.blank?
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.qrcode_url = file_path
+      self.save
+    end
+  end
+
+  def clear_qrcode_url
+    file_path = "#{self.qrcode_url}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_qrcode_url
+    url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.qrcode_url}"
+    return url
+  end
+
+  def after_destroy
+    clear_qrcode_url
+  end
+
+  rails_admin do
+    navigation_label '用户管理'
+    weight -220
+
+    list do
+      filters [:id, :wx_user]
+      field :id
+      field :wx_uid
+      field :wx_user    
+      field :parent_relate_id
+      field :relate_title
+      field :relate_id 
+      field :ptype, :enum do
+        enum do
+          PTYPE_ENUM
+        end
+      end
+      field :qrcode_url do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_qrcode_url,
+           :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+           :onClick => "javascript:window.open('#{bindings[:object].get_qrcode_url}')"})
+        end
+      end
+      field :scan_times
+      field :created_at
+    end
+
+    show do
+      field :id
+      field :wx_uid
+      field :wx_user    
+      field :parent_relate_id
+      field :relate_title
+      field :relate_id 
+      field :ptype, :enum do
+        enum do
+          PTYPE_ENUM
+        end
+      end
+      field :scan_times
+      field :qrcode_url do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].get_qrcode_url,
+           :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+           :onClick => "javascript:window.open('#{bindings[:object].get_qrcode_url}')"})
+        end
+      end
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :wx_uid
+      field :parent_relate_id
+      field :relate_id 
+      field :ptype
+      field :scan_times
+      field :v_qrcode_url, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_qrcode_url, :class => 'preview'})
+        end
+      end
+    end
+  end
+
+end

+ 50 - 0
app/models/poster_qrcode_scan_record.rb

@@ -0,0 +1,50 @@
+# encoding:utf-8
+class PosterQrcodeScanRecord < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "poster_qrcode_scan_records"
+  validates_presence_of :poster_qrcode_id, :wx_uid, :scan_times
+
+  belongs_to :wx_user, :foreign_key => :wx_uid
+  belongs_to :poster_qrcode_record, :foreign_key => :poster_qrcode_id
+
+  rails_admin do
+    navigation_label '用户管理'
+    weight -500
+    parent PosterQrcodeRecord
+
+    list do
+      filters [:id, :wx_user, :poster_qrcode_record]
+      field :id
+      field :poster_qrcode_id
+      field :poster_qrcode_record
+      field :wx_uid
+      field :wx_user
+      field :ip
+      field :scan_times
+      field :scan_last_time
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :poster_qrcode_id
+      field :poster_qrcode_record
+      field :wx_uid
+      field :wx_user
+      field :ip
+      field :scan_times
+      field :scan_last_time
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :poster_qrcode_id
+      field :wx_uid
+      field :ip
+      field :scan_times
+      field :scan_last_time
+    end
+  end
+end

+ 198 - 0
app/models/product.rb

@@ -0,0 +1,198 @@
+class Product < ActiveRecord::Base
+    has_paper_trail
+    self.table_name = 'products'
+    belongs_to :product_cat, :foreign_key => :category_id
+    belongs_to :merchant, :foreign_key => :merchant_id
+    validates :name,:buy_price,:price,:category_id,:count,:robo_balance_price, presence: true
+    attr_accessor :v_share_img
+
+    TYPE_ENUM = [["直营","direct_sale"]]
+    #["代销","user_sale"]
+
+    IMG_STORE_PATH = "product"
+
+    def v_share_img=file
+        unless file.blank?
+        file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+        file_path = "#{IMG_STORE_PATH}/product/share/#{file_name}"
+        Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+        self.share_img = file_path
+        self.save
+        end
+    end
+
+    def clean_share_img
+        file_path = "#{self.share_img}"
+        Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+    end
+
+    def get_share_img
+        url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.share_img}"
+        return url
+    end
+
+    def after_destroy
+        clean_share_img
+    end
+
+    def gross_interest_rate 
+        rate = 0
+        if self.buy_price != 0 && self.price != 0
+            rate = (( self.price.to_f - self.buy_price.to_f )/self.buy_price.to_f)*100
+        end 
+        return ((rate*100).round.to_f/100).to_s + "%"
+    end
+
+    rails_admin do 
+        navigation_label '商品管理'
+        weight -240
+
+        list do
+            filters [:id,:detail,:status,:name]
+            field :id
+            field :merchant_id
+            field :merchant
+            field :name do
+                filterable true
+            end
+            field :ptype, :enum do
+              enum do 
+                TYPE_ENUM
+              end
+            end 
+            #field :category_id
+            field :product_cat
+            field :detail
+            field :price do
+                label "现金价格(元)"
+                formatted_value do # used in form views
+                    value.to_f / 100
+                end
+            end
+            field :robo_balance_price
+            field :user_sale_price
+            field :buy_price
+            field :gross_interest_rate
+            field :count
+            field :recommend
+            field :status
+            #field :is_support_poor
+            field :virtual_sold_count
+            field :purchase_limit_count
+            field :share_img do 
+              visible false
+                formatted_value do
+                bindings[:view].tag(:img,{:src => bindings[:object].get_share_img,
+                    :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                    :onClick => "javascript:window.open('#{bindings[:object].get_share_img}')"})
+                end
+            end
+            field :seckill_price do
+                label "秒杀显示原价(元)"
+                formatted_value do # used in form views
+                    value.to_f / 100
+                end
+            end
+            field :is_only_new
+            field :video_state
+            field :created_at
+            field :updated_at
+        end
+
+        show do
+            field :id
+            field :merchant_id
+            field :merchant
+            field :name
+            field :ptype, :enum do
+              enum do 
+                TYPE_ENUM
+              end
+            end
+            #field :category_id
+            field :product_cat
+            field :detail
+            field :price do
+                label "现金价格(元)"
+                formatted_value do # used in form views
+                    value.to_f / 100
+                end
+            end
+            field :robo_balance_price
+            field :buy_price
+            field :user_sale_price
+            field :count
+            field :recommend
+            field :status
+            #field :is_support_poor
+            field :virtual_sold_count
+            field :purchase_limit_count
+            field :share_content
+            # field :share_img do 
+            #     formatted_value do
+            #     bindings[:view].tag(:img,{:src => bindings[:object].get_share_img,
+            #         :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+            #         :onClick => "javascript:window.open('#{bindings[:object].get_share_img}')"})
+            #     end
+            # end
+            field :seckill_start
+            field :seckill_end
+            field :seckill_price do
+                label "秒杀显示原价(元)"
+                formatted_value do # used in form views
+                    value.to_f / 100
+                end
+            end
+            field :deliver_stop_at
+            field :deliver_start_at
+            field :is_only_new
+            field :specification
+            field :no_delivery_area
+            field :video_state
+            field :video_url
+            field :created_at
+            field :updated_at
+        end
+
+        edit do 
+            field :name
+            field :ptype, :enum do
+              enum do 
+                TYPE_ENUM
+              end
+            end
+            #field :category_id
+            field :merchant_id
+            field :product_cat
+            field :detail, :ck_editor
+            field :price
+            field :robo_balance_price
+            field :buy_price
+            field :user_sale_price
+            field :count
+            field :recommend
+            field :status
+            #field :is_support_poor
+            field :virtual_sold_count
+            field :purchase_limit_count
+            field :share_content
+            # field :v_share_img, :file_upload do
+            #     pretty_value do
+            #         bindings[:view].tag(:img, {:src => bindings[:object].get_share_img, :class => 'preview'})
+            #     end
+            # end
+            field :seckill_start
+            field :seckill_end
+            field :seckill_price
+            field :deliver_stop_at
+            field :deliver_start_at
+            field :is_only_new
+            field :specification
+            field :no_delivery_area
+            field :video_state
+            field :video_url
+        end
+
+    end
+
+end

+ 46 - 0
app/models/product_cat.rb

@@ -0,0 +1,46 @@
+class ProductCat < ActiveRecord::Base
+    has_paper_trail
+    self.table_name = 'product_cats'
+    has_ancestry
+    has_many :products, :foreign_key => :category_id
+    validates :name,presence:true
+    
+    rails_admin do
+        navigation_label '商品管理'
+        weight -240
+        nestable_tree({
+            position_field: :position,
+            max_depth: 2
+        })
+
+        list do 
+            filters [:name,:ancestry,:position]
+            field :id
+            field :name 
+            field :position 
+            field :ancestry
+            field :status
+            field :cow_state
+            field :products
+        end
+
+        show do
+            field :id
+            field :name 
+            field :position 
+            field :ancestry
+            field :status
+            field :cow_state
+            field :products
+        end
+
+        edit do 
+            field :name 
+            field :status
+            field :cow_state
+            field :products
+        end 
+
+    end
+
+end

+ 101 - 0
app/models/product_picture.rb

@@ -0,0 +1,101 @@
+require 'uuid'
+class ProductPicture < ActiveRecord::Base
+    has_paper_trail
+    self.table_name = "product_pictures"
+    after_destroy :after_destroy
+    belongs_to :product
+    validates :product_id, presence: true
+    attr_accessor :v_img
+
+    IMG_STORE_PATH = "product_pictures" 
+
+    PIC_TYPE_ENUM = [["视频封面图",2],["详情图",1],["轮播图",0]]
+
+    rails_admin do
+        navigation_label '商品管理'
+        weight -240
+
+        list do
+            filters [:id,:pic_type]
+            field :id
+            field :product
+            field :img do
+                formatted_value do
+                    bindings[:view].tag(:img,{:src => bindings[:object].get_img,
+                        :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                        :onClick => "javascript:window.open('#{bindings[:object].get_img}')"})
+                end
+            end
+            field :pic_type,:enum do
+                enum do
+                    PIC_TYPE_ENUM
+                end
+            end
+            field :sort
+            field :created_at
+            field :updated_at
+        end
+
+        show do
+            field :id
+            field :product
+            field :img do
+                formatted_value do
+                    bindings[:view].tag(:img,{:src => bindings[:object].get_img,
+                    :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                    :onClick => "javascript:window.open('#{bindings[:object].get_img}')"})
+                end
+            end
+            field :pic_type, :enum do
+                enum do
+                    PIC_TYPE_ENUM
+                end
+            end
+            field :sort
+            field :created_at
+            field :updated_at
+        end
+
+        edit do
+            field :product
+            field :v_img, :file_upload do
+                pretty_value do
+                    bindings[:view].tag(:img,{:src => bindings[:object].get_img, :class => 'preview'})
+                end
+            end
+            field :pic_type,:enum do
+                enum do
+                    PIC_TYPE_ENUM
+                end
+            end
+            field :sort
+        end
+
+    end
+
+    def v_img=file
+        unless file.blank?
+            # clear_img
+            file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+            file_path = "#{IMG_STORE_PATH}/#{file_name}"
+            Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+            self.img = file_path
+            self.save
+        end
+    end
+
+
+    def clear_img
+        file_path = "#{self.img}"
+        Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ,file_path)
+    end
+
+    def get_img
+        url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.img}"
+        return url
+    end
+
+    def after_destroy
+        clear_img
+    end
+end

+ 74 - 0
app/models/push_after_sub.rb

@@ -0,0 +1,74 @@
+# encoding:utf-8
+class PushAfterSub< ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "push_after_subs"
+  validates_presence_of :push_type, :remark
+  PUSH_TYPE_ENUM = [["图片","image"],["文字","text"],["图文","article"]]
+
+  IMG_STORE_PATH = "push_after_sub"
+
+  rails_admin do
+    navigation_label '推送管理'
+    # parent ChannelQrcode
+    weight -220
+
+    list do
+      filters [:id, :push_title]
+      field :id
+      field :push_title
+      field :push_type, :enum do
+        enum do
+          PUSH_TYPE_ENUM
+        end
+      end
+      field :cover do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].cover,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].cover}')"})
+        end
+      end
+      field :word
+      field :url
+      field :remark
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :push_title
+      field :push_type, :enum do
+        enum do
+          PUSH_TYPE_ENUM
+        end
+      end
+      field :cover do
+        formatted_value do
+            bindings[:view].tag(:img, {:src => bindings[:object].cover,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].cover}')"})
+        end
+      end
+      field :word
+      field :url
+      field :remark
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :push_title
+      field :push_type, :enum do
+        enum do
+          PUSH_TYPE_ENUM
+        end
+      end
+      field :cover
+      field :word
+      field :url
+      field :remark
+    end
+  end
+
+end

+ 139 - 0
app/models/push_tmpl.rb

@@ -0,0 +1,139 @@
+# encoding:utf-8
+class PushTmpl < ActiveRecord::Base
+  has_paper_trail
+  belongs_to :wx_gongzhonghao
+  self.table_name = "push_tmpls"
+  MSG_TYPE_ENUM = [
+    ["订单待支付提醒","0"],
+    ["新项目提醒", "1"],
+    ["提货通知","2"],
+    ["订购成功通知","3"],
+    ["一元购退款通知","4"]
+  ]
+  def get_push_count
+    if self.push_count.to_i >0
+      return self.push_count 
+    end
+    if !self.user_id.blank?
+      if self.user_id.start_with?("sql=select * ")
+        sql = self.user_id.gsub("sql=select * ","select count(*) as sqlcount ")
+        item = WxUser.find_by_sql(sql)
+        if !item.blank?
+          c = item[0].sqlcount
+          if self.push_count == 0 
+            self.push_count  = c
+            self.save
+          end
+          return c
+        end
+      end
+    end
+  end
+
+  def get_click_count
+    if self.click_count.to_i >0
+      return self.click_count 
+    end
+    if self.url.blank?
+      return 
+    end
+    if self.url.start_with?("#{CONFIG_FILE["api_host"]}/v1/cfc/")
+      size = "#{CONFIG_FILE["api_host"]}/v1/cfc/".size
+      id = self.url[size..-1].to_i
+      if id>0 
+        item = ClickFromChannel.where("id=?",id).first
+        if !item.blank?
+          if item.click_times !=self.click_count 
+            self.click_count  = item.click_times
+            self.save
+          end
+          return item.click_times
+        end
+      end
+    end
+  end
+
+  rails_admin do
+    navigation_label '推送管理'
+    weight -220
+
+    list do
+      items_per_page 10
+      filters [:id, :user_id, :first]
+      field :id
+      field :user_id
+      field :get_push_count
+      field :push_count
+      field :msg_type, :enum do
+        enum do
+          MSG_TYPE_ENUM
+        end
+      end
+      field :push_force
+      field :first
+      field :keyword1
+      field :keyword2
+      field :keyword3
+      field :keyword4
+      field :keyword5
+      field :url
+      field :last_updated_at
+      field :times
+      field :get_click_count
+      field :click_count
+      field :remark
+      field :wx_gongzhonghao
+      field :created_at
+    end
+
+    show do
+      field :id
+      field :user_id
+      field :msg_type, :enum do
+        enum do
+          MSG_TYPE_ENUM
+        end
+      end
+      field :push_force
+      field :first
+      field :keyword1
+      field :keyword2
+      field :keyword3
+      field :keyword4
+      field :keyword5
+      field :url
+      field :last_updated_at
+      field :times
+      field :remark
+      field :wx_gongzhonghao
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :user_id do
+        label "微信用户ID(注意:拉比兔公众号的openid记录在wx_user_gongzhonghaos表中的gzh_open_id)"
+      end
+      field :msg_type, :enum do
+        enum do
+          MSG_TYPE_ENUM
+        end
+      end
+      field :push_force
+      field :push_count
+      field :click_count
+      field :first
+      field :keyword1
+      field :keyword2
+      field :keyword3
+      field :keyword4
+      field :keyword5
+      field :url
+      field :last_updated_at
+      field :times
+      field :remark
+      field :wx_gongzhonghao
+    end
+  end
+
+end

+ 33 - 0
app/models/push_tmpl_record.rb

@@ -0,0 +1,33 @@
+# encoding:utf-8
+class PushTmplRecord < ActiveRecord::Base
+  has_paper_trail  
+  self.table_name = "push_tmpl_records"
+  belongs_to :wx_user , :foreign_key => :wx_uid
+  rails_admin do
+    navigation_label '推送管理'
+    weight -220
+
+    list do
+      filters [:id, :wx_user, :temp_id, :push_time]
+      field :id
+      field :wx_user    
+      field :temp_id
+      field :push_time
+    end
+
+    show do
+      field :id
+      field :wx_uid    
+      field :temp_id
+      field :push_time
+    end
+
+    edit do
+      field :id
+      field :wx_uid    
+      field :temp_id
+      field :push_time
+    end
+  end
+
+end

+ 96 - 0
app/models/recharge_cash_order.rb

@@ -0,0 +1,96 @@
+# encoding:utf-8
+class RechargeCashOrder < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "recharge_cash_orders"
+  belongs_to :user
+  belongs_to :wx_user
+  validates :order_id,:user_id,:total_price,presence: true
+
+  PAY_WAY_ENUM = [
+    ["微信支付","recharge_wxpay"],
+  ]
+
+  rails_admin do
+    navigation_label '资金管理'
+    parent CashBalance
+    weight -920
+
+    list do
+      filters [:user,:wx_user,:order_id,:state]
+      field :id
+      field :order_id
+      field :user
+      field :wx_user
+      field :pay_way ,:enum do
+        enum do
+          PAY_WAY_ENUM
+        end
+      end
+      field :trade_no
+      field :paied_at do
+        formatted_value do
+          (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+        end
+      end
+      field :total_price do
+        label "总额(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :state
+      field :remark
+      field :balance_bank_card_no
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :order_id
+      field :user
+      field :wx_user
+      field :pay_way ,:enum do
+        enum do
+          PAY_WAY_ENUM
+        end
+      end
+      field :trade_no
+      field :paied_at do
+        formatted_value do
+          (value == 0 || value == nil) ? Time.at(0) : Time.at(value)
+        end
+      end
+      field :total_price do
+        label "总额(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :state
+      field :balance_bank_card_no
+      field :remark
+      field :created_at
+    end
+
+    edit do
+      field :order_id
+      field :user_id
+      field :wx_user_id
+      field :pay_way ,:enum do
+        enum do
+          PAY_WAY_ENUM
+        end
+      end
+      field :trade_no
+      field :paied_at do
+        label "支付时间单位(秒)"
+      end
+      field :total_price do
+        label "总额(分)"
+      end
+      field :state
+      field :remark
+      field :balance_bank_card_no
+    end
+  end
+end

+ 37 - 0
app/models/session.rb

@@ -0,0 +1,37 @@
+# encoding:utf-8
+class Session < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = 'session'
+  self.primary_key = "session_key"
+  validates_presence_of :session_key
+
+  rails_admin do
+    navigation_label '系统会话管理'
+    weight -35
+
+    list do
+      filters [:session_key]
+      # include_all_fields
+      field :session_key      
+      field :session_expiry do
+        formatted_value do
+          Time.at(value)
+        end
+      end
+    end
+    show do
+      # include_all_fields
+      field :session_key      
+      field :session_expiry do
+        formatted_value do
+          Time.at(value)
+        end
+      end
+    end
+
+    edit do
+
+    end
+  end
+
+end

+ 118 - 0
app/models/share_info.rb

@@ -0,0 +1,118 @@
+# encoding:utf-8
+class ShareInfo < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "share_infos"
+  validates_presence_of :share_code, :relate_id, :relate_parent, :wx_user, :share_to, :ip
+  belongs_to :wx_user, :foreign_key => :wx_user_id
+  attr_accessor :relate_title
+
+  def relate_title
+    return "-" if self.share_code != "article" && self.share_code != "product_sale" && self.share_code != "xcx_product" && share_code != "xcx_project"
+
+    if self.share_code == "article"
+      item = Article.where(" id = ?" , self.relate_id).first
+      return "-" if item.blank?
+      return item.title
+    elsif self.share_code == "product_sale"
+      item = ProductSaleSubject.where(" id = ?" , self.relate_id).first
+      return "-" if item.blank?
+      return item.subject_title
+    elsif self.share_code == "xcx_product"
+      item = Product.where(" id = ?" , self.relate_id).first
+      return "-" if item.blank?
+      return item.name
+    elsif self.share_code == "xcx_project"
+      item = Project.where(" id = ?" , self.relate_id).first
+      return "-" if item.blank?
+      return item.title
+    end
+  end
+
+  SHARE_CODE_ENUM = [
+    ["文章分享","article"],
+    ["商品销售专题","product_sale"],
+    ["小程序首页","xcx_home"],
+    ["我的推广页面","xcx_invite"],
+    ["我的推广正确转发页面","xcx_invite_detail"],
+    ["小程序商品","xcx_product"],
+    ["小程序项目","xcx_project"],
+    ["小程序排行榜","xcx_rank"]
+  ]
+  SHARE_TO_ENUM = [
+    ["朋友圈","timeline"],
+    ["群","group"],
+  ]
+  
+  rails_admin do
+    navigation_label '分享管理'
+    weight -750
+
+    list do
+      filters [:id, :wx_user, :relate_id, :ip]
+      field :id
+      # field :wx_user_id
+      field :wx_user
+      field :relate_title
+      field :relate_id
+      field :relate_parent
+      field :share_code, :enum do
+        enum do
+          SHARE_CODE_ENUM
+        end
+      end
+      field :share_to, :enum do
+        enum do
+          SHARE_TO_ENUM
+        end
+      end
+      field :ip
+      field :share_times
+      field :share_latest_time
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :wx_user
+      field :relate_id
+      field :relate_title
+      field :relate_parent
+      field :share_code, :enum do
+        enum do
+          SHARE_CODE_ENUM
+        end
+      end
+      field :share_to, :enum do
+        enum do
+          SHARE_TO_ENUM
+        end
+      end
+      field :ip
+      field :share_times
+      field :share_latest_time
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :wx_user
+      field :relate_id
+      field :relate_parent
+      field :share_code, :enum do
+        enum do
+          SHARE_CODE_ENUM
+        end
+      end
+      field :share_to, :enum do
+        enum do
+          SHARE_TO_ENUM
+        end
+      end
+      field :ip
+      field :share_times
+      field :share_latest_time
+    end
+  end
+
+end

+ 646 - 0
app/models/share_material.rb

@@ -0,0 +1,646 @@
+# encoding:utf-8
+require 'uuid'
+class ShareMaterial < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "share_materials"
+  before_save :before_save
+  
+  belongs_to :wx_user, :foreign_key => :wx_uid
+  validates :type_id,presence: true
+  attr_accessor :v_image_1, :v_image_2, :v_image_3, :v_image_4, :v_image_5, :v_image_6, :v_image_7, :v_image_8, :v_image_9
+  attr_accessor :is_delete_image_1, :is_delete_image_2, :is_delete_image_3, :is_delete_image_4, :is_delete_image_5, :is_delete_image_6, :is_delete_image_7, :is_delete_image_8, :is_delete_image_9
+  attr_accessor :image_ratio_1, :image_ratio_2, :image_ratio_3, :image_ratio_4, :image_ratio_5, :image_ratio_6, :image_ratio_7, :image_ratio_8, :image_ratio_9
+
+  MTYPE_ENUM = [["商品","product"],["项目","project"]]
+  def type_title 
+    if m_type == "project"
+      project = Project.where("id = ?", self.type_id).first
+      if !project.blank?
+        return project.title
+      end
+    elsif m_type == "product"
+      product = Product.where("id = ?", self.type_id).first
+      if !product.blank?
+        return product.name
+      end
+    end 
+    return "-"
+  end
+   
+  IMG_STORE_PATH = "share_materials" 
+
+  rails_admin do
+    navigation_label '发圈素材管理'
+    weight -240
+
+    list do
+      filters [:id]
+      field :id
+      field :wx_user
+      field :m_type, :enum do
+          enum do 
+              MTYPE_ENUM
+          end
+      end
+      field :type_title
+      field :type_id
+      field :image_1st do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(1),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(1)}')"
+              }
+            )
+        end
+      end
+      field :image_2nd do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(2),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(2)}')"
+              }
+            )
+        end
+      end
+      field :is_published
+      field :created_at
+    end
+
+    show do
+      field :id
+      field :wx_user
+      field :m_type, :enum do
+          enum do 
+              MTYPE_ENUM
+          end
+      end
+      field :type_title
+      field :type_id
+      field :material_text
+      field :image_1st do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(1),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(1)}')"
+              }
+            )
+        end
+      end
+      field :image_2nd do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(2),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(2)}')"
+              }
+            )
+        end
+      end
+      field :image_3rd do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(3),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(3)}')"
+              }
+            )
+        end
+      end
+      field :image_4th do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(4),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(4)}')"
+              }
+            )
+        end
+      end
+      field :image_5th do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(5),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(5)}')"
+              }
+            )
+        end
+      end
+      field :image_6th do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(6),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(6)}')"
+              }
+            )
+        end
+      end
+      field :image_7th do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(7),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(7)}')"
+              }
+            )
+        end
+      end
+      field :image_8th do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(8),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(8)}')"
+              }
+            )
+        end
+      end
+      field :image_9th do
+        formatted_value do
+          bindings[:view].tag(
+              :img, 
+              {
+                  :src => bindings[:object].get_img(9),
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img(9)}')"
+              }
+            )
+        end
+      end
+      field :is_published
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :wx_uid
+      field :m_type, :enum do
+          enum do 
+              MTYPE_ENUM
+          end
+      end
+      field :type_id
+      field :material_text
+      field :v_image_1, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(1), :class => 'preview'})
+        end
+      end
+      field :image_ratio_1, :integer
+      field :is_delete_image_1, :boolean do
+        visible do
+          bindings[:object].image_1st != "" && bindings[:object].image_1st != nil
+        end
+      end
+      field :v_image_2, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(2), :class => 'preview'})
+        end
+      end
+      field :image_ratio_2, :integer
+      field :is_delete_image_2, :boolean do
+        visible do
+          bindings[:object].image_2nd != "" && bindings[:object].image_2nd != nil
+        end
+      end
+      field :v_image_3, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(3), :class => 'preview'})
+        end
+      end
+      field :image_ratio_3, :integer
+      field :is_delete_image_3, :boolean do
+        visible do
+          bindings[:object].image_3rd != "" && bindings[:object].image_3rd != nil
+        end
+      end
+      field :v_image_4, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(4), :class => 'preview'})
+        end
+      end
+      field :image_ratio_4, :integer
+      field :is_delete_image_4, :boolean do
+        visible do
+          bindings[:object].image_4th != "" && bindings[:object].image_4th != nil
+        end
+      end
+      field :v_image_5, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(5), :class => 'preview'})
+        end
+      end
+      field :image_ratio_5, :integer
+      field :is_delete_image_5, :boolean do
+        visible do
+          bindings[:object].image_5th != "" && bindings[:object].image_5th != nil
+        end
+      end
+      field :v_image_6, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(6), :class => 'preview'})
+        end
+      end
+      field :image_ratio_6, :integer
+      field :is_delete_image_6, :boolean do
+        visible do
+          bindings[:object].image_6th != "" && bindings[:object].image_6th != nil
+        end
+      end
+      field :v_image_7, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(7), :class => 'preview'})
+        end
+      end
+      field :image_ratio_7, :integer
+      field :is_delete_image_7, :boolean do
+        visible do
+          bindings[:object].image_7th != "" && bindings[:object].image_7th != nil
+        end
+      end
+      field :v_image_8, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(8), :class => 'preview'})
+        end
+      end
+      field :image_ratio_8, :integer
+      field :is_delete_image_8, :boolean do
+        visible do
+          bindings[:object].image_8th != "" && bindings[:object].image_8th != nil
+        end
+      end
+      field :v_image_9, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_img(9), :class => 'preview'})
+        end
+      end
+      field :image_ratio_9, :integer
+      field :is_delete_image_9, :boolean do
+        visible do
+          bindings[:object].image_9th != "" && bindings[:object].image_9th != nil
+        end
+      end
+      field :is_published
+    end
+  end
+
+
+  
+  after_destroy :after_destroy
+
+  def v_image_1=file
+    upload(file, 1)
+  end
+  def v_image_2=file
+    upload(file, 2)
+  end
+  def v_image_3=file
+    upload(file, 3)
+  end
+  def v_image_4=file
+    upload(file, 4)
+  end
+  def v_image_5=file
+    upload(file, 5)
+  end
+  def v_image_6=file
+    upload(file, 6)
+  end
+  def v_image_7=file
+    upload(file, 7)
+  end
+  def v_image_8=file
+    upload(file, 8)
+  end
+  def v_image_9=file
+    upload(file, 9)
+  end
+
+  # ?x-oss-process=image/quality,q_70 控制图片质量,CDN转换也可以用
+  def upload(file, img_idx)
+    unless file.blank?
+      clear_img(img_idx)
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss::store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      case img_idx
+      when 1
+        self.image_1st = file_path
+      when 2
+        self.image_2nd = file_path
+      when 3
+        self.image_3rd = file_path
+      when 4
+        self.image_4th = file_path
+      when 5
+        self.image_5th = file_path
+      when 6
+        self.image_6th = file_path
+      when 7
+        self.image_7th = file_path
+      when 8
+        self.image_8th = file_path
+      when 9
+        self.image_9th = file_path
+      end
+    end
+  end
+
+  def getImageFilePath(img_idx) 
+    case img_idx
+    when 1
+      if self.image_1st != nil && self.image_1st != ""
+        if self.image_ratio_1 != nil && self.image_ratio_1 !="" 
+          if self.image_1st.include?"?x-oss-process=image/quality,q_"
+            self.image_1st = self.image_1st[0, self.image_1st.rindex("_")+1] + self.image_ratio_1
+          else
+            self.image_1st = self.image_1st + "?x-oss-process=image/quality,q_" + self.image_ratio_1
+          end
+        else
+          if !self.image_1st.include?"?x-oss-process=image/quality,q_"
+            self.image_1st = self.image_1st + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 2
+      if self.image_2nd != nil && self.image_2nd != ""
+        if self.image_ratio_2 != nil && self.image_ratio_2 != "" 
+          if self.image_2nd.include?"?x-oss-process=image/quality,q_"
+            self.image_2nd = self.image_2nd[0, self.image_2nd.rindex("_")+1] + self.image_ratio_2
+          else
+            self.image_2nd = self.image_2nd + "?x-oss-process=image/quality,q_" + self.image_ratio_2
+          end
+        else
+          if !self.image_2nd.include?"?x-oss-process=image/quality,q_"
+            self.image_2nd = self.image_2nd + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 3
+      if self.image_3rd != nil && self.image_3rd != ""
+        if self.image_ratio_3 != nil && self.image_ratio_3 != "" 
+          if self.image_3rd.include?"?x-oss-process=image/quality,q_"
+            self.image_3rd = self.image_3rd[0, self.image_3rd.rindex("_")+1] + self.image_ratio_3
+          else
+          self.image_3rd = self.image_3rd + "?x-oss-process=image/quality,q_" + self.image_ratio_3
+          end
+        else
+          if !self.image_3rd.include?"?x-oss-process=image/quality,q_"
+            self.image_3rd = self.image_3rd + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 4
+      if self.image_4th != nil && self.image_4th != ""
+        if self.image_ratio_4 != nil && self.image_ratio_4 != "" 
+          if self.image_4th.include?"?x-oss-process=image/quality,q_"
+            self.image_4th = self.image_4th[0, self.image_4th.rindex("_")+1] + self.image_ratio_4
+          else
+          self.image_4th = self.image_4th + "?x-oss-process=image/quality,q_" + self.image_ratio_4
+          end
+        else
+          if !self.image_4th.include?"?x-oss-process=image/quality,q_"
+            self.image_4th = self.image_4th + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 5
+      if self.image_5th != nil && self.image_5th != ""
+        if self.image_ratio_5 != nil && self.image_ratio_5 != "" 
+          if self.image_5th.include?"?x-oss-process=image/quality,q_"
+            self.image_5th = self.image_5th[0, self.image_5th.rindex("_")+1] + self.image_ratio_5
+          else
+          self.image_5th = self.image_5th + "?x-oss-process=image/quality,q_" + self.image_ratio_5
+          end
+        else
+          if !self.image_5th.include?"?x-oss-process=image/quality,q_"
+            self.image_5th = self.image_5th + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 6
+      if self.image_6th != nil && self.image_6th != ""
+        if self.image_ratio_6 != nil && self.image_ratio_6 != "" 
+          if self.image_6th.include?"?x-oss-process=image/quality,q_"
+            self.image_6th = self.image_6th[0, self.image_6th.rindex("_")+1] + self.image_ratio_6
+          else
+          self.image_6th = self.image_6th + "?x-oss-process=image/quality,q_" + self.image_ratio_6
+          end
+        else
+          if !self.image_6th.include?"?x-oss-process=image/quality,q_"
+            self.image_6th = self.image_6th + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 7
+      if self.image_7th != nil && self.image_7th != ""
+        if self.image_ratio_7 != nil && self.image_ratio_7 != ""
+          if self.image_7th.include?"?x-oss-process=image/quality,q_"
+            self.image_7th = self.image_7th[0, self.image_7th.rindex("_")+1] + self.image_ratio_7
+          else
+          self.image_7th = self.image_7th + "?x-oss-process=image/quality,q_" + self.image_ratio_7
+          end
+        else
+          if !self.image_7th.include?"?x-oss-process=image/quality,q_"
+            self.image_7th = self.image_7th + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 8
+      if self.image_8th != nil && self.image_8th != ""
+        if self.image_ratio_8 != nil && self.image_ratio_8 != ""
+          if self.image_8th.include?"?x-oss-process=image/quality,q_"
+            self.image_8th = self.image_8th[0, self.image_8th.rindex("_")+1] + self.image_ratio_8
+          else
+          self.image_8th = self.image_8th + "?x-oss-process=image/quality,q_" + self.image_ratio_8
+          end
+        else
+          if !self.image_8th.include?"?x-oss-process=image/quality,q_"
+            self.image_8th = self.image_8th + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    when 9
+      if self.image_9th != nil && self.image_9th != ""
+        if self.image_ratio_9 != nil && self.image_ratio_9 != ""
+          if self.image_9th.include?"?x-oss-process=image/quality,q_"
+            self.image_9th = self.image_9th[0, self.image_9th.rindex("_")+1] + self.image_ratio_9
+          else
+          self.image_9th = self.image_9th + "?x-oss-process=image/quality,q_" + self.image_ratio_9
+          end
+        else
+          if !self.image_9th.include?"?x-oss-process=image/quality,q_"
+            self.image_9th = self.image_9th + "?x-oss-process=image/quality,q_100"
+          end
+        end
+      end
+    end
+  end
+
+  def get_img(img_idx)
+    store_name = ""
+    case img_idx
+    when 1
+      store_name = self.image_1st
+    when 2
+      store_name = self.image_2nd
+    when 3
+      store_name = self.image_3rd
+    when 4
+      store_name = self.image_4th
+    when 5
+      store_name = self.image_5th
+    when 6
+      store_name = self.image_6th
+    when 7
+      store_name = self.image_7th
+    when 8
+      store_name = self.image_8th
+    when 9
+      store_name = self.image_9th     
+    end
+    if store_name != "" && store_name != nil 
+      url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{store_name}"
+      return url
+    end
+    return ""
+  end
+
+  def clear_img(img_idx)
+    file_path = ""
+    case img_idx
+    when 1
+      file_path = "#{self.image_1st}"
+    when 2
+      file_path = "#{self.image_2nd}"
+    when 3
+      file_path = "#{self.image_3rd}"
+    when 4
+      file_path = "#{self.image_4th}"
+    when 5
+      file_path = "#{self.image_5th}"
+    when 6
+      file_path = "#{self.image_6th}"
+    when 7
+      file_path = "#{self.image_7th}"
+    when 8
+      file_path = "#{self.image_8th}"
+    when 9
+      file_path = "#{self.image_9th}"
+    end
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def after_destroy
+    for i in 1..9
+      clear_img(i)
+    end
+  end
+
+  def is_delete_img(img_idx, is_delete)
+    case img_idx
+    when 1
+      if is_delete == 1
+        clear_img(1)
+        self.image_1st = ""
+      end
+    when 2
+      if is_delete == 1
+        clear_img(2)
+        self.image_2nd = ""
+      end
+    when 3
+      if is_delete == 1
+        clear_img(3)
+        self.image_3rd = ""
+      end
+    when 4
+      if is_delete == 1
+        clear_img(4)
+        self.image_4th = ""
+      end
+    when 5
+      if is_delete == 1
+        clear_img(5)
+        self.image_5th = ""
+      end
+    when 6
+      if is_delete == 1
+        clear_img(6)
+        self.image_6th = ""
+      end
+    when 7
+      if is_delete == 1
+        clear_img(7)
+        self.image_7th = ""
+      end
+    when 8  
+      if is_delete == 1
+        clear_img(8)
+        self.image_8th = ""
+      end
+    when 9 
+      if is_delete == 1
+        clear_img(9)
+        self.image_9th = ""
+      end
+    end
+  end
+
+  def get_is_delete(img_idx)
+    case img_idx
+    when 1
+      return self.is_delete_image_1.to_i
+    when 2
+      return self.is_delete_image_2.to_i
+    when 3
+      return self.is_delete_image_3.to_i
+    when 4
+      return self.is_delete_image_4.to_i
+    when 5
+      return self.is_delete_image_5.to_i
+    when 6
+      return self.is_delete_image_6.to_i
+    when 7
+      return self.is_delete_image_7.to_i
+    when 8
+      return self.is_delete_image_8.to_i
+    when 9
+      return self.is_delete_image_9.to_i
+    end
+  end
+
+  def before_save
+    for i in 1..9
+      is_delete_img(i, get_is_delete(i))
+    end
+    for i in 1..9
+      getImageFilePath(i)
+    end
+  end
+
+end

+ 61 - 0
app/models/sign_up_channel.rb

@@ -0,0 +1,61 @@
+# encoding:utf-8
+#小程序码
+class SignUpChannel < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "sign_up_channels"
+  belongs_to :parent_signup_channel, :foreign_key => :parent_id
+
+  rails_admin do
+    navigation_label '用户管理'
+    weight -300
+
+    list do
+      filters [:id, :channel_value, :invite_id]   
+      field :id
+      field :parent_signup_channel
+      field :qrcode_path
+      field :channel_value
+      field :channel_url
+      field :img do
+          formatted_value do
+              bindings[:view].tag(:img,{:src => bindings[:object].get_img,
+                  :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+                  :onClick => "javascript:window.open('#{bindings[:object].get_img}')"})
+          end
+      end      
+      field :invite_id
+      field :qrcode_img_url
+      field :scan_times
+      field :created_at    
+    end
+
+
+    edit do
+      field :parent_id
+      field :channel_value
+      field :channel_url
+      field :invite_id
+    end
+  end
+
+  def qrcode_path
+    # url = "#{CONFIG_FILE["api_host"]}/v1/xcx/qrcode/generate"
+      path =  "pages/start/start?scene=#{self.id}"
+    return path
+  end
+
+  def qrcode_img_url
+    # url = "#{CONFIG_FILE["api_host"]}/v1/xcx/qrcode/generate"
+      url =  "#{CONFIG_FILE["api_host"]}/v1/xcx/qrcode/channel/#{self.id}"
+    if self.url_image.blank?
+      open(url)
+    end
+    return url
+  end
+
+  def get_img
+      url = "#{self.url_image}"
+      return url
+  end
+
+end

+ 57 - 0
app/models/sign_up_channel_qrcode_result.rb

@@ -0,0 +1,57 @@
+# encoding:utf-8
+class SignUpChannelQrcodeResult < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "sign_up_channel_qrcode_results"
+  #小程序码
+  belongs_to :sign_up_channel, :foreign_key => :sign_up_channel_id
+  #扫码微信用户
+  belongs_to :wx_user, :foreign_key => :wx_uid
+  validates_presence_of :wx_uid,:sign_up_channel_id
+
+  def wx_user_nickname
+    return "-" if self.blank?
+    wx_user = WxUser.where("id = ?", self.wx_uid).first
+    return "-" if wx_user.blank?
+    return wx_user.nickname
+  end
+
+  def user_tel
+    return "-" if self.blank?
+    wx_user = WxUser.where("id = ?", self.wx_uid).first
+    return "-" if wx_user.blank?
+    user = User.where("id = ?", wx_user.user_id).first
+    return "-" if user.blank?
+    return user.tel
+  end
+
+  rails_admin do
+    navigation_label '用户管理'
+    parent SignUpChannel
+    weight -500
+
+    list do
+      filters [:sign_up_channel, :id]
+      field :id
+      field :wx_uid
+      field :wx_user
+      field :sign_up_channel_id
+      field :sign_up_channel
+      field :user_tel
+      field :wx_user_nickname
+      field :created_at
+    end
+    show do
+      field :id
+      field :wx_uid
+      field :sign_up_channel_id
+      field :user_tel
+      field :wx_user_nickname
+      field :created_at
+    end
+
+    edit do
+      field :wx_uid
+      field :sign_up_channel_id
+    end
+  end
+end

+ 168 - 0
app/models/take_cash_order.rb

@@ -0,0 +1,168 @@
+# encoding:utf-8
+class TakeCashOrder < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "take_cash_orders"
+  before_destroy :before_destroy_update
+
+  belongs_to :wx_user, :foreign_key => :wx_uid
+  
+  STATE_ENUM = [["未审核", 0],["审核同意", 1], ["审核拒绝", 2]]
+  REAL_ENUM = [["强制检验", 0],["取消检验", 1]]
+  PAY_STATE_ENUM = [["未支付", 0],["已支付", 1],["提现失败", 2]]
+
+  validates :wx_uid,:order_id,:count,presence: true
+
+  def before_destroy_update
+    tcOrder = TakeCashOrder.where("id=?",self.id).first
+    if !tcOrder.nil? && tcOrder.audit_state == 1
+      raise "审批通过的记录不允许删除!"
+    end
+  end
+
+  rails_admin do
+    navigation_label '资金管理'
+    parent CashBalance
+    weight -920
+
+    list do
+      filters [:wx_user,:order_id,:audit_state,:created_at]
+      field :id
+      field :wx_user
+      field :wx_uid      
+      field :order_id
+      field :trade_no
+      field :count do
+        pretty_value do
+          value/100.0
+        end
+      end
+      field :pay_state , :enum do
+        enum do
+          PAY_STATE_ENUM
+        end
+      end  
+      field :real_state , :enum do
+        enum do
+          REAL_ENUM
+        end
+      end  
+      field :audit_state, :enum do
+        enum do
+          STATE_ENUM
+        end
+      end  
+      field :paied_at do
+        pretty_value do
+          # value.to_i >0 ? Time.at(value.to_i) : ''
+          (value == nil || value <=0) ? "" : Time.at(value)          
+        end
+      end
+      field :bank_name
+      field :bank_account
+      field :account_name
+      field :expc_pay_at
+      field :remark
+      field :created_at
+    end
+
+    show do
+      field :wx_user
+      field :wx_uid      
+      field :order_id
+      field :trade_no
+      field :count do
+        pretty_value do
+          value/100.0
+        end
+      end
+      field :pay_state  , :enum do
+        enum do
+          PAY_STATE_ENUM
+        end
+      end 
+     field :real_state , :enum do
+        enum do
+          REAL_ENUM
+        end
+      end   
+      field :audit_state, :enum do
+        enum do
+          STATE_ENUM
+        end
+      end  
+      field :paied_at do
+        pretty_value do
+          # value.to_i >0 ? Time.at(value.to_i) : ''
+          (value == nil || value <=0) ? "" : Time.at(value)          
+        end
+      end
+      field :bank_name
+      field :bank_account
+      field :account_name
+      field :expc_pay_at
+      field :remark
+    end
+
+    edit do
+      field :wx_uid do
+        read_only do
+          [1].include?(bindings[:object].audit_state)
+        end
+      end
+      field :order_id do
+        read_only do
+          [1].include?(bindings[:object].audit_state)
+        end
+      end
+      field :trade_no do
+        read_only do
+          [1].include?(bindings[:object].audit_state)
+        end
+      end
+      field :count do
+        read_only do
+          [1].include?(bindings[:object].audit_state)
+        end
+      end
+      field :pay_state , :enum do
+        enum do
+          PAY_STATE_ENUM
+        end
+        # read_only do
+        #   [1].include?(bindings[:object].audit_state)
+        # end
+      end  
+      field :real_state , :enum do
+        enum do
+          REAL_ENUM
+        end
+      end  
+      field :audit_state, :enum do
+        enum do
+          STATE_ENUM
+        end
+        # read_only do
+        #   [1].include?(bindings[:object].audit_state)
+        # end
+      end  
+      field :paied_at do
+        label "支付时间,单位(秒)"
+      end
+      field :bank_name
+      field :bank_account
+      field :account_name
+      field :expc_pay_at
+      field :remark
+    end
+    export do
+      include_all_fields
+      field :count do
+        pretty_value do
+          value/100.0
+        end
+      end
+    end
+
+
+    end
+end

+ 220 - 0
app/models/user.rb

@@ -0,0 +1,220 @@
+# encoding:utf-8
+#会员表
+require 'digest/md5'
+class User < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "users"
+  belongs_to :parent_signup_channel, :foreign_key => :signup_channel_id
+
+  after_create :after_create
+  after_destroy :after_destroy
+  attr_accessor :sub, :wx_user, :v_head, :getNickname, :getProvince
+
+  validates :tel , uniqueness: true
+  # validates :pwd , :trade_pwd , presence: true
+  # vaildates_numericality_of :tel
+
+  # def wx_user
+  #   wx_user = WxUser.where("user_id = ?", self.id).first
+  #   if !wx_user.blank?
+  #     return wx_user.nickname
+  #   else
+  #     return "未关联"
+  #   end
+  # end
+
+  # def sub
+  #   wx_user = WxUser.where("user_id = ?", self.id).first
+  #   if !wx_user.blank?
+  #     return wx_user.subscribe
+  #   end    
+  # end
+
+  def after_create
+    md5_trade_pwd = Digest::MD5.hexdigest(self.trade_pwd)
+    self.trade_pwd = md5_trade_pwd
+    self.save
+  end
+
+  SEX_ENUM= [["未知","0"], ["男性","1"], ["女性", "2"]]
+  IMG_STORE_PATH = "user"
+
+  rails_admin do
+    navigation_label '用户管理'
+    weight -400
+
+    list do
+      filters [:id,:tel]
+      # include_all_fields
+      field :id 
+      field :nickname     
+      field :getNickname
+      field :real_name
+      field :sex, :enum do
+        enum do
+          SEX_ENUM
+        end
+      end
+      # field :age
+      field :head do
+        formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_head,
+          :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px',
+          :onClick => "javascript:window.open('#{bindings[:object].get_head}')"})
+        end
+      end
+      field :tel      
+      field :province
+      field :city
+      field :signup_channel_id
+      # field :sign_up_channel
+      field :signup_ip
+      field :invite_id
+      field :age
+      field :is_black_user
+      field :created_at
+      # field :updated_at
+    end
+
+    show do
+      field :id
+      field :nickname   
+      field :real_name
+      field :identity_card
+      field :is_certification   
+      field :tel
+      # field :pwd
+      # field :trade_pwd
+      field :birthday
+      field :city
+      field :country
+      field :province
+      field :sex, :enum do
+         enum do
+           SEX_ENUM
+         end
+      end
+      field :age
+      field :head do
+        formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_head,
+          :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px',
+          :onClick => "javascript:window.open('#{bindings[:object].get_head}')"})
+        end
+      end
+      field :invite_id
+      field :signup_channel_id
+      field :signup_ip
+      field :age
+      field :is_black_user
+      field :bank_name
+      field :bank_account
+      field :account_name
+      field :created_at
+      field :updated_at
+    end
+
+
+    edit do
+      field :real_name
+      field :identity_card
+      field :is_certification
+      field :tel 
+      #field :pwd     
+      field :trade_pwd
+      field :birthday
+      field :nickname
+      field :city
+      field :country
+      field :province
+      field :sex, :enum do
+        enum do
+          SEX_ENUM
+        end
+      end
+      field :age
+      field :v_head, :file_upload do
+         pretty_value do
+           bindings[:view].tag(:img, {:src => bindings[:object].get_head,
+            :class => 'preview'})
+         end
+      end
+      field :invite_id
+      field :signup_ip
+      field :signup_channel_id
+      field :bank_name
+      field :bank_account
+      field :account_name
+      field :is_black_user
+    end
+    
+  end
+
+  def get_head
+    url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.head}"
+    return url
+  end
+
+  def v_head=file
+    unless file.blank?
+      clear_head
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.head = file_path
+      self.save
+    end
+  end
+
+  def clear_head
+    file_path = "#{self.head}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def after_destroy
+    clear_head
+  end
+
+  def getProvince
+    if self.province.blank?
+      wx_user = WxUser.where("user_id =?", self.id).first
+      if !wx_user.blank?
+        self.signup_channel_id = wx_user.parent_signup_channel
+         self.save
+      end
+    end
+    return self.province
+  end
+
+  def getNickname
+
+    needUpdate = false
+    wxUser = WxUser.where("user_id = ?", self.id).first
+    return "-" if wxUser.blank?
+
+    if self.nickname == "" && wxUser.nickname != ""
+      self.nickname = wxUser.nickname
+      needUpdate = true if !needUpdate
+    end
+    if self.sex == 0 && wxUser.sex != 0
+      self.sex = wxUser.sex
+      needUpdate = true if !needUpdate
+    end
+    if self.country = "" && wxUser.country != ""
+      self.country = wxUser.country
+      needUpdate = true if !needUpdate
+    end
+    if self.province = "" && wxUser.province != ""
+      self.province = wxUser.province
+      needUpdate = true if !needUpdate
+    end
+    if self.city = "" && wxUser.city != ""
+      self.city = wxUser.city
+      needUpdate = true if !needUpdate
+    end
+
+    self.save if needUpdate
+    return self.nickname
+  end
+
+end

+ 66 - 0
app/models/wx_form_id.rb

@@ -0,0 +1,66 @@
+# encoding:utf-8
+class WxFormId < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "wx_form_ids"
+
+  attr_accessor :wx_user_name, :user_id, :is_outdate, :investments
+
+  def wx_user_name
+    wxUser = WxUser.where(" openid = ? ", self.openid).first
+    if !wxUser.blank?
+      return wxUser.nickname
+    end
+    return "-"
+  end
+  def user_id
+    wxUser = WxUser.where(" openid = ? ", self.openid).first
+    if !wxUser.blank?
+      return wxUser.user_id
+    end
+    return "-"
+  end
+  def is_outdate
+    if self.state == 1 
+      return true
+    else
+      return Time.now.to_i - 7 * 24 * 60 * 60 > self.created_at.to_i
+    end
+  end
+
+
+  rails_admin do
+    navigation_label '推送管理'
+    weight -450
+
+    list do
+      filters [:id,:state, :created_at]
+      field :id
+      field :wx_user_name
+      field :user_id
+      # field :openid
+      # field :form_id
+      field :state
+      field :is_outdate, :boolean
+      field :created_at
+      field :updated_at
+    end
+
+    show do
+      field :id
+      field :wx_user_name
+      field :user_id
+      field :openid
+      field :form_id
+      field :state
+      field :is_outdate, :boolean
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :openid
+      field :form_id
+      field :state
+    end
+  end
+end

+ 86 - 0
app/models/wx_gongzhonghao.rb

@@ -0,0 +1,86 @@
+# encoding:utf-8
+require 'uuid'
+class WxGongzhonghao < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "wx_gongzhonghaos"
+  # has_many :wx_menus
+  
+  validates :wx_hao,:wx_name,:app_id,presence: true
+
+  after_create :after_create
+
+  #生成token
+  def after_create
+    _token = UUID.new.generate(:compact)
+    if self.token.blank?
+      self.token = _token
+      self.save()
+    end
+  end
+
+  def wx_url
+    "#{CONFIG_FILE['api_host']}/mp/#{self.app_id}"
+  end
+
+  WX_TYPE_ENUM = [["服务号", "service"], ["订阅号", "subscribe"]]
+  rails_admin do
+    navigation_label '公众号管理'
+    weight -350
+
+    list do
+      filters [:wx_hao, :wx_name, :wx_type,:is_authed]
+      field :id
+      field :wx_hao
+      field :wx_name
+      field :is_authed
+      field :wx_type, :enum do
+        enum do
+          WX_TYPE_ENUM
+        end
+      end
+      # field :wx_menus
+      field :wx_url
+      field :token do
+      end
+      include_all_fields
+      field :created_at do
+        visible false
+      end
+      field :updated_at do
+        visible false
+      end
+    end
+    show do
+      field :id
+      field :wx_hao
+      field :wx_name
+      field :is_authed
+      field :wx_type, :enum do
+        enum do
+          WX_TYPE_ENUM
+        end
+      end
+      # field :wx_menus
+      field :wx_url
+      field :token do
+      end
+      include_all_fields
+      field :created_at
+      field :updated_at do
+        visible false
+      end
+    end
+
+    edit do
+      include_all_fields
+      field :wx_type, :enum do
+        enum do
+          WX_TYPE_ENUM
+        end
+      end
+      field :token do
+        visible false
+      end
+    end
+  end
+end

+ 70 - 0
app/models/wx_menu.rb

@@ -0,0 +1,70 @@
+# encoding:utf-8
+class WxMenu < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "wx_menus"
+  has_ancestry
+  belongs_to :wx_gongzhonghao
+  # attr_accessor   :ancestry
+  validates :wx_gongzhonghao_id,:name,:action ,presence: true
+
+  ACTION_ENUM = [["公众号", "root"],["链接", "view"], ["事件", "click"],["小程序","miniprogram"]]
+
+  rails_admin do
+    navigation_label '公众号管理'
+    weight -350
+
+    nestable_tree({
+                    position_field: :position ,
+                    max_depth: 3
+    })
+
+    list do
+      filters [:wx_gongzhonghao,:position,:action]
+      # include_all_fields
+      field :id
+      field :wx_gongzhonghao
+      field :wx_gongzhonghao_id
+      field :name
+      field :ancestry
+      field :action, :enum do
+        enum do
+          ACTION_ENUM
+        end
+      end
+      field :content   
+      field :appid
+      field :pagepath   
+      field :key
+      field :position
+      field :created_at
+    end
+    show do
+      # include_all_fields
+      field :id
+      field :wx_gongzhonghao
+      field :wx_gongzhonghao_id
+      field :name
+      field :ancestry
+      field :action, :enum do
+        enum do
+          ACTION_ENUM
+        end
+      end
+      field :content      
+      field :appid
+      field :pagepath 
+      field :key
+      field :position
+      field :created_at
+    end
+    edit do
+      include_all_fields
+      field :action, :enum do
+        enum do
+          ACTION_ENUM
+        end
+      end
+    end
+  end
+
+end

+ 249 - 0
app/models/wx_user.rb

@@ -0,0 +1,249 @@
+# encoding:utf-8
+#微信用户表
+class WxUser < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "wx_users"
+  belongs_to :user
+  #has_many :channel_qrcode_results, :foreign_key => :mp_openid
+  belongs_to :parent_signup_channel, :foreign_key => :channel_qrcode_id
+  validates_presence_of :nickname, :unionid
+  #belongs_to :channel_qrcode
+  attr_accessor :invite, :v_head, :intro_user
+
+  SEX_ENUM= [["未知","0"], ["男性","1"], ["女性", "2"]]
+
+  COPARTNET_STATE_ENUM = [["否",0],["是",1],["曾经是",2]]
+
+  IMG_STORE_PATH = "wx_user"
+
+  after_destroy :after_destroy
+
+  def invite
+    wu = WxUser.where("id = ?", invite_id).first
+    if !wu.blank?
+      return wu.nickname
+    end
+  end
+
+  def intro_user
+    wu = WxUser.where("id = ?", intro_user_id).first
+    if !wu.blank?
+      return wu.nickname
+    end
+  end
+
+  def tel
+    if self.user_id.to_i >0
+      u = User.where("id=?",self.user_id).first
+      return if u.blank?
+      return u.tel
+    end
+  end
+
+  def gzhOpenid
+    if self.id.to_i >0
+      u = WxUserGongzhonghao.where("wx_user_id=?",self.id).first
+      return if u.blank?
+      return u.gzh_open_id
+    end
+    return "-"
+  end
+  def gzhIsSub
+    if self.id.to_i >0
+      u = WxUserGongzhonghao.where("wx_user_id=?",self.id).first
+      return false if u.blank?
+      return u.subscribe
+    end
+    return false
+  end
+  def gzhSubTime
+    if self.id.to_i >0
+      u = WxUserGongzhonghao.where("wx_user_id=?",self.id).first
+      return "-" if u.blank? || u.subscribe_time.blank? || u.subscribe_time == nil
+      return Time.at(u.subscribe_time) if u.subscribe_time != nil
+    end
+    return "-"
+  end
+  def gzhUnSubTime
+    if self.id.to_i >0
+      u = WxUserGongzhonghao.where("wx_user_id=?",self.id).first
+      return "-" if u.blank? || u.unsubscribe_time.blank? || u.unsubscribe_time == nil
+      return Time.at(u.unsubscribe_time) if u.unsubscribe_time != nil
+    end
+    return "-"
+  end
+  def gzhLastConversationTime
+    if self.id.to_i >0
+      u = WxUserGongzhonghao.where("wx_user_id=?",self.id).first
+      return "-" if u.blank? || u.last_conversation_at.blank? || u.last_conversation_at == nil
+      return Time.at(u.last_conversation_at) if u.last_conversation_at != nil
+    end
+    return "-"
+  end
+  
+
+  rails_admin do
+    navigation_label '用户管理'
+    # parent User
+    weight -300
+
+    list do
+      filters [:id,:user_id,:nickname, :city, :parent_signup_channel, :sale_group, :sale_group_sum]
+      field :id
+      field :user_id do
+        filterable true
+      end
+      field :tel
+      # field :gzhOpenid
+      field :gzhIsSub, :boolean
+      field :gzhSubTime     
+      field :gzhUnSubTime      
+      field :gzhLastConversationTime      
+      field :nickname
+      field :invite_id
+      field :intro_user_id
+      field :sex, :enum do
+        enum do
+          SEX_ENUM
+        end
+      end
+      field :head do
+        formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_head_img,
+          :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px',
+          :onClick => "javascript:window.open('#{bindings[:object].get_head_img}')"})
+        end
+      end
+      # field :openid
+      # field :unionid
+      # field :province
+      field :city
+      # field :signup_ip
+      field :parent_signup_channel
+      field :show_invite_mode
+      field :sale_group
+      field :sale_group_sum
+      # field :channel_qrcode_id
+      field :created_at
+    end
+
+    show do
+      field :id
+      field :user
+      field :user_id
+      field :nickname
+      field :invite
+      field :invite_id
+      field :intro_user
+      field :intro_user_id
+      field :sex, :enum do
+        enum do
+          SEX_ENUM
+        end
+      end
+      field :head do
+        formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_head_img,
+          :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px',
+          :onClick => "javascript:window.open('#{bindings[:object].get_head_img}')"})
+        end
+      end
+
+      field :unionid
+      field :openid
+      field :gzhOpenid
+      field :gzhIsSub, :boolean
+      field :gzhSubTime     
+      field :gzhUnSubTime      
+      field :gzhLastConversationTime
+      field :province
+      field :city
+      field :signup_ip
+      # field :subscribe
+      # field :subscribe_time do
+      #   formatted_value do
+      #     (value !=nil || value != 0) ? Time.at(value):Time.now
+      #   end
+      # end
+      # field :unsubscribe_time do
+      #   formatted_value do
+      #     (value !=nil || value != 0) ? Time.at(value):Time.now
+      #   end
+      # end
+      # field :last_conversation_at do
+      #   formatted_value do
+      #     (value !=nil || value != 0) ? Time.at(value):Time.now
+      #   end
+      # end
+      # field :channel_qrcode_id
+      field :invite_qrcode_url
+      field :show_invite_mode
+      field :parent_signup_channel
+      field :sale_group
+      field :sale_group_sum
+      field :created_at
+    end
+
+    edit do
+      field :user_id
+      field :nickname
+      # field :unionid
+      field :city
+      field :country
+      field :province
+      field :sex, :enum do
+        enum do
+          SEX_ENUM
+        end
+      end
+      field :v_head, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_head_img, :class => 'preview'})
+        end
+      end
+      # field :subscribe
+      # field :unsubscribe_time, :datetime do
+      #   formatted_value do
+      #     (value.blank?) ? Time.at(0) : Time.at(value)
+      #   end
+      # end
+      # field :subscribe_time, :datetime do
+      #   formatted_value do
+      #     (value.blank?) ? Time.at(0) : Time.at(value)
+      #   end
+      # end
+      # field :last_conversation_at
+      field :invite_id
+      field :signup_ip
+      field :channel_qrcode_id
+      field :invite_qrcode_url
+      #field :show_invite_mode
+    end
+  end
+  def get_head_img
+    url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.head}"
+    return url
+  end
+
+  def v_head=file
+    unless file.blank?
+      clear_head_img
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.head = file_path
+      self.save
+    end
+  end
+
+  def clear_head_img
+    file_path = "#{self.head}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def after_destroy
+    clear_head_img
+  end
+
+
+end

+ 86 - 0
app/models/wx_user_gongzhonghao.rb

@@ -0,0 +1,86 @@
+# encoding:utf-8
+require 'uuid'
+class WxUserGongzhonghao < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "wx_user_gongzhonghaos"
+  # has_many :wx_menus
+  
+  validates :wx_user_id,:app_id,:gzh_open_id,presence: true
+
+  rails_admin do
+    navigation_label '用户管理'
+    weight -350
+
+    list do
+      filters [:wx_user_id, :app_id, :gzh_open_id]
+      field :id
+      field :wx_user_id
+      field :app_id
+      field :gzh_open_id
+      field :subscribe
+      field :subscribe_time do
+        formatted_value do
+          if not value.blank?
+            Time.at(value)
+          end
+        end
+      end
+      field :unsubscribe_time do
+        formatted_value do
+          if not value.blank?
+            Time.at(value)
+          end
+        end
+      end
+      field :last_conversation_at do
+        formatted_value do
+          if not value.blank?
+            Time.at(value)
+          end
+        end
+      end
+      include_all_fields
+      field :created_at do
+        visible false
+      end
+      field :updated_at do
+        visible false
+      end
+    end
+    show do
+      include_all_fields
+      field :subscribe
+      field :subscribe_time do
+        formatted_value do
+          if not value.blank?
+            Time.at(value)
+          end
+        end
+      end
+      field :unsubscribe_time do
+        formatted_value do
+          if not value.blank?
+            Time.at(value)
+          end
+        end
+      end
+      field :last_conversation_at do
+        formatted_value do
+          if not value.blank?
+            Time.at(value)
+          end
+        end
+      end
+      field :created_at
+      field :updated_at do
+        visible false
+      end
+    end
+
+    edit do
+      field :wx_user_id
+      field :app_id
+      field :gzh_open_id
+    end
+  end
+end

+ 436 - 0
app/models/wxku_commodity.rb

@@ -0,0 +1,436 @@
+# encoding:utf-8
+require 'uuid'
+class WxkuCommodity < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "wxku_commodities"
+  before_save :before_save
+  after_destroy :after_destroy
+  belongs_to :product
+  validates :product_id, :title,presence: true
+  attr_accessor :v_image_info_1, :v_image_info_2, :v_image_info_3, :v_image_info_4, :v_image_info_5
+  attr_accessor :is_delete_v_image_info_1, :is_delete_v_image_info_2, :is_delete_v_image_info_3, :is_delete_v_image_info_4, :is_delete_v_image_info_5
+   
+  IMG_STORE_PATH = "wxku_commodities" 
+
+  #图书,女装,男装,美妆个护,母婴,食品生鲜,数码家电,珠宝配饰,鞋靴箱包,运动户外,家居百货,汽车用品
+  OFFICIALCATEGORYINFO_ENUM = [
+                                ["食品生鲜","食品生鲜"],
+                                ["图书","图书"],
+                                ["女装","女装"],
+                                ["男装","男装"],
+                                ["美妆个护","美妆个护"],
+                                ["母婴","母婴"],
+                                ["数码家电","数码家电"],
+                                ["珠宝配饰","珠宝配饰"],
+                                ["鞋靴箱包","鞋靴箱包"],
+                                ["运动户外","运动户外"],
+                                ["家居百货","家居百货"],
+                                ["汽车用品","汽车用品"]]
+
+  SOURCE_ENUM = [["平台自营",1],["非平台自营",0]]
+
+  SALE_STATUS_ENUM = [["上架","on"],["下架","off"]]
+
+  rails_admin do
+    navigation_label '商品管理'
+    weight -240
+
+    list do
+      filters [:id]
+      field :id
+      field :product
+      field :image_info_1 do 
+          formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_image_info_1,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_image_info_1}')"})
+          end
+      end
+      field :image_info_2 do 
+          formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_image_info_2,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_image_info_2}')"})
+          end
+      end
+      field :category_info
+      field :official_category_info, :enum do 
+        enum do
+          OFFICIALCATEGORYINFO_ENUM
+        end
+      end
+      # field :url
+      field :title
+      field :sub_title
+      field :brand
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      # field :desc
+      field :min_price do
+        label "现价最低价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :max_price do
+        label "现价最高价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :min_ori_price do
+        label "原价最低价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :max_ori_price do
+        label "原价最高价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :sale_status, :enum do
+        enum do
+          SALE_STATUS_ENUM
+        end
+      end
+      field :stock
+      field :created_at
+    end
+
+    show do
+      field :id
+      field :product
+      field :product_id
+      field :image_info_1 do 
+          formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_image_info_1,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_image_info_1}')"})
+          end
+      end
+      field :image_info_2 do 
+          formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_image_info_2,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_image_info_2}')"})
+          end
+      end
+      field :image_info_3 do 
+          formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_image_info_3,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_image_info_3}')"})
+          end
+      end
+      field :image_info_4 do 
+          formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_image_info_4,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_image_info_4}')"})
+          end
+      end
+      field :image_info_5 do 
+          formatted_value do
+          bindings[:view].tag(:img,{:src => bindings[:object].get_image_info_5,
+              :style => 'width: 100px;height: 100px;cursor: pointer;display: block;max-width: 100px;',
+              :onClick => "javascript:window.open('#{bindings[:object].get_image_info_5}')"})
+          end
+      end
+      field :category_info
+      field :official_category_info, :enum do 
+        enum do
+          OFFICIALCATEGORYINFO_ENUM
+        end
+      end
+      field :url
+      field :title
+      field :sub_title
+      field :brand
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :desc
+      field :min_price do
+        label "现价最低价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :max_price do
+        label "现价最高价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :min_ori_price do
+        label "原价最低价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :max_ori_price do
+        label "原价最高价(元)"
+        formatted_value do # used in form views
+          value.to_f / 100
+        end
+      end
+      field :sale_status, :enum do
+        enum do
+          SALE_STATUS_ENUM
+        end
+      end
+      field :stock
+      field :status_ticket
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :product_id
+      field :v_image_info_1, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_image_info_1, :class => 'preview'})
+        end        
+      end
+      field :is_delete_v_image_info_1, :boolean do
+        visible do
+          bindings[:object].image_info_1 != "" && bindings[:object].image_info_1 != nil
+        end
+      end
+      field :v_image_info_2, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_image_info_2, :class => 'preview'})
+        end        
+      end
+      field :is_delete_v_image_info_2, :boolean do
+        visible do
+          bindings[:object].image_info_2 != "" && bindings[:object].image_info_2 != nil
+        end
+      end
+      field :v_image_info_3, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_image_info_3, :class => 'preview'})
+        end        
+      end
+      field :is_delete_v_image_info_3, :boolean do
+        visible do
+          bindings[:object].image_info_3 != "" && bindings[:object].image_info_3 != nil
+        end
+      end
+      field :v_image_info_4, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_image_info_4, :class => 'preview'})
+        end        
+      end
+      field :is_delete_v_image_info_4, :boolean do
+        visible do
+          bindings[:object].image_info_4 != "" && bindings[:object].image_info_4 != nil
+        end
+      end
+      field :v_image_info_5, :file_upload do
+        pretty_value do
+          bindings[:view].tag(:img, {:src => bindings[:object].get_image_info_5, :class => 'preview'})
+        end        
+      end
+      field :is_delete_v_image_info_5, :boolean do
+        visible do
+          bindings[:object].image_info_5 != "" && bindings[:object].image_info_5 != nil
+        end
+      end
+      field :category_info
+      field :official_category_info, :enum do 
+        enum do
+          OFFICIALCATEGORYINFO_ENUM
+        end
+      end
+      field :url
+      field :title
+      field :sub_title
+      field :brand
+      field :source, :enum do
+        enum do
+          SOURCE_ENUM
+        end
+      end
+      field :desc
+      field :min_price do
+        label "现价最低价(分)"
+      end
+      field :max_price do
+        label "现价最高价(分)"
+      end
+      field :min_ori_price do
+        label "原价最低价(分)"
+      end
+      field :max_ori_price do
+        label "原价最高价(分)"
+      end
+      field :sale_status, :enum do
+        enum do
+          SALE_STATUS_ENUM
+        end
+      end
+      field :stock
+      field :status_ticket
+    end
+  end
+
+  def v_image_info_1=file
+    unless file.blank?
+      clear_image_info_1
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.image_info_1 = file_path
+      self.save
+    end
+  end
+
+  def clear_image_info_1
+    file_path = "#{self.image_info_1}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_image_info_1
+    if self.image_info_1 != ""
+      url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.image_info_1}"
+      return url
+    end
+    return ""
+  end
+
+  def v_image_info_2=file
+    unless file.blank?
+      clear_image_info_2
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.image_info_2 = file_path
+      self.save
+    end
+  end
+
+  def clear_image_info_2
+    file_path = "#{self.image_info_2}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_image_info_2
+    if self.image_info_2 != ""
+      url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.image_info_2}"
+      return url
+    end
+    return ""
+  end
+
+  def v_image_info_3=file
+    unless file.blank?
+      clear_image_info_3
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.image_info_3 = file_path
+      self.save
+    end
+  end
+
+  def clear_image_info_3
+    file_path = "#{self.image_info_3}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_image_info_3
+    if self.image_info_3 != ""
+      url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.image_info_3}"
+      return url
+    end
+    return ""
+  end
+
+  def v_image_info_4=file
+    unless file.blank?
+      clear_image_info_4
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.image_info_4 = file_path
+      self.save
+    end
+  end
+
+  def clear_image_info_4
+    file_path = "#{self.image_info_4}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_image_info_4
+    if self.image_info_4 != ""
+      url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.image_info_4}"
+      return url
+    end
+    return ""
+  end
+
+  def v_image_info_5=file
+    unless file.blank?
+      clear_image_info_5
+      file_name = "#{UUID.new.generate[0...8].downcase}.jpg"
+      file_path = "#{IMG_STORE_PATH}/#{file_name}"
+      Ali::Oss.store(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path, file.read)
+      self.image_info_5 = file_path
+      self.save
+    end
+  end
+
+  def clear_image_info_5
+    file_path = "#{self.image_info_5}"
+    Ali::Oss.delete_object(Ali::Oss::BUCKET_NAME_PUBLIC_READ, file_path)
+  end
+
+  def get_image_info_5
+    if self.image_info_5 != ""
+      url = "http://#{Ali::Oss::CDN_URL_FOR_HOST}/#{self.image_info_5}"
+      return url
+    end
+    return ""
+  end
+
+  def before_save
+    if self.is_delete_v_image_info_1.to_i == 1
+      clear_image_info_1
+      self.image_info_1 = ""
+    end
+    if self.is_delete_v_image_info_2.to_i == 1
+      clear_image_info_2
+      self.image_info_2 = ""
+    end
+    if self.is_delete_v_image_info_3.to_i == 1
+      clear_image_info_3
+      self.image_info_3 = ""
+    end
+    if self.is_delete_v_image_info_4.to_i == 1
+      clear_image_info_4
+      self.image_info_4 = ""
+    end
+    if self.is_delete_v_image_info_5.to_i == 1
+      clear_image_info_5
+      self.image_info_5 = ""
+    end
+  end
+
+  def after_destroy
+    clear_image_info_1   
+    clear_image_info_2
+    clear_image_info_3
+    clear_image_info_4
+    clear_image_info_5  
+  end
+
+end

+ 144 - 0
app/models/xcx_push_tmpl.rb

@@ -0,0 +1,144 @@
+# encoding:utf-8
+class XcxPushTmpl < ActiveRecord::Base
+  has_paper_trail
+  self.table_name = "xcx_push_tmpls"
+  MSG_TYPE_ENUM = [
+    ["物品状态提醒","MessageTemplateId_ItemStatusRemind"],
+    ["众筹项目最新状态通知","MessageTemplateId_ProjectNewStateNofity"],
+    ["提货通知","MessageTemplateId_DeliveryNotify"]
+  ]
+  EMPHASIS_ENUM = [
+    ["内容1","keyword1.DATA"],
+    ["内容2","keyword2.DATA"],
+    ["内容3","keyword3.DATA"],
+    ["内容4","keyword4.DATA"],
+    ["内容5","keyword5.DATA"],
+    ["无","-"],
+  ]
+  # def get_push_count
+  #   if self.push_count.to_i >0
+  #     return self.push_count 
+  #   end
+  #   if !self.user_id.blank?
+  #     if self.user_id.start_with?("sql=select * ")
+  #       sql = self.user_id.gsub("sql=select * ","select count(*) as sqlcount ")
+  #       item = WxUser.find_by_sql(sql)
+  #       if !item.blank?
+  #         c = item[0].sqlcount
+  #         if self.push_count == 0 
+  #           self.push_count  = c
+  #           self.save
+  #         end
+  #         return c
+  #       end
+  #     end
+  #   end
+  # end
+
+  # def get_click_count
+  #   if self.click_count.to_i >0
+  #     return self.click_count 
+  #   end
+  #   if self.url.blank?
+  #     return 
+  #   end
+  #   if self.url.start_with?("#{CONFIG_FILE["api_host"]}/v1/cfc/")
+  #     size = "#{CONFIG_FILE["api_host"]}/v1/cfc/".size
+  #     id = self.url[size..-1].to_i
+  #     if id>0 
+  #       item = ClickFromChannel.where("id=?",id).first
+  #       if !item.blank?
+  #         if item.click_times !=self.click_count 
+  #           self.click_count  = item.click_times
+  #           self.save
+  #         end
+  #         return item.click_times
+  #       end
+  #     end
+  #   end
+  # end
+
+  rails_admin do
+    navigation_label '推送管理'
+    weight -220
+
+    list do
+      items_per_page 10
+      filters [:id, :user_id]
+      field :id
+      field :user_id
+      field :msg_type, :enum do
+        enum do
+          MSG_TYPE_ENUM
+        end
+      end
+      field :push_force
+      field :emphasis_keyword, :enum do
+        enum do
+          EMPHASIS_ENUM
+        end
+      end
+      field :keyword1
+      field :keyword2
+      field :keyword3
+      field :keyword4
+      field :keyword5
+      field :page
+      field :last_updated_at
+      field :times
+      field :created_at
+    end
+
+    show do
+      field :id
+      field :user_id
+      field :msg_type, :enum do
+        enum do
+          MSG_TYPE_ENUM
+        end
+      end
+      field :push_force
+      field :emphasis_keyword, :enum do
+        enum do
+          EMPHASIS_ENUM
+        end
+      end
+      field :keyword1
+      field :keyword2
+      field :keyword3
+      field :keyword4
+      field :keyword5
+      field :page
+      field :last_updated_at
+      field :times
+      field :created_at
+      field :updated_at
+    end
+
+    edit do
+      field :user_id do
+        label "微信用户ID(注意:填微信用户id(以逗号分隔)、填all(所有微信用户)、填allUser(所有注册用户)、填sql=xxx(xxx执行结果是WxUser结构体))"
+      end
+      field :msg_type, :enum do
+        enum do
+          MSG_TYPE_ENUM
+        end
+      end
+      field :push_force
+      field :emphasis_keyword, :enum do
+        enum do
+          EMPHASIS_ENUM
+        end
+      end
+      field :keyword1
+      field :keyword2
+      field :keyword3
+      field :keyword4
+      field :keyword5
+      field :page
+      field :last_updated_at
+      field :times
+    end
+  end
+
+end

+ 33 - 0
app/models/xcx_push_tmpl_record.rb

@@ -0,0 +1,33 @@
+# encoding:utf-8
+class XcxPushTmplRecord < ActiveRecord::Base
+  has_paper_trail  
+  self.table_name = "xcx_push_tmpl_records"
+  belongs_to :wx_user , :foreign_key => :wx_uid
+  rails_admin do
+    navigation_label '推送管理'
+    weight -220
+
+    list do
+      filters [:id, :wx_user, :temp_id, :push_time]
+      field :id
+      field :wx_user    
+      field :temp_id
+      field :push_time
+    end
+
+    show do
+      field :id
+      field :wx_uid    
+      field :temp_id
+      field :push_time
+    end
+
+    edit do
+      field :id
+      field :wx_uid    
+      field :temp_id
+      field :push_time
+    end
+  end
+
+end

+ 34 - 0
app/models/xcx_version.rb

@@ -0,0 +1,34 @@
+# encoding: utf-8
+class XcxVersion < ActiveRecord::Base
+  self.table_name = "xcx_versions"
+  validates :version,:desc,presence: true
+
+  rails_admin do
+    navigation_label '小程序发布管理'
+    weight -500
+    list do
+      filters [:version,:state]
+      field :id
+      field :version      
+      field :desc
+      field :state      
+      field :created_at
+      # field :updated_at
+    end
+    show do
+      field :id
+      field :version      
+      field :desc
+      field :state      
+      field :created_at
+      field :updated_at
+    end
+    edit do
+      field :version      
+      field :desc
+      field :state    
+    end
+
+  end
+
+end

+ 17 - 0
app/views/chunjie_config_stat/index.html.erb

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>第五创</title>
+  <link rel="stylesheet" href="/css/index.css">
+</head>
+<body>
+
+活动名称:<%=@title%><br/>
+已发放的红包总额:<%=@hongbaoTotalMoney%><br/>
+参与人数:<%=@total_join%><br/>
+新增注册用户数:<%=@total_new_register%><br/>
+新增关注:<%=@total_new_sub%><br/>
+
+</body>
+</html>

+ 20 - 0
app/views/devise/sessions/new.html.erb

@@ -0,0 +1,20 @@
+<div class="container">
+
+  <%= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => {:class => "form-signin"}) do |f| %>
+      <div class="form-signin-heading">用户登入</div>
+      <% if flash[:alert] %>
+          <div class="alert alert-error">
+            <a class="close" data-dismiss="alert">×</a>
+            <div id="flash_alert"><%= flash[:alert] %></div>
+          </div>
+      <% end -%>
+      <%= f.email_field :email, :autofocus => true, :class => "input-block-level", :placeholder => "邮箱" %>
+      <br/>
+      <%= f.password_field :password, :class => "input-block-level", :placeholder => "密码" %>
+      <label class="checkbox">
+        <%= f.check_box :remember_me %> <span class="remember_pw">记住密码</span>
+      </label>
+      <%= f.submit "登入", :class => "btn btn-large btn-primary" %>
+  <% end -%>
+
+</div>

+ 15 - 0
app/views/layouts/application.html.erb

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>AdminD5ctCom</title>
+  <%= stylesheet_link_tag    "application", :media => "all" %>
+  <%= javascript_include_tag "application" %>
+  <%= javascript_include_tag 'ckeditor/ckeditor.js' %>
+  <%= csrf_meta_tags %>
+</head>
+<body>
+
+<%= yield %>
+
+</body>
+</html>

+ 114 - 0
app/views/layouts/devise_layout.html.erb

@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>登入</title>
+  <%= stylesheet_link_tag    "application", :media => "all" %>
+  <%= javascript_include_tag "application" %>
+  <style>
+      body {
+          padding-top: 100px;
+          padding-bottom: 40px;
+          /*background-color: #f5f5f5;*/
+          font-family: 'PT Sans', Helvetica, Arial, sans-serif;
+          background: #f8f8f8;
+      }
+      .form-signin {
+          max-width: 300px;
+          padding: 19px 29px 29px;
+          margin: 0 auto 20px;
+          background-color: #fff;
+          border: 1px solid #e5e5e5;
+          -webkit-border-radius: 5px;
+          -moz-border-radius: 5px;
+          border-radius: 5px;
+          -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
+          -moz-box-shadow: 0 1px 2px rgba(0,0,0,.05);
+          box-shadow: 0 1px 2px rgba(0,0,0,.05);
+      }
+      /*用户登录*/
+      .form-signin-heading{
+        font-size: 30px;
+        font-weight: 700;
+        text-shadow: 0 1px 4px rgba(0,0,0,.2);
+        text-align: center;
+      }
+      /*输入框*/
+      .input-block-level{
+        width: 250px;
+        height: 42px;
+        margin-top: 25px;
+        padding: 0 15px;
+        background: #2d2d2d; /* browsers that don't support rgba */
+        background: rgba(45,45,45,.15);
+        -moz-border-radius: 6px;
+        -webkit-border-radius: 6px;
+        border-radius: 6px;
+        border: 1px solid #3d3d3d; /* browsers that don't support rgba */
+        border: 1px solid rgba(255,255,255,.15);
+        -moz-box-shadow: 0 2px 3px 0 rgba(0,0,0,.1) inset;
+        -webkit-box-shadow: 0 2px 3px 0 rgba(0,0,0,.1) inset;
+        box-shadow: 0 2px 3px 0 rgba(0,0,0,.1) inset;
+        font-family: 'PT Sans', Helvetica, Arial, sans-serif;
+        font-size: 14px;
+        color: #000;
+        text-shadow: 0 1px 2px rgba(0,0,0,.1);
+        -o-transition: all .2s;
+        -moz-transition: all .2s;
+        -webkit-transition: all .2s;
+        -ms-transition: all .2s;
+      }
+      /*记住密码*/
+      .checkbox{
+        width: 250px;
+        height: 25px;
+        margin-top: 15px;
+        margin-left: 20px;
+        padding: 0 15px;
+      }
+      /*登录*/
+      .btn{
+        /*color: */
+        cursor: pointer;
+        width: 250px;
+        height: 44px;
+        margin-top: 0px;
+        padding: 0;
+        background: #ef4300;
+        -moz-border-radius: 6px;
+        -webkit-border-radius: 6px;
+        border-radius: 6px;
+        border: 1px solid #ff730e;
+        -moz-box-shadow:
+            0 15px 30px 0 rgba(255,255,255,.25) inset,
+            0 2px 7px 0 rgba(0,0,0,.2);
+        -webkit-box-shadow:
+            0 15px 30px 0 rgba(255,255,255,.25) inset,
+            0 2px 7px 0 rgba(0,0,0,.2);
+        box-shadow:
+            0 15px 30px 0 rgba(255,255,255,.25) inset,
+            0 2px 7px 0 rgba(0,0,0,.2);
+        font-family: 'PT Sans', Helvetica, Arial, sans-serif;
+        font-size: 14px;
+        font-weight: 700;
+        color: #fff;
+        text-shadow: 0 1px 2px rgba(0,0,0,.1);
+        -o-transition: all .2s;
+        -moz-transition: all .2s;
+        -webkit-transition: all .2s;
+        -ms-transition: all .2s;
+      }
+      span.remember_pw{
+        font-family: 'PT Sans', Helvetica, Arial, sans-serif;
+        font-size: 14px;
+        font-weight: 700;
+        text-shadow: 0 1px 2px rgba(0,0,0,.1);
+      }
+  </style>
+  <%= csrf_meta_tags %>
+</head>
+<body>
+
+<%= yield %>
+
+</body>
+</html>

+ 49 - 0
app/views/rails_admin/cash_balance/refuse_takecash.html.erb

@@ -0,0 +1,49 @@
+<%
+  @confirm = params[:confirm].to_i || 0
+  @confirm_diaplay = params[:c] || "block"
+  @success_display = params[:s] || "none"
+  if @confirm == 1
+    if @object.pay_state == 0
+      #回退提现金额到账户余额中, 确保账户表中之前没有拒绝的记录
+      cbalance = CashBalance.where("wx_uid = ? and source = ? and relate_id = ?", 
+        @object.wx_uid, 'extract_reject', @object.order_id).first
+      if cbalance.blank?
+        cbalance = CashBalance.new
+        cbalance.wx_uid = @object.wx_uid
+        cbalance.relate_id = @object.order_id
+        cbalance.source = "extract_reject"
+        cbalance.count = @object.count
+        cbalance.remark = "提现被拒绝"
+        cbalance.save
+
+        update_sql = "update take_cash_orders set audit_state = 2 where id = '#{@object.id}'"
+        TakeCashOrder.connection.execute(update_sql)                    
+      end
+    end
+  end
+%>
+<!DOCTYPE html>
+<html>
+<head>
+  <title>拒绝提现</title>
+  <script type="text/javascript">
+    function confirm(){
+     <% go_url = "#{CONFIG_FILE["admin_host"]}/admin/take_cash_order/#{@object.id}/refuse_takecash?confirm=1&c=none&s=block" %> 
+      window.open("<%= go_url %>","_self");
+    }
+    function not_confirm(){
+      <% go_url2 = "#{CONFIG_FILE["admin_host"]}/admin/take_cash_order" %>
+      window.open("<%= go_url2 %>","_self");
+    }
+  </script>
+</head>
+<body>
+  <div id="confirm" style="display: <%=@confirm_diaplay%>">
+    <input type="button" value="是的,我确定" id="yes" onclick="confirm()" >
+    <input type="button" value="取 消" id="no" onclick="not_confirm()" >
+  </div>
+  <div id="success" style="display:<%=@success_display%>;">
+    <h3>已拒绝, 提现款项已回到资金账户中。</h3>
+  </div>
+</body>
+</html>

+ 4 - 0
config.ru

@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment',  __FILE__)
+run AdminD5ctCom::Application

+ 79 - 0
config/application.rb

@@ -0,0 +1,79 @@
+require File.expand_path('../boot', __FILE__)
+
+# Pick the frameworks you want:
+require "active_record/railtie"
+require "action_controller/railtie"
+require "action_mailer/railtie"
+# require "active_resource/railtie"
+require "sprockets/railtie"
+# require "rails/test_unit/railtie"
+
+if defined?(Bundler)
+  # If you precompile assets before deploying to production, use this line
+  Bundler.require(*Rails.groups(:assets => %w(development test)))
+  # If you want your assets lazily compiled in production, use this line
+  # Bundler.require(:default, :assets, Rails.env)
+end
+
+module AdminD5ctCom
+  class Application < Rails::Application
+    # require 'active_record/connection_adapters/mysql2_adapter'
+    # ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
+    # Settings in config/environments/* take precedence over those specified here.
+    # Application configuration should go into files in config/initializers
+    # -- all .rb files in that directory are automatically loaded.
+
+    # Custom directories with classes and modules you want to be autoloadable.
+    # config.autoload_paths += %W(#{config.root}/extras)
+    config.autoload_paths += %W(#{config.root}/lib)
+
+    # Only load the plugins named here, in the order given (default is alphabetical).
+    # :all can be used as a placeholder for all plugins not explicitly named.
+    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+    # Activate observers that should always be running.
+    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
+
+    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+    # config.time_zone = 'Central Time (US & Canada)'
+    config.time_zone = 'Beijing'
+    #config.active_record.default_timezone = :local
+    Time::DATE_FORMATS[:default] = "%Y-%m-%d %H:%M:%S"
+    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+    # config.i18n.load_path = Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
+    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
+    config.i18n.default_locale = 'zh-CN'
+
+    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+    # config.i18n.default_locale = :de
+
+    # Configure the default encoding used in templates for Ruby 1.9.
+    config.encoding = "utf-8"
+
+    # Configure sensitive parameters which will be filtered from the log file.
+    config.filter_parameters += [:password]
+
+    # Enable escaping HTML in JSON.
+    config.active_support.escape_html_entities_in_json = true
+
+    # Use SQL instead of Active Record's schema dumper when creating the database.
+    # This is necessary if your schema can't be completely dumped by the schema dumper,
+    # like if you have constraints or database-specific column types
+    # config.active_record.schema_format = :sql
+
+    # Enforce whitelist mode for mass assignment.
+    # This will create an empty whitelist of attributes available for mass-assignment for all models
+    # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
+    # parameters by using an attr_accessible or attr_protected declaration.
+    # config.active_record.whitelist_attributes = false
+
+    # Enable the asset pipeline
+    config.assets.enabled = true
+
+    # Version of your assets, change this if you want to expire all your assets
+    config.assets.version = '1.0'
+    config.autoload_paths += %W(#{config.root}/app/models/ckeditor)
+  end
+end

+ 6 - 0
config/boot.rb

@@ -0,0 +1,6 @@
+require 'rubygems'
+
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+ENV['EXECJS_RUNTIME'] = 'Node'
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])

+ 35 - 0
config/config.yml

@@ -0,0 +1,35 @@
+development:
+  root_path:  /home/rails/fohow/admin
+  admin_host: http://tfhadmin.hiwavo.com
+  wx_host: http://testlfwx.hiwavo.com
+  api_host: https://tfohowapi.hiwavo.com
+  m_host: http://testlfohom.hiwavo.com
+
+  ali_access_id: LTAI4G4BptSJxPYrnx4XFnT5
+  ali_access_secret: 3QFdigF8Ngm5Z1X1U3WkTHYoAHyajh
+  ali_oss_bucket: fohow-test
+  ali_oss_data_center: oss-cn-shenzhen
+
+test:
+  root_path:  /home/rails/fohow/admin
+  admin_host: http://testadmin.hiwavo.com
+  wx_host: http://testwx.hiwavo.com
+  api_host: https://testapi.hiwavo.com
+  m_host: http://testm.hiwavo.com
+
+  ali_access_id: LTAIkgdHJ7VrV8JN
+  ali_access_secret: WcopFbgfdUdtgB8Q5ccstqvkouNwJa
+  ali_oss_bucket: d5ctest
+  ali_oss_data_center: oss-cn-shanghai
+
+production:
+  root_path:  /home/www/fohow/admin.com
+  admin_host: http://fhadmin.hiwavo.com
+  api_host: https://ofohowapi.hiwavo.com
+  m_host: https://lfohom.hiwavo.com
+
+  ali_access_id: LTAI4G4BptSJxPYrnx4XFnT5
+  ali_access_secret: 3QFdigF8Ngm5Z1X1U3WkTHYoAHyajh
+  ali_oss_bucket: fohow
+  ali_oss_data_center: oss-cn-shenzhen
+

+ 43 - 0
config/database.yml

@@ -0,0 +1,43 @@
+# MySQL.  Versions 4.1 and 5.0 are recommended.
+# 
+# Install the MYSQL driver
+#   gem install mysql2
+#
+# Ensure the MySQL gem is defined in your Gemfile
+#   gem 'mysql2'
+#
+# And be sure to use new-style password hashing:
+#   http://dev.mysql.com/doc/refman/5.0/en/old-client.html
+development:
+  adapter: mysql2
+  encoding: utf8
+  reconnect: false
+  database: test_fohow
+  pool: 5
+  username: root
+  password: fohow123!@#
+  host: 127.0.0.1
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+  adapter: mysql2
+  encoding: utf8
+  reconnect: false
+  database: org_db
+  pool: 5
+  username: root
+  password: fohow123!@#
+  host: 127.0.0.1
+
+production:
+  adapter: mysql2
+  encoding: utf8
+  reconnect: false
+  database: fohow_org
+  pool: 30
+  username: vx99mall
+  password: fohow123!@#
+  port: 3306
+  host: rm-wz9pd3e23k8d32t99.mysql.rds.aliyuncs.com

+ 7 - 0
config/environment.rb

@@ -0,0 +1,7 @@
+#encoding: utf-8
+# Load the rails application
+require File.expand_path('../application', __FILE__)
+
+# Initialize the rails application
+AdminD5ctCom::Application.initialize!
+Time::DATE_FORMATS[:format] = "%Y年%m月%d %H:%M:%S"

+ 39 - 0
config/environments/development.rb

@@ -0,0 +1,39 @@
+AdminD5ctCom::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # In the development environment your application's code is reloaded on
+  # every request. This slows down response time but is perfect for development
+  # since you don't have to restart the web server when you make code changes.
+  config.cache_classes = false
+  config.eager_load = false
+
+  # Log error messages when you accidentally call methods on nil.
+  config.whiny_nils = true
+
+  # Show full error reports and disable caching
+  config.consider_all_requests_local       = true
+  config.action_controller.perform_caching = false
+  config.active_record.raise_in_transactional_callbacks = true
+
+  # Don't care if the mailer can't send
+  config.action_mailer.raise_delivery_errors = false
+
+  # Print deprecation notices to the Rails logger
+  config.active_support.deprecation = :log
+
+  # Only use best-standards-support built into browsers
+  config.action_dispatch.best_standards_support = :builtin
+
+  # Raise exception on mass assignment protection for Active Record models
+  # config.active_record.mass_assignment_sanitizer = :strict
+
+  # Log the query plan for queries taking more than this (works
+  # with SQLite, MySQL, and PostgreSQL)
+  # config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+  # Do not compress assets
+  config.assets.compress = false
+
+  # Expands the lines which load the assets
+  config.assets.debug = true
+end

+ 71 - 0
config/environments/production.rb

@@ -0,0 +1,71 @@
+AdminD5ctCom::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # Code is not reloaded between requests
+  config.cache_classes = false
+  config.eager_load = true
+
+  # Full error reports are disabled and caching is turned on
+  config.consider_all_requests_local       = false
+  config.action_controller.perform_caching = true
+
+  # Disable Rails's static asset server (Apache or nginx will already do this)
+  config.serve_static_files = false
+
+  # Compress JavaScripts and CSS
+  config.assets.compress = true
+
+  # Don't fallback to assets pipeline if a precompiled asset is missed
+  config.assets.compile = true
+
+  # Generate digests for assets URLs
+  config.assets.digest = true
+
+  # Defaults to nil and saved in location specified by config.assets.prefix
+  # config.assets.manifest = YOUR_PATH
+
+  # Specifies the header that your server uses for sending files
+  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+
+  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+  # config.force_ssl = true
+
+  # See everything in the log (default is :info)
+  config.log_level = :info
+
+  # Prepend all log lines with the following tags
+  # config.log_tags = [ :subdomain, :uuid ]
+
+  # Use a different logger for distributed setups
+  # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+  # Use a different cache store in production
+  # config.cache_store = :mem_cache_store
+
+  # Enable serving of images, stylesheets, and JavaScripts from an asset server
+  # config.action_controller.asset_host = "http://assets.example.com"
+
+  # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
+  # config.assets.precompile += %w( search.js )
+  # config.assets.precompile << '*.js'
+
+  # Disable delivery errors, bad email addresses will be ignored
+  # config.action_mailer.raise_delivery_errors = false
+  #邮箱 验证
+  # config.action_mailer.default_url_options = { :host => 'localhost:3000' }  
+
+  # Enable threaded mode
+  # config.threadsafe!
+
+  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+  # the I18n.default_locale when a translation can not be found)
+  config.i18n.fallbacks = true
+
+  # Send deprecation notices to registered listeners
+  config.active_support.deprecation = :notify
+
+  # Log the query plan for queries taking more than this (works
+  # with SQLite, MySQL, and PostgreSQL)
+  # config.active_record.auto_explain_threshold_in_seconds = 0.5
+end

+ 45 - 0
config/environments/test.rb

@@ -0,0 +1,45 @@
+AdminD5ctCom::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # The test environment is used exclusively to run your application's
+  # test suite. You never need to work with it otherwise. Remember that
+  # your test database is "scratch space" for the test suite and is wiped
+  # and recreated between test runs. Don't rely on the data there!
+  config.cache_classes = false
+  config.eager_load = false
+  # Configure static asset server for tests with Cache-Control for performance
+  config.serve_static_files = true
+  config.static_cache_control = "public, max-age=3600"
+
+  # Log error messages when you accidentally call methods on nil
+  config.whiny_nils = true
+
+  # Show full error reports and disable caching
+  config.consider_all_requests_local       = true
+  config.action_controller.perform_caching = false
+
+  # Raise exceptions instead of rendering exception templates
+  config.action_dispatch.show_exceptions = false
+
+  #DEPRECATION WARNING: Currently, Active Record suppresses errors raised within `after_rollback`/`after_commit` callbacks
+  #and only print them to the logs. In the next version, these errors will no longer be suppressed. Instead, the errors wil
+  #l propagate normally just like in other Active Record callbacks.
+
+  #You can opt into the new behavior and remove this warning by setting:
+  config.active_record.raise_in_transactional_callbacks = true
+
+  # Disable request forgery protection in test environment
+  config.action_controller.allow_forgery_protection    = false
+
+  # Tell Action Mailer not to deliver emails to the real world.
+  # The :test delivery method accumulates sent emails in the
+  # ActionMailer::Base.deliveries array.
+  config.action_mailer.delivery_method = :test
+
+  # Raise exception on mass assignment protection for Active Record models
+  # config.active_record.mass_assignment_sanitizer = :strict
+
+  # Print deprecation notices to the stderr
+  config.active_support.deprecation = :stderr
+
+end

+ 7 - 0
config/initializers/backtrace_silencers.rb

@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!

+ 58 - 0
config/initializers/ckeditor.rb

@@ -0,0 +1,58 @@
+# Use this hook to configure ckeditor
+Ckeditor.setup do |config|
+  # ==> ORM configuration
+  # Load and configure the ORM. Supports :active_record (default), :mongo_mapper and
+  # :mongoid (bson_ext recommended) by default. Other ORMs may be
+  # available as additional gems.
+  require "ckeditor/orm/active_record"
+
+  # Allowed image file types for upload.
+  # Set to nil or [] (empty array) for all file types
+  # By default: %w(jpg jpeg png gif tiff)
+  # config.image_file_types = %w(jpg jpeg png gif tiff)
+
+  # Allowed flash file types for upload.
+  # Set to nil or [] (empty array) for all file types
+  # By default: %w(jpg jpeg png gif tiff)
+  # config.flash_file_types = %w(swf)
+
+  # Allowed attachment file types for upload.
+  # Set to nil or [] (empty array) for all file types
+  # By default: %w(doc docx xls odt ods pdf rar zip tar tar.gz swf)
+  # config.attachment_file_types = %w(doc docx xls odt ods pdf rar zip tar tar.gz swf)
+
+  # Setup authorization to be run as a before filter
+  # By default: there is no authorization.
+  # config.authorize_with :cancan
+
+  # Override parent controller CKEditor inherits from
+  # By default: 'ApplicationController'
+  # config.parent_controller = 'MyController'
+
+  # Asset model classes
+  #  config.picture_model { Ckeditor::Picture }
+  # config.attachment_file_model { Ckeditor::AttachmentFile }
+
+  # Paginate assets
+  # By default: 24
+  # config.default_per_page = 24
+
+  # Customize ckeditor assets path
+  # By default: nil
+  # config.asset_path = "http://www.example.com/assets/ckeditor/"
+
+  # To reduce the asset precompilation time, you can limit plugins and/or languages to those you need:
+  # By default: nil (no limit)
+  # config.assets_languages = ['en', 'uk']
+  # config.assets_plugins = ['image', 'smiley']
+
+  # CKEditor CDN
+  # More info here http://cdn.ckeditor.com/
+  # By default: nil (CDN disabled)
+  # config.cdn_url = "//cdn.ckeditor.com/4.5.6/standard/ckeditor.js"
+
+  # JS config url
+  # Used when CKEditor CDN enabled
+  # By default: "/assets/ckeditor/config.js"
+  # config.js_config_url = "/assets/ckeditor/config.js"
+end

+ 265 - 0
config/initializers/devise.rb

@@ -0,0 +1,265 @@
+# Use this hook to configure devise mailer, warden hooks and so forth.
+# Many of these configuration options can be set straight in your model.
+Devise.setup do |config|
+  # The secret key used by Devise. Devise uses this key to generate
+  # random tokens. Changing this key will render invalid all existing
+  # confirmation, reset password and unlock tokens in the database.
+  # Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key`
+  # by default. You can change it below and use your own secret key.
+  config.secret_key = 'c050bf52e7141ce6b1514132f5d9e8acf6713cfd3cff5b66b1e6d1a88a3e8b44b635526edcc372f61bdd4cdec41db50106d809ac129fddf6339247e64f8be4e8'
+
+  # ==> Mailer Configuration
+  # Configure the e-mail address which will be shown in Devise::Mailer,
+  # note that it will be overwritten if you use your own mailer class
+  # with default "from" parameter.
+  config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
+
+  # Configure the class responsible to send e-mails.
+  # config.mailer = 'Devise::Mailer'
+
+  # ==> ORM configuration
+  # Load and configure the ORM. Supports :active_record (default) and
+  # :mongoid (bson_ext recommended) by default. Other ORMs may be
+  # available as additional gems.
+  require 'devise/orm/active_record'
+
+  # ==> Configuration for any authentication mechanism
+  # Configure which keys are used when authenticating a user. The default is
+  # just :email. You can configure it to use [:username, :subdomain], so for
+  # authenticating a user, both parameters are required. Remember that those
+  # parameters are used only when authenticating and not when retrieving from
+  # session. If you need permissions, you should implement that in a before filter.
+  # You can also supply a hash where the value is a boolean determining whether
+  # or not authentication should be aborted when the value is not present.
+  # config.authentication_keys = [:email]
+
+  # Configure parameters from the request object used for authentication. Each entry
+  # given should be a request method and it will automatically be passed to the
+  # find_for_authentication method and considered in your model lookup. For instance,
+  # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
+  # The same considerations mentioned for authentication_keys also apply to request_keys.
+  # config.request_keys = []
+
+  # Configure which authentication keys should be case-insensitive.
+  # These keys will be downcased upon creating or modifying a user and when used
+  # to authenticate or find a user. Default is :email.
+  config.case_insensitive_keys = [:email]
+
+  # Configure which authentication keys should have whitespace stripped.
+  # These keys will have whitespace before and after removed upon creating or
+  # modifying a user and when used to authenticate or find a user. Default is :email.
+  config.strip_whitespace_keys = [:email]
+
+  # Tell if authentication through request.params is enabled. True by default.
+  # It can be set to an array that will enable params authentication only for the
+  # given strategies, for example, `config.params_authenticatable = [:database]` will
+  # enable it only for database (email + password) authentication.
+  # config.params_authenticatable = true
+
+  # Tell if authentication through HTTP Auth is enabled. False by default.
+  # It can be set to an array that will enable http authentication only for the
+  # given strategies, for example, `config.http_authenticatable = [:database]` will
+  # enable it only for database authentication. The supported strategies are:
+  # :database      = Support basic authentication with authentication key + password
+  # config.http_authenticatable = false
+
+  # If 401 status code should be returned for AJAX requests. True by default.
+  # config.http_authenticatable_on_xhr = true
+
+  # The realm used in Http Basic Authentication. 'Application' by default.
+  # config.http_authentication_realm = 'Application'
+
+  # It will change confirmation, password recovery and other workflows
+  # to behave the same regardless if the e-mail provided was right or wrong.
+  # Does not affect registerable.
+  # config.paranoid = true
+
+  # By default Devise will store the user in session. You can skip storage for
+  # particular strategies by setting this option.
+  # Notice that if you are skipping storage for all authentication paths, you
+  # may want to disable generating routes to Devise's sessions controller by
+  # passing skip: :sessions to `devise_for` in your config/routes.rb
+  config.skip_session_storage = [:http_auth]
+
+  # By default, Devise cleans up the CSRF token on authentication to
+  # avoid CSRF token fixation attacks. This means that, when using AJAX
+  # requests for sign in and sign up, you need to get a new CSRF token
+  # from the server. You can disable this option at your own risk.
+  # config.clean_up_csrf_token_on_authentication = true
+
+  # ==> Configuration for :database_authenticatable
+  # For bcrypt, this is the cost for hashing the password and defaults to 10. If
+  # using other encryptors, it sets how many times you want the password re-encrypted.
+  #
+  # Limiting the stretches to just one in testing will increase the performance of
+  # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
+  # a value less than 10 in other environments. Note that, for bcrypt (the default
+  # encryptor), the cost increases exponentially with the number of stretches (e.g.
+  # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
+  config.stretches = Rails.env.test? ? 1 : 10
+
+  # Setup a pepper to generate the encrypted password.
+  # config.pepper = '506a26b387b77fb4a3cdd14ed3267308e2bacaa4888114f3b02aba1fce3d2cbc4b13bd62a8dc3392689cde8c42346ebfb9688a86e9a5f7c5d914cfed977d25b2'
+
+  # Send a notification email when the user's password is changed
+  # config.send_password_change_notification = false
+
+  # ==> Configuration for :confirmable
+  # A period that the user is allowed to access the website even without
+  # confirming their account. For instance, if set to 2.days, the user will be
+  # able to access the website for two days without confirming their account,
+  # access will be blocked just in the third day. Default is 0.days, meaning
+  # the user cannot access the website without confirming their account.
+  # config.allow_unconfirmed_access_for = 2.days
+
+  # A period that the user is allowed to confirm their account before their
+  # token becomes invalid. For example, if set to 3.days, the user can confirm
+  # their account within 3 days after the mail was sent, but on the fourth day
+  # their account can't be confirmed with the token any more.
+  # Default is nil, meaning there is no restriction on how long a user can take
+  # before confirming their account.
+  # config.confirm_within = 3.days
+
+  # If true, requires any email changes to be confirmed (exactly the same way as
+  # initial account confirmation) to be applied. Requires additional unconfirmed_email
+  # db field (see migrations). Until confirmed, new email is stored in
+  # unconfirmed_email column, and copied to email column on successful confirmation.
+  config.reconfirmable = true
+
+  # Defines which key will be used when confirming an account
+  # config.confirmation_keys = [:email]
+
+  # ==> Configuration for :rememberable
+  # The time the user will be remembered without asking for credentials again.
+  # config.remember_for = 2.weeks
+
+  # Invalidates all the remember me tokens when the user signs out.
+  config.expire_all_remember_me_on_sign_out = true
+
+  # If true, extends the user's remember period when remembered via cookie.
+  # config.extend_remember_period = false
+
+  # Options to be passed to the created cookie. For instance, you can set
+  # secure: true in order to force SSL only cookies.
+  # config.rememberable_options = {}
+
+  # ==> Configuration for :validatable
+  # Range for password length.
+  config.password_length = 8..72
+
+  # Email regex used to validate email formats. It simply asserts that
+  # one (and only one) @ exists in the given string. This is mainly
+  # to give user feedback and not to assert the e-mail validity.
+  # config.email_regexp = /\A[^@]+@[^@]+\z/
+
+  # ==> Configuration for :timeoutable
+  # The time you want to timeout the user session without activity. After this
+  # time the user will be asked for credentials again. Default is 30 minutes.
+  # config.timeout_in = 30.minutes
+
+  # ==> Configuration for :lockable
+  # Defines which strategy will be used to lock an account.
+  # :failed_attempts = Locks an account after a number of failed attempts to sign in.
+  # :none            = No lock strategy. You should handle locking by yourself.
+  # config.lock_strategy = :failed_attempts
+
+  # Defines which key will be used when locking and unlocking an account
+  # config.unlock_keys = [:email]
+
+  # Defines which strategy will be used to unlock an account.
+  # :email = Sends an unlock link to the user email
+  # :time  = Re-enables login after a certain amount of time (see :unlock_in below)
+  # :both  = Enables both strategies
+  # :none  = No unlock strategy. You should handle unlocking by yourself.
+  # config.unlock_strategy = :both
+
+  # Number of authentication tries before locking an account if lock_strategy
+  # is failed attempts.
+  # config.maximum_attempts = 20
+
+  # Time interval to unlock the account if :time is enabled as unlock_strategy.
+  # config.unlock_in = 1.hour
+
+  # Warn on the last attempt before the account is locked.
+  # config.last_attempt_warning = true
+
+  # ==> Configuration for :recoverable
+  #
+  # Defines which key will be used when recovering the password for an account
+  # config.reset_password_keys = [:email]
+
+  # Time interval you can reset your password with a reset password key.
+  # Don't put a too small interval or your users won't have the time to
+  # change their passwords.
+  config.reset_password_within = 6.hours
+
+  # When set to false, does not sign a user in automatically after their password is
+  # reset. Defaults to true, so a user is signed in automatically after a reset.
+  # config.sign_in_after_reset_password = true
+
+  # ==> Configuration for :encryptable
+  # Allow you to use another encryption algorithm besides bcrypt (default). You can use
+  # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
+  # :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
+  # and :restful_authentication_sha1 (then you should set stretches to 10, and copy
+  # REST_AUTH_SITE_KEY to pepper).
+  #
+  # Require the `devise-encryptable` gem when using anything other than bcrypt
+  # config.encryptor = :sha512
+
+  # ==> Scopes configuration
+  # Turn scoped views on. Before rendering "sessions/new", it will first check for
+  # "users/sessions/new". It's turned off by default because it's slower if you
+  # are using only default views.
+  # config.scoped_views = false
+
+  # Configure the default scope given to Warden. By default it's the first
+  # devise role declared in your routes (usually :user).
+  # config.default_scope = :user
+
+  # Set this configuration to false if you want /users/sign_out to sign out
+  # only the current scope. By default, Devise signs out all scopes.
+  # config.sign_out_all_scopes = true
+
+  # ==> Navigation configuration
+  # Lists the formats that should be treated as navigational. Formats like
+  # :html, should redirect to the sign in page when the user does not have
+  # access, but formats like :xml or :json, should return 401.
+  #
+  # If you have any extra navigational formats, like :iphone or :mobile, you
+  # should add them to the navigational formats lists.
+  #
+  # The "*/*" below is required to match Internet Explorer requests.
+  # config.navigational_formats = ['*/*', :html]
+
+  # The default HTTP method used to sign out a resource. Default is :delete.
+  config.sign_out_via = :delete
+
+  # ==> OmniAuth
+  # Add a new OmniAuth provider. Check the wiki for more information on setting
+  # up on your models and hooks.
+  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
+
+  # ==> Warden configuration
+  # If you want to use other strategies, that are not supported by Devise, or
+  # change the failure app, you can configure them inside the config.warden block.
+  #
+  # config.warden do |manager|
+  #   manager.intercept_401 = false
+  #   manager.default_strategies(scope: :user).unshift :some_external_strategy
+  # end
+
+  # ==> Mountable engine configurations
+  # When using Devise inside an engine, let's call it `MyEngine`, and this engine
+  # is mountable, there are some extra configurations to be taken into account.
+  # The following options are available, assuming the engine is mounted as:
+  #
+  #     mount MyEngine, at: '/my_engine'
+  #
+  # The router that invoked `devise_for`, in the example above, would be:
+  # config.router_name = :my_engine
+  #
+  # When using OmniAuth, Devise cannot automatically set OmniAuth path,
+  # so you need to do it manually. For the users scope, it would be:
+  # config.omniauth_path_prefix = '/my_engine/users/auth'
+end

+ 15 - 0
config/initializers/inflections.rb

@@ -0,0 +1,15 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# ActiveSupport::Inflector.inflections do |inflect|
+#   inflect.plural /^(ox)$/i, '\1en'
+#   inflect.singular /^(ox)en/i, '\1'
+#   inflect.irregular 'person', 'people'
+#   inflect.uncountable %w( fish sheep )
+# end
+#
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections do |inflect|
+#   inflect.acronym 'RESTful'
+# end

+ 1 - 0
config/initializers/load_config.rb

@@ -0,0 +1 @@
+CONFIG_FILE = YAML.load_file("#{Rails.root}/config/config.yml")[Rails.env]

+ 0 - 0
config/initializers/mime_types.rb


Some files were not shown because too many files changed in this diff