├── .gitignore ├── .ruby-version ├── Capfile ├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ └── application.js │ └── stylesheets │ │ └── application.scss ├── controllers │ ├── admin │ │ ├── activities_controller.rb │ │ ├── base_controller.rb │ │ ├── crop_users_controller.rb │ │ ├── dash_boards_controller.rb │ │ ├── logins_controller.rb │ │ ├── pages_controller.rb │ │ ├── pay_configs_controller.rb │ │ ├── public_accounts_controller.rb │ │ ├── reminds_controller.rb │ │ ├── ticket_orders_controller.rb │ │ ├── users_controller.rb │ │ └── virtual_goods_controller.rb │ ├── application_controller.rb │ ├── concerns │ │ └── .keep │ ├── delivery_infos_controller.rb │ ├── orders_controller.rb │ ├── pages_controller.rb │ ├── payments_controller.rb │ ├── storages_controller.rb │ ├── types_controller.rb │ └── wechats_controller.rb ├── helpers │ └── application_helper.rb ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── account_button.rb │ ├── activity.rb │ ├── article_type.rb │ ├── company.rb │ ├── concerns │ │ ├── .keep │ │ ├── activitiable.rb │ │ ├── activity_constant.rb │ │ ├── auth_token.rb │ │ ├── error_const.rb │ │ ├── errorable.rb │ │ ├── userable.rb │ │ └── wechatable.rb │ ├── crm │ │ ├── delivery_info.rb │ │ └── remind.rb │ ├── crop_user.rb │ ├── event.rb │ ├── goods │ │ ├── goods.rb │ │ └── virtual_goods.rb │ ├── goods_flash.rb │ ├── media_resource.rb │ ├── page.rb │ ├── public_account.rb │ ├── trades │ │ ├── goods_order.rb │ │ ├── order.rb │ │ ├── payment.rb │ │ ├── ticket_order.rb │ │ ├── wxpub_pay_config.rb │ │ └── wxpub_payment.rb │ └── user.rb ├── services │ ├── storage_service.rb │ ├── wechat_service.rb │ └── wxpub_payment_service.rb ├── views │ ├── admin │ │ ├── activities │ │ │ ├── _activity.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ └── new.html.erb │ │ ├── crop_users │ │ │ └── show.html.erb │ │ ├── dash_boards │ │ │ └── index.html.erb │ │ ├── logins │ │ │ └── index.html.erb │ │ ├── pages │ │ │ ├── _page.html.erb │ │ │ ├── account_pages.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ └── new.html.erb │ │ ├── pay_configs │ │ │ ├── _wxpub_form.html.erb │ │ │ ├── edit_wxpub_pay_config.html.erb │ │ │ ├── new_wxpub_pay_config.html.erb │ │ │ └── wechat_list.html.erb │ │ ├── public_accounts │ │ │ ├── _account.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ └── new.html.erb │ │ ├── ticket_orders │ │ │ ├── _ticket.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ └── new.html.erb │ │ ├── users │ │ │ └── index.html.erb │ │ └── virtual_goods │ │ │ ├── _virtual_goods.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ ├── new.html.erb │ │ │ └── show.html.erb │ ├── layouts │ │ ├── admin.html.erb │ │ └── application.html.erb │ ├── pages │ │ └── article.html.erb │ └── types │ │ └── show.html.erb └── workers │ ├── activity_join_worker.rb │ ├── join_activity_worker.rb │ └── send_wechat_message_worker.rb ├── bin ├── bundle ├── rails ├── rake └── setup ├── config.ru ├── config ├── application.rb ├── boot.rb ├── config.yml ├── database.yml ├── deploy.rb ├── deploy │ └── production.rb ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── auto_load_activities.rb │ ├── backtrace_silencers.rb │ ├── config.rb │ ├── cookies_serializer.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── kaminary.rb │ ├── mime_types.rb │ ├── qiniu.rb │ ├── redis.rb │ ├── session_store.rb │ ├── sidekiq.rb │ ├── simple_form.rb │ └── wrap_parameters.rb ├── locales │ ├── en.yml │ └── simple_form.en.yml ├── routes.rb ├── routes │ ├── admin.rb │ └── weixin.rb ├── schedule.rb ├── secrets.yml ├── sidekiq.yml └── wechat.yml ├── db ├── migrate │ ├── 20180317110326_create_crop_users.rb │ ├── 20180317110637_create_companys.rb │ ├── 20180317114644_create_public_accounts.rb │ ├── 20180317115226_create_events.rb │ ├── 20180317115550_create_activities.rb │ ├── 20180317120003_create_users.rb │ ├── 20180317120110_create_join_table_activity_user.rb │ ├── 20180405073440_create_pages.rb │ ├── 20180414104327_create_article_types.rb │ ├── 20180414120123_create_media_resources.rb │ ├── 20180415100503_add_menu_to_public_account.rb │ ├── 20180415100611_add_event_key_to_public_account.rb │ ├── 20180427160606_change_user_nickname_limit.rb │ ├── 20180503105812_change_user_column.rb │ ├── 20180505154123_create_wxpub_pay_config.rb │ ├── 20180505161029_add_timestamps_to_wxpub_pay_configs.rb │ ├── 20180506112053_create_orders.rb │ ├── 20180506113942_create_payment.rb │ ├── 20180506123258_add_payment_detail_to_payments.rb │ ├── 20180506130317_add_payment_no_to_payments.rb │ ├── 20180507144603_add_title_to_orders.rb │ ├── 20180507172555_change_order_attr_type.rb │ ├── 20180508143853_add_slug_to_public_account.rb │ ├── 20180509162937_add_pay_res_id_to_payments.rb │ ├── 20180510103721_create_goods.rb │ ├── 20180510105746_create_goods_flash.rb │ ├── 20180510151913_add_type_to_goods.rb │ ├── 20180528025128_create_reminds.rb │ └── 20180529071311_create_delivery_info.rb ├── schema.rb └── seeds.rb ├── img └── 1.jpg ├── lib ├── activities │ ├── .store │ ├── 1_2.rb │ ├── 2_2.rb │ └── 2_5.rb ├── assets │ └── .keep ├── tasks │ └── .keep └── templates │ └── erb │ └── scaffold │ └── _form.html.erb ├── package-lock.json ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico ├── robots.txt ├── static │ ├── css │ │ └── app.517a6594b965f629600861007174f753.css │ ├── fonts │ │ ├── element-icons.27c7209.ttf │ │ ├── element-icons.6f0a763.ttf │ │ ├── fontawesome-webfont.674f50d.eot │ │ ├── fontawesome-webfont.af7ae50.woff2 │ │ ├── fontawesome-webfont.b06871f.ttf │ │ └── fontawesome-webfont.fee66e7.woff │ ├── img │ │ ├── 401.089007e.gif │ │ ├── 404.a57b6f3.png │ │ └── fontawesome-webfont.912ec66.svg │ ├── js │ │ ├── 0.33171700c0b1ab76fe07.js │ │ ├── 1.5c8320e98796bd885b19.js │ │ ├── 10.19f36bdadea022ab4862.js │ │ ├── 11.d17382e46509f063847d.js │ │ ├── 12.586a09bd1790df1cf9e1.js │ │ ├── 13.907400c683de4e670994.js │ │ ├── 14.7a8129e7193ce857278e.js │ │ ├── 15.117085614b5d7d485982.js │ │ ├── 16.5edaa3b1d46d6ea6e4e1.js │ │ ├── 17.c524fca676d71e65e040.js │ │ ├── 18.e9397ef0e4fcd641c3ef.js │ │ ├── 19.d44f139d3086f809fa46.js │ │ ├── 2.6e9f392889d39a40afcc.js │ │ ├── 20.1b1ef5b605cd82b469de.js │ │ ├── 21.2368dfc1d33e262626a7.js │ │ ├── 22.2aa52c087fa5e316e88f.js │ │ ├── 23.780255a1bd01070c0a33.js │ │ ├── 24.c891137dde403544b385.js │ │ ├── 25.c4fa26fdb1662ee7f139.js │ │ ├── 26.5b5ff59b18376fe1de73.js │ │ ├── 27.26694b0425b3ba2a31f5.js │ │ ├── 28.ae5b41d7ed5dbffbfd84.js │ │ ├── 29.5ccdd1b145bc5156f91b.js │ │ ├── 3.9caf5b5a886184faf83c.js │ │ ├── 30.32d72c80009005b8c0c2.js │ │ ├── 31.083409a324e4f31da9ad.js │ │ ├── 32.0438da92f8b0246edd6d.js │ │ ├── 33.92da0ab56c84e0a85611.js │ │ ├── 34.ec5f53056ffff3d9f9f3.js │ │ ├── 35.13da4951f1e67e60119a.js │ │ ├── 36.4ecdee19981744124b10.js │ │ ├── 37.3fedb74047a770badf1a.js │ │ ├── 38.63f17f7481508d3464f4.js │ │ ├── 39.ee6ce5803307ff5cbed7.js │ │ ├── 4.1a9e8b76e0e498b8d587.js │ │ ├── 40.435821d1ada54869971e.js │ │ ├── 41.6c5429798933a5e742bd.js │ │ ├── 42.aad19d829f1525196a06.js │ │ ├── 43.f681da8d65449515125f.js │ │ ├── 44.a6f9c496b2cd6151bab9.js │ │ ├── 45.909fae5661195bb66539.js │ │ ├── 46.73c0807083516474f1a4.js │ │ ├── 47.ab57a2ae83266d3bdbca.js │ │ ├── 48.0580e34abd87ee02a658.js │ │ ├── 49.8468d7d0e0431d39f0c4.js │ │ ├── 5.7156aab3cc7257207d70.js │ │ ├── 50.523e1fc86e72c1f11582.js │ │ ├── 51.b1e224295159fb12b66c.js │ │ ├── 52.ca61fc721e5420181995.js │ │ ├── 53.1609bd4f497ec249dce1.js │ │ ├── 54.50b3bb605bc81a107ccc.js │ │ ├── 55.b35c7faec6edb3d3f0f2.js │ │ ├── 56.e1c6e0bb1c5348cdf8d5.js │ │ ├── 57.309813805e444a862bb5.js │ │ ├── 58.3b57dcecdda7f3784325.js │ │ ├── 59.1513bd1147b53441889f.js │ │ ├── 6.4e8feba37cdf4a21532f.js │ │ ├── 60.4da6604318400d2cdc0c.js │ │ ├── 63.3de27a9919f59586c018.js │ │ ├── 64.b40d68abf2beb4008c1d.js │ │ ├── 65.ed8ae6e52e9e7b2490e8.js │ │ ├── 7.ac444c931247457a03c0.js │ │ ├── 8.4b0c7926f413529f581c.js │ │ ├── 9.e15691377ae4e4e888a5.js │ │ ├── app.cfee61c859c27ac62c74.js │ │ ├── manifest.b6fcd46717a62f0ca049.js │ │ └── vendor.17e19fb408469245774d.js │ └── tinymce4.7.5 │ │ ├── langs │ │ └── zh_CN.js │ │ ├── plugins │ │ ├── codesample │ │ │ └── css │ │ │ │ └── prism.css │ │ ├── emoticons │ │ │ └── img │ │ │ │ ├── smiley-cool.gif │ │ │ │ ├── smiley-cry.gif │ │ │ │ ├── smiley-embarassed.gif │ │ │ │ ├── smiley-foot-in-mouth.gif │ │ │ │ ├── smiley-frown.gif │ │ │ │ ├── smiley-innocent.gif │ │ │ │ ├── smiley-kiss.gif │ │ │ │ ├── smiley-laughing.gif │ │ │ │ ├── smiley-money-mouth.gif │ │ │ │ ├── smiley-sealed.gif │ │ │ │ ├── smiley-smile.gif │ │ │ │ ├── smiley-surprised.gif │ │ │ │ ├── smiley-tongue-out.gif │ │ │ │ ├── smiley-undecided.gif │ │ │ │ ├── smiley-wink.gif │ │ │ │ └── smiley-yell.gif │ │ └── visualblocks │ │ │ └── css │ │ │ └── visualblocks.css │ │ ├── skins │ │ └── lightgray │ │ │ ├── content.inline.min.css │ │ │ ├── content.min.css │ │ │ ├── fonts │ │ │ ├── tinymce-mobile.woff │ │ │ ├── tinymce-small.eot │ │ │ ├── tinymce-small.svg │ │ │ ├── tinymce-small.ttf │ │ │ ├── tinymce-small.woff │ │ │ ├── tinymce.eot │ │ │ ├── tinymce.svg │ │ │ ├── tinymce.ttf │ │ │ └── tinymce.woff │ │ │ ├── img │ │ │ ├── anchor.gif │ │ │ ├── loader.gif │ │ │ ├── object.gif │ │ │ └── trans.gif │ │ │ ├── skin.min.css │ │ │ └── skin.min.css.map │ │ └── tinymce.min.js └── upload │ ├── invite_4_1.png │ ├── invite_4_11.png │ ├── invite_4_12.png │ ├── invite_4_13.png │ ├── invite_4_14.png │ ├── invite_4_15.png │ ├── invite_4_2.png │ ├── invite_4_4.png │ ├── invite_4_6.png │ └── invite_4_8.png ├── test ├── controllers │ ├── .keep │ └── admin │ │ ├── logins_controller_test.rb │ │ └── public_accounts_controller_test.rb ├── factories │ ├── activities.rb │ ├── article_types.rb │ ├── companies.rb │ ├── crop_users.rb │ ├── events.rb │ ├── media_resources.rb │ ├── public_accounts.rb │ └── users.rb ├── fixtures │ └── .keep ├── helpers │ └── .keep ├── integration │ └── .keep ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── activity_test.rb │ ├── article_type_test.rb │ ├── event_test.rb │ ├── media_resource_test.rb │ ├── public_account_test.rb │ └── user_test.rb └── test_helper.rb └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | .DS_Store 8 | dump.rdb 9 | capybara-*.html 10 | frontend/node_modules 11 | *.rbc 12 | *.sassc 13 | *.swp 14 | /.idea 15 | /.bundle 16 | /vendor/bundle 17 | /log/* 18 | /tmp/* 19 | /db/*.sqlite3 20 | /db/exports/ 21 | /db/tmp/* 22 | /public/assets 23 | /public/upload 24 | /public/uploads 25 | /spec/tmp/* 26 | **.orig 27 | tags 28 | rerun.txt 29 | pickle-email-*.html 30 | /.tags 31 | /.tags_sorted_by_file 32 | /.yardoc 33 | /deploy*.sh 34 | /config/keys 35 | /vendor/cache 36 | .ruby-gemset 37 | one.iml 38 | railways.cache 39 | /public/uploads/* 40 | *.un~ 41 | photos 42 | .byebug_history 43 | /coverage 44 | /activities/* 45 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.3.0 -------------------------------------------------------------------------------- /Capfile: -------------------------------------------------------------------------------- 1 | # Load DSL and Setup Up Stages 2 | require 'capistrano/setup' 3 | 4 | # Includes default deployment tasks 5 | require 'capistrano/deploy' 6 | 7 | # Includes tasks from other gems included in your Gemfile 8 | # 9 | # For documentation on these, see for example: 10 | # 11 | # https://github.com/capistrano/rvm 12 | # https://github.com/capistrano/rbenv 13 | # https://github.com/capistrano/chruby 14 | # https://github.com/capistrano/bundler 15 | # https://github.com/capistrano/rails 16 | # 17 | require 'capistrano/rvm' 18 | 19 | # require 'capistrano/rbenv' 20 | # require 'capistrano/chruby' 21 | require 'capistrano/bundler' 22 | require 'capistrano/rails/assets' 23 | 24 | require 'capistrano/rails/migrations' unless ENV['disable_db'] == '1' 25 | 26 | require 'capistrano/sidekiq' 27 | require 'capistrano/puma' 28 | 29 | require 'whenever/capistrano' unless ENV['disable_db'] == '1' 30 | 31 | 32 | # Loads custom tasks from `lib/capistrano/tasks' if you have any defined. 33 | Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } 34 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://gems.ruby-china.org' 2 | 3 | 4 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 5 | gem 'rails', '4.2.10' 6 | 7 | gem 'jquery-rails' 8 | # Use mysql as the database for Active Record 9 | gem 'mysql2', '>= 0.3.13', '< 0.5' 10 | # Use SCSS for stylesheets 11 | gem 'sass-rails', '~> 5.0' 12 | # Use Uglifier as compressor for JavaScript assets 13 | gem 'uglifier', '>= 1.3.0' 14 | 15 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 16 | gem 'jbuilder', '~> 2.0' 17 | gem 'bcrypt', '~> 3.1.7' 18 | 19 | gem 'mini_magick' 20 | 21 | gem "select2-rails" 22 | 23 | gem 'jwt' 24 | 25 | gem 'will_paginate' 26 | 27 | gem 'rack-cors', :require => 'rack/cors' 28 | 29 | # using puma as default server 30 | gem 'puma' 31 | 32 | # pagination 33 | gem 'kaminari' 34 | 35 | gem 'sinatra', require: false 36 | 37 | gem 'whenever' 38 | 39 | # for background job schedule 40 | gem 'sidekiq', '>= 5' 41 | 42 | # for cache 43 | gem 'redis' 44 | 45 | 46 | gem 'redis-namespace' 47 | 48 | # for file upload 49 | gem 'carrierwave' 50 | 51 | gem 'qiniu', '>= 6.9.0' 52 | 53 | # for http api call 54 | gem 'httparty' 55 | 56 | # for wechat endpoint 57 | gem 'wechat' 58 | 59 | gem 'alipay' 60 | gem 'wx_pay', '~> 0.17.0' 61 | 62 | gem 'simple_form' 63 | 64 | 65 | group :development, :test do 66 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 67 | gem 'byebug' 68 | gem 'test_after_commit' 69 | gem 'pry-rails' 70 | gem 'pry-stack_explorer' 71 | gem 'mocha', '~> 0.14.0', require: false 72 | gem 'factory_girl_rails', '~> 4.5.0' 73 | gem 'minitest-reporters' 74 | gem 'faker' 75 | gem 'better_errors' 76 | gem 'binding_of_caller' 77 | gem 'simplecov', require: false, group: :test 78 | end 79 | 80 | group :development do 81 | gem 'capistrano-bundler', require: false 82 | gem 'capistrano', '3.5.0', require: false 83 | gem 'capistrano-rails', '1.1.3' 84 | gem 'capistrano-rvm', require: false 85 | gem 'capistrano-sidekiq', require: false 86 | gem 'capistrano3-puma' 87 | gem 'annotate', '>=2.5.0' 88 | gem 'spring' 89 | gem 'web-console' 90 | gem 'pry-byebug' 91 | end 92 | 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WEI 微信服务号裂变引擎 2 | 3 | ## 创作初衷: 4 | 微信作为互联网流量生态最重要的一环,承载了大部分创业公司的品牌曝光和营销策略,其中不乏所有产品均围绕微信生态的公司。在下对于营销的理解非常的片面,将其抽象为"借势"和"造势"两个策略, 5 | 而裂变作为营销方法论最重要的一环,无论是借势还是造势,均可以使用裂变的方式拓宽曝光,增加关注。至于变现和转化,不在本项目的讨论范围内便不再赘述。 6 | 7 | 在下为多个创业公司以及自己的公司提供过裂变服务,深知裂变的核心不在于技术手段,而在于如何巧妙设计裂变灵活借势,以及如何使用有吸引力的产品或想法造势,遂决定开源这套引擎。 8 | 9 | ## 核心功能 10 | 11 | * 服务号矩阵管理与动态配置(菜单、appid等基本信息) 12 | * 一套完整裂变DSL(高可配置,能迅速开发出各种裂变方式) 13 | * 高效(跑分双核4G云服务器每秒支撑1.3w + 用户裂变) 14 | * 一套简单的支付网关(可0代码实现支付) 15 | * 大部分前端页面变更不发版 16 | * 快速创建静态页面 17 | 18 | ## 待完成 19 | * 前后端分离(在下不善前端,很渣的那种) 20 | * 完整支付及订单支持 21 | * Docker 镜像 22 | * 文档编写中 23 | 24 | ## 黑科技 25 | * 虽说是服务号裂变引擎,其实订阅号也是稍微配置下可以用的 26 | * 大量使用动态语言eval特性,灵活的同时也带来很多安全隐患,操作不慎一个运营人员就能把后台搞垮。不过也带来更多试错机会和想象力(55开吧) 27 | 28 | ## 示例 29 | 因安全原因,不提供在线demo预览,你可以手工安装到服务器进行测试。 30 | 31 | 请更改database.yml更换default和production的数据库帐密 32 | 33 | > 34 | > git clone 35 | > 36 | > cd wei 37 | > 38 | > bundle install 39 | > 40 | > rake db:create db:migrate 41 | > 42 | > rails s 43 | 44 | ### 依赖: 45 | * Mysql 46 | * redis 47 | * ssdb (你也可以再开一个redis在8888端口替代ssdb) 48 | 49 | ### 一个简单的裂变活动: 50 | 代码: 51 | ```ruby 52 | joined_success '想免费包邮送点好东西 53 | 54 | 一想到初学吉他的时候手割得生疼就想放弃是吧?没关系,尼龙弦了解一下~ 55 | 56 | 活动规则: 57 | 1. 邀请29个微信好友扫码即可免费包邮送。 58 | 2. 好友扫码接力时你会第一时间在公众号收到通知,同时会告知当前你的好友接力数。 59 | 3. 好友扫码接力后如果取消关注,你也会收到相应通知,好友接力数-1。 60 | 61 | 接力成功后,公众号会自动推送发货表单链接给你,填写收货地址后2天内即发货。 62 | 63 | 温馨提示:转发分享卡到朋友圈和群会大大提高活动成功率噢。' 64 | 65 | relaied_success '你已成功接力#{relaied_user&.nickname}~' 66 | 67 | relaied_feedback '你的好友#{user&.nickname}接力了你。当前接力人数:#{relaied_user_supporters.size}' 68 | 69 | activity_success '你已成功完成活动:点此填写收货地址 我们会尽快安排发货。 70 | 嫌麻烦?加我微信 "sidekiq",直接报地址也可以的。' 71 | 72 | def start 73 | if support_success? 74 | say relaied_success 75 | say_to_relaied relaied_feedback if relaied_user 76 | (say_to_relaied activity_success) if relaied_user_supporters.size == 29 77 | end 78 | 79 | say joined_success 80 | 81 | image invite_pic("http://static.njupt.org/activity_10.jpg", [ 82 | (image_query qr_url, 170, 'SouthWest', 60, 60, 0.25) 83 | ]) 84 | end 85 | ``` 86 | 87 | 扫码体验: 88 | ![](img/1.jpg) 89 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require_tree . 14 | //= require 'jquery' 15 | //= require 'jquery_ujs' 16 | //= require select2 17 | -------------------------------------------------------------------------------- /app/controllers/admin/activities_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class ActivitiesController < BaseController 3 | before_action :set_activity, except: [:index, :new, :create] 4 | 5 | def index 6 | @activities = Activity.all 7 | respond_to do |format| 8 | format.json { render json: {code: 200, activities: @activities.map(&:to_api_json)} } 9 | format.html 10 | end 11 | end 12 | 13 | def new 14 | @activity = Activity.new 15 | @accounts = current_user.company.public_accounts.all 16 | end 17 | 18 | def edit 19 | @accounts = current_user.company.public_accounts.all 20 | end 21 | 22 | def create 23 | @activity = Activity.new activity_params 24 | 25 | respond_to do |format| 26 | if @activity.save 27 | format.json { render json: {code: 200} } 28 | format.html { redirect_to admin_activities_path, alert: '创建成功' } 29 | else 30 | errors = @activity.errors.to_a.join '\n' 31 | format.json { render json: {code: 419, error: errors} } 32 | format.html { redirect_to :back, alert: errors } 33 | end 34 | end 35 | end 36 | 37 | def refresh_qr 38 | @activity.refresh_activity_qr 39 | redirect_to :back 40 | end 41 | 42 | def show 43 | render json: {code: 200, activity: @activity.to_api_json} 44 | end 45 | 46 | def destroy 47 | @activity.destroy 48 | respond_to do |format| 49 | format.json { render json: {code: 200} } 50 | format.html { redirect_to :back } 51 | end 52 | end 53 | 54 | def update 55 | if @activity.update_attributes activity_params 56 | respond_to do |format| 57 | format.json { render json: {code: 200} } 58 | format.html { redirect_to :back, flash: {alert: '更新成功'} } 59 | end 60 | else 61 | errors = @activity.errors.to_a.join '\n' 62 | respond_to do |format| 63 | format.json { render json: {code: 419, error: errors} } 64 | format.html { redirect_to :back, flash: {alert: errors} } 65 | end 66 | end 67 | end 68 | 69 | private 70 | 71 | def activity_params 72 | params.require(:activity).permit(:name, :author, :desc, :template, :public_account_id, :event_key) 73 | end 74 | 75 | def set_activity 76 | @activity = Activity.find(params[:id]) 77 | end 78 | end 79 | end -------------------------------------------------------------------------------- /app/controllers/admin/base_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class BaseController < ApplicationController 3 | 4 | layout 'admin' 5 | before_action :allow_cross_domain_access 6 | before_action :cors_preflight_check 7 | after_action :cors_set_access_control_headers 8 | 9 | before_action :current_user 10 | 11 | def allow_cross_domain_access 12 | headers['Access-Control-Allow-Origin'] = '*' 13 | headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS' 14 | headers['Access-Control-Allow-Headers'] = %w{Origin Accept Content-Type X-Requested-With X-CSRF-Token}.join(',') 15 | headers['Access-Control-Max-Age'] = '1728000' 16 | end 17 | 18 | def cors_set_access_control_headers 19 | headers['Access-Control-Allow-Origin'] = '*' 20 | headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS' 21 | headers['Access-Control-Allow-Headers'] = %w{Origin Accept Content-Type X-Requested-With X-CSRF-Token}.join(',') 22 | headers['Access-Control-Max-Age'] = '1728000' 23 | end 24 | 25 | def cors_preflight_check 26 | logger.info "request method: #{request.method}" 27 | if request.method == :options 28 | headers['Access-Control-Allow-Origin'] = '*' 29 | headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, PUT, DELETE' 30 | headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version' 31 | headers['Access-Control-Max-Age'] = '1728000' 32 | render :text => '123', :content_type => 'text/plain' 33 | end 34 | end 35 | 36 | def current_user 37 | @current_user ||= set_current_user 38 | end 39 | 40 | def set_current_user 41 | if session[:user_id] 42 | return CropUser.find session[:user_id] 43 | end 44 | 45 | token = request.headers['Authentication'] 46 | token ||=params[:Authentication] 47 | 48 | # html render result call 49 | respond_to do |format| 50 | format.html { return redirect_to admin_logins_path } 51 | end 52 | 53 | # api call response handle 54 | unless token 55 | render json: {code: 403, error: '请先登陆', bicode: 10001} 56 | end 57 | 58 | unless (user = CropUser.from_token(token)) 59 | return render json: {code: 403, error: '登陆信息已过期', bicode: 10002} 60 | end 61 | user 62 | end 63 | 64 | end 65 | end -------------------------------------------------------------------------------- /app/controllers/admin/crop_users_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class CropUsersController < BaseController 3 | def show 4 | end 5 | 6 | def update 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /app/controllers/admin/dash_boards_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class DashBoardsController < BaseController 3 | def index 4 | logger.info current_user.as_json 5 | end 6 | 7 | def update 8 | 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /app/controllers/admin/logins_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class LoginsController < BaseController 3 | skip_before_action :current_user 4 | layout false 5 | 6 | def index 7 | end 8 | 9 | def create 10 | user = CropUser.find_by_account(params[:account]) 11 | 12 | unless user&.authenticate(params[:password]) 13 | respond_to do |format| 14 | format.html { return redirect_to admin_logins_path, alert: '用户名或密码错误' } 15 | format.json { return render json: {code: 401, error: '用户名或密码错误', bicode: 10003} } 16 | end 17 | end 18 | 19 | respond_to do |format| 20 | format.html do 21 | session[:user_id] = user.id 22 | redirect_to admin_dash_boards_path 23 | end 24 | format.json { render json: {code: 200, user: user.as_json, company: user.company.as_json, authentication: user.token} } 25 | end 26 | end 27 | end 28 | end -------------------------------------------------------------------------------- /app/controllers/admin/pages_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::PagesController < Admin::BaseController 2 | before_action :set_account, only: [:create, :new, :edit, :update, :destroy] 3 | 4 | def index 5 | @accounts = current_user.company.public_accounts 6 | end 7 | 8 | def account_pages 9 | @pages = current_user.company.public_accounts.find(params[:public_account_id]).pages 10 | end 11 | 12 | def create 13 | page = @account.pages.new page_params 14 | if page.save 15 | redirect_to action: :account_pages, alert: '创建成功', public_account_id: @account.id 16 | else 17 | redirect_to :back, alert: "创建失败: #{page.errors.to_a.map(&:to_s).join('\n')}" 18 | end 19 | end 20 | 21 | def new 22 | @account = current_user.company.public_accounts.find(params[:public_account_id]) 23 | @page = @account.pages.new 24 | end 25 | 26 | def edit 27 | @page = @account.pages.find(params[:id]) 28 | end 29 | 30 | def update 31 | @page = @account.pages.find(params[:id]) 32 | if @page.update page_params 33 | redirect_to :back, alert: '更新成功' 34 | else 35 | redirect_to :back, alert: "更新失败: #{@page.errors.to_a.map(&:to_s).join("\n")}" 36 | end 37 | end 38 | 39 | def destroy 40 | @page = @account.pages.find(params[:id]) 41 | @page.destroy 42 | redirect_to :back 43 | end 44 | 45 | private 46 | def set_account 47 | @account = current_user.company.public_accounts.find(params[:public_account_id]) 48 | end 49 | 50 | def page_params 51 | params.require(:page).permit! 52 | end 53 | end -------------------------------------------------------------------------------- /app/controllers/admin/pay_configs_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class PayConfigsController < BaseController 3 | before_action :set_class, except: [:index, :wechat_list] 4 | 5 | def index 6 | redirect_to action: :wechat_list 7 | end 8 | 9 | def wechat_list 10 | @cfgs = WxpubPayConfig.all.order(created_at: :desc) 11 | end 12 | 13 | def new 14 | @cfg = @clazz.new 15 | 16 | render "new_#{params[:type].underscore}" 17 | end 18 | 19 | def show 20 | end 21 | 22 | def create 23 | @cfg = @clazz.new params[params[:type].underscore].permit! 24 | if @cfg.save 25 | redirect_to :back, alert: '创建成功' 26 | else 27 | errors = @cfg.errors.to_a.join '\n' 28 | redirect_to :back, alert: "保存失败:#{errors}" 29 | end 30 | end 31 | 32 | def edit 33 | @cfg = @clazz.find(params[:id]) 34 | 35 | render "edit_#{params[:type].underscore}" 36 | end 37 | 38 | def update 39 | @cfg = @clazz.find(params[:id]) 40 | @cfg.update_attributes params[params[:type].underscore].permit! 41 | 42 | redirect_to :back, alert: '更新成功' 43 | end 44 | 45 | def destroy 46 | @cfg = @clazz.find(params[:id]) 47 | @cfg.destroy 48 | 49 | redirect_to :back 50 | end 51 | 52 | private 53 | 54 | def set_class 55 | @clazz = params[:type].constantize 56 | end 57 | end 58 | end -------------------------------------------------------------------------------- /app/controllers/admin/public_accounts_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | 3 | class PublicAccountsController < BaseController 4 | before_action :set_account, except: [:index, :create, :new] 5 | 6 | def index 7 | @accounts = @current_user.company.public_accounts.order_desc 8 | 9 | respond_to do |format| 10 | format.json {render json: {code: 200, public_accounts: @accounts.map(&:to_api_json) } } 11 | format.html 12 | end 13 | end 14 | 15 | def edit 16 | end 17 | 18 | def new 19 | @account = PublicAccount.new 20 | end 21 | 22 | def show 23 | respond_to do |format| 24 | format.json { render json: {code: 200, account: @account.to_api_json} } 25 | format.html 26 | end 27 | end 28 | 29 | def create 30 | @account = current_user.company.public_accounts.new account_params 31 | 32 | respond_to do |format| 33 | if @account.save 34 | format.json { render json: {code: 200} } 35 | format.html { redirect_to admin_public_accounts_path, alert: '创建成功' } 36 | else 37 | errors = @account.errors.to_a.join '\n' 38 | format.json { render json: {code: 419, error: errors} } 39 | format.html { redirect_to :back, alert: errors } 40 | end 41 | end 42 | end 43 | 44 | def update 45 | updated = @account.update_attributes account_params 46 | logger.info "result: #{@account.update_account_button}" 47 | 48 | respond_to do |format| 49 | if updated 50 | format.json { render json: {code: 200} } 51 | format.html { redirect_to :back, alert: '更新成功' } 52 | else 53 | errors = @account.errors.to_a.join "\n" 54 | format.json { render json: {code: 419, error: errors} } 55 | format.html { redirect_to :back, alert: errors } 56 | end 57 | end 58 | 59 | end 60 | 61 | def destroy 62 | @account.destroy 63 | 64 | respond_to do |format| 65 | format.json { render json: {code: 200}} 66 | format.html { redirect_to admin_public_accounts_path } 67 | end 68 | end 69 | 70 | private 71 | 72 | def set_account 73 | @account = PublicAccount.find(params[:id]) 74 | raise PermissionError unless @account.company_id == current_user.company_id 75 | end 76 | 77 | def account_params 78 | params.require(:public_account).permit(:name, :account, :appid, :appsecret, :menu_json, :slug) 79 | end 80 | 81 | end 82 | end -------------------------------------------------------------------------------- /app/controllers/admin/reminds_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::RemindsController < Admin::BaseController 2 | def index 3 | 4 | end 5 | end -------------------------------------------------------------------------------- /app/controllers/admin/ticket_orders_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class TicketOrdersController < BaseController 3 | before_action :set_order, except: [:index, :new, :create] 4 | 5 | def index 6 | @orders = TicketOrder.all.order(id: :desc) 7 | end 8 | 9 | def show 10 | redirect_to "/pages/ticket?oid=#{@order.order_no}" 11 | end 12 | 13 | def new 14 | @order = TicketOrder.new 15 | end 16 | 17 | def create 18 | @order = TicketOrder.new(params[:ticket_order].permit!) 19 | 20 | if @order.save 21 | redirect_to action: :index, alert: '创建成功' 22 | else 23 | redirect_to :back, alert: "创建失败: #{@order.errors.to_a.join '\n'}" 24 | end 25 | end 26 | 27 | def update 28 | if @order.update_attributes params[:ticket_order].permit! 29 | redirect_to :back, alert: '修改成功' 30 | else 31 | redirect_to :back, alert: "创建失败: #{@order.errors.to_a.join '\n'}" 32 | end 33 | end 34 | 35 | def destroy 36 | @order.destroy 37 | 38 | redirect_to :back 39 | end 40 | 41 | private 42 | 43 | def set_order 44 | @order = TicketOrder.find(params[:id]) 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /app/controllers/admin/users_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class UsersController < BaseController 3 | before_action :set_account 4 | def index 5 | @users = @account.users.order(created_at: :desc).paginate(page: params[:page], per_page: 20) 6 | end 7 | 8 | private 9 | 10 | def set_account 11 | @account = current_user.company.public_accounts.find(params[:public_account_id]) 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /app/controllers/admin/virtual_goods_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class VirtualGoodsController < BaseController 3 | before_action :set_goods, except: [:index, :new, :create] 4 | 5 | def index 6 | @goods = VirtualGoods.all.order(created_at: :desc) 7 | end 8 | 9 | def new 10 | @goods = VirtualGoods.new 11 | end 12 | 13 | def create 14 | goods = VirtualGoods.new params[:goods].permit! 15 | 16 | if goods.save 17 | redirect_to action: :index, alert: '成功创建虚拟商品' 18 | else 19 | redirect_to :back, alert: "创建失败:#{@account.errors.to_a.join '\n'}" 20 | end 21 | end 22 | 23 | def show 24 | end 25 | 26 | def update 27 | if @goods.update_attributes params[:goods] 28 | redirect_to :back, alert: '更新成功' 29 | else 30 | redirect_to :back, alert: "更新失败:#{@account.errors.to_a.join '\n'}" 31 | end 32 | end 33 | 34 | def destroy 35 | @goods.destroy 36 | 37 | redirect_to :back 38 | end 39 | 40 | 41 | private 42 | 43 | def set_goods 44 | @goods = VirtualGoods.find(params[:id]) 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | 5 | class Admin::PermissionError < StandardError; end 6 | 7 | rescue_from Admin::PermissionError do 8 | render json: {code: 401, error: '你无权进行这个操作', bicode: 10004} 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/delivery_infos_controller.rb: -------------------------------------------------------------------------------- 1 | class DeliveryInfosController < ApplicationController 2 | before_action :set_user 3 | 4 | def create 5 | info = @current_user.delivery_infos.mine(params[:activity_id]).first 6 | if info 7 | info.update delivery_info_params 8 | else 9 | info = DeliveryInfo.create_from(params[:activity_id], @current_user.id, delivery_info_params) 10 | end 11 | render json: {code: 200, info: info.to_api_json} 12 | end 13 | 14 | private 15 | def set_user 16 | @current_user = User.find_by_openid params[:openid] 17 | end 18 | 19 | def delivery_info_params 20 | params.require(:delivery_info).permit(:province, :city, :street, :name, :phone) 21 | end 22 | end -------------------------------------------------------------------------------- /app/controllers/orders_controller.rb: -------------------------------------------------------------------------------- 1 | class OrdersController < ApplicationController 2 | def show 3 | @order = Order.find_by_order_no(params[:order_no]) 4 | 5 | render json: {code: 200, order: @order.to_api_json} 6 | end 7 | 8 | def create 9 | @goods = Goods.find(params[:goods_id]) 10 | @order = Order.generate_new order_params.merge( 11 | user_id: current_user.id, 12 | title: "#{@goods.title}-#{current_user.nickname}" 13 | ) 14 | 15 | if @order.save 16 | render json: {code: 200, order: @order.to_api_json} 17 | else 18 | render json: {code: 419, error: (@order.errors.to_a.join '\n')} 19 | end 20 | end 21 | 22 | private 23 | 24 | def order_params 25 | params[:order].permit(:real_name, :phone, :address, :note) 26 | end 27 | end -------------------------------------------------------------------------------- /app/controllers/pages_controller.rb: -------------------------------------------------------------------------------- 1 | class PagesController < ApplicationController 2 | def show 3 | @page = Page.find_by_code params[:code] 4 | @params = params 5 | @controller = self 6 | @request = request 7 | 8 | if @page.page_type == 'raw' 9 | render inline: @page.content, type: :rhtml 10 | else 11 | render :article, layout: false 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /app/controllers/payments_controller.rb: -------------------------------------------------------------------------------- 1 | class PaymentsController < ApplicationController 2 | def create 3 | order = Order.find(params[:order_id]) 4 | payment = WxpubPaymentService.instance.pay params[:pay_config], params[:openid], order 5 | render json: {code: 200, payment: payment.to_api_json} 6 | end 7 | 8 | def wx_notify 9 | logger.info "params: #{params}" 10 | notify_params = params_transform 11 | 12 | payment = Payment.find_by(payment_no: notify_params[:out_trade_no]) 13 | payment.pay! if payment.notify_verify? notify_params 14 | render text: 'ok' 15 | end 16 | 17 | private 18 | 19 | def params_transform 20 | raw_data = request.body.read 21 | notify_params = HashWithIndifferentAccess.new(Hash.from_xml(raw_data)['xml']) 22 | payment = Payment.find_by payment_no: notify_params[:out_trade_no] 23 | notify_params[:key] = WxpubPayConfig.find(payment.pay_res_id).key 24 | notify_params 25 | end 26 | end -------------------------------------------------------------------------------- /app/controllers/storages_controller.rb: -------------------------------------------------------------------------------- 1 | class StoragesController < ApplicationController 2 | 3 | # 保存一个字符串 4 | def create 5 | StorageService.instance.set(params[:key], params[:value], params[:expire]) 6 | render json: {code: 200, key: params[:key]} 7 | end 8 | 9 | def append 10 | StorageService.instance.append(params[:key], params[:value], params[:expire]) 11 | render json: {code: 200, key: params[:key]} 12 | end 13 | 14 | # 获取一个字符串 15 | def show 16 | render json: {code: 200, data: StorageService.instance.get(params[:key])} 17 | end 18 | end -------------------------------------------------------------------------------- /app/controllers/types_controller.rb: -------------------------------------------------------------------------------- 1 | class TypesController < ApplicationController 2 | def show 3 | @type = ArticleType.find_by_code params[:code] 4 | end 5 | end -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | 3 | def panel_menu 4 | self.try "#{controller_name}_menu" 5 | end 6 | 7 | def dash_boards_menu 8 | end 9 | 10 | def activities_menu 11 | [ 12 | (link_to '活动列表', admin_activities_path), 13 | (link_to '新建活动', new_admin_activity_path) 14 | ] 15 | end 16 | 17 | def public_accounts_menu 18 | [ 19 | (link_to '公众号列表', admin_public_accounts_path), 20 | (link_to '绑定公众号', new_admin_public_account_path) 21 | ] 22 | end 23 | 24 | def pages_menu 25 | [ 26 | (link_to '公众号列表', admin_pages_path) 27 | ] 28 | end 29 | 30 | def crop_users_menu 31 | 32 | end 33 | 34 | def pay_configs_menu 35 | [ 36 | (link_to '公众号支付', wechat_list_admin_pay_configs_path) 37 | ] 38 | end 39 | 40 | def ticket_orders_menu 41 | [ 42 | (link_to '支付单列表', admin_ticket_orders_path), 43 | (link_to '新建支付单', new_admin_ticket_order_path) 44 | ] 45 | end 46 | 47 | def virtual_goods_menu 48 | [ 49 | (link_to '虚拟商品列表', admin_virtual_goods_path), 50 | (link_to '新建虚拟商品', new_admin_virtual_good_path) 51 | ] 52 | end 53 | 54 | end 55 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/app/mailers/.keep -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/app/models/.keep -------------------------------------------------------------------------------- /app/models/account_button.rb: -------------------------------------------------------------------------------- 1 | class AccountButton < ActiveRecord::Base 2 | belongs_to :public_account 3 | 4 | # 创建自定义菜单 5 | # 详细文档请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013 6 | def update_account_button 7 | WechatService.instance.account_api(self.public_account).menu_create(JSON.parse(self.button_json)) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/models/activity.rb: -------------------------------------------------------------------------------- 1 | class Activity < ActiveRecord::Base 2 | TICKET_BASE = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' 3 | QINIU_BASE = 'http://searchnerd.qiniudn.com/' 4 | 5 | after_commit { Rails.cache.delete Activity.cache_key(self.id) } 6 | 7 | belongs_to :public_account 8 | has_many :delivery_infos 9 | has_and_belongs_to_many :users 10 | 11 | after_commit :refresh_template, on: [:create, :update] 12 | 13 | validates_presence_of :name, :public_account_id 14 | 15 | def refresh_template 16 | File.open(filename, 'w') {|f| f.write prepare_template} 17 | $redis.set "need_reload:#{self.id}", 1 18 | load_activity 19 | end 20 | 21 | def refresh_activity_qr 22 | api = WechatService.instance.account_api public_account 23 | ticket = (api.qrcode_create_limit_scene "base_#{self.id}")['ticket'] 24 | puts ticket 25 | update qrurl: "#{TICKET_BASE}#{ticket}" 26 | end 27 | 28 | def to_api_json 29 | { 30 | id: id, 31 | name: name, 32 | author: author, 33 | desc: desc, 34 | consts: consts, 35 | template: template, 36 | qrurl: qrurl, 37 | created_at: created_at.strftime("%Y-%m-%d"), 38 | public_account: { 39 | id: public_account_id, 40 | name: public_account.name 41 | } 42 | } 43 | end 44 | 45 | def prepare_class_name 46 | "Activity#{id}" 47 | end 48 | 49 | def load_activity 50 | load filename 51 | end 52 | 53 | def self.fetch(id) 54 | Rails.cache.fetch(cache_key(id)) { self.find(id) } 55 | end 56 | 57 | def self.cache_key(id) 58 | "activity:#{id}" 59 | end 60 | 61 | private 62 | 63 | def prepare_template 64 | < (activity_id) { where(activity_id: activity_id) } 5 | 6 | def self.create_from(activity_id, user_id, options={}) 7 | self.create options.merge({ 8 | user_id: user_id, 9 | activity_id: activity_id 10 | }) 11 | end 12 | 13 | def to_api_json 14 | { 15 | province: province, 16 | city: city, 17 | street: street, 18 | name: name, 19 | phone: phone, 20 | 21 | activity_id: activity_id 22 | } 23 | end 24 | end -------------------------------------------------------------------------------- /app/models/crm/remind.rb: -------------------------------------------------------------------------------- 1 | class Remind < ActiveRecord::Base 2 | enum state: [:initialized, :done] 3 | 4 | validates_uniqueness_of :title, message: '提醒事项标题不能重复' 5 | 6 | 7 | 8 | end -------------------------------------------------------------------------------- /app/models/crop_user.rb: -------------------------------------------------------------------------------- 1 | class CropUser < ActiveRecord::Base 2 | include AuthToken 3 | 4 | belongs_to :company 5 | 6 | validates_presence_of :account, :password_digest, :phone, message: '基本信息必须填写' 7 | 8 | has_secure_password 9 | 10 | end -------------------------------------------------------------------------------- /app/models/event.rb: -------------------------------------------------------------------------------- 1 | class Event < ActiveRecord::Base 2 | validates_presence_of :event_type, :action_type 3 | 4 | belongs_to :public_account 5 | end 6 | -------------------------------------------------------------------------------- /app/models/goods/goods.rb: -------------------------------------------------------------------------------- 1 | class Goods < ActiveRecord::Base 2 | # initial: "未发布" 3 | # on_sale: "已上架" 4 | # not_sale: "补货中" 5 | # stop_sale: "已售罄下架" 6 | enum state: [:initial, :on_sale, :not_sale, :stop_sale] 7 | 8 | has_many :goods_flashes 9 | 10 | alias_method :flash, :as_json 11 | end -------------------------------------------------------------------------------- /app/models/goods/virtual_goods.rb: -------------------------------------------------------------------------------- 1 | class VirtualGoods < Goods 2 | # 虚拟商品,不需要发货,直接购买即可 3 | end -------------------------------------------------------------------------------- /app/models/goods_flash.rb: -------------------------------------------------------------------------------- 1 | class GoodsFlash < ActiveRecord::Base 2 | 3 | belongs_to :goods 4 | belongs_to :order 5 | 6 | def flash_key 7 | "goods_flash:#{self.id}" 8 | end 9 | 10 | def self.create_flash(goods, order) 11 | flash = GoodsFlash.create goods_id: goods.id, order_id: order.id, price: order.price 12 | flash.save! 13 | pre_content = { 14 | goods: goods.flash, 15 | order: order.flash 16 | } 17 | $ssdb.set(flash.flash_key, pre_content.to_json) 18 | end 19 | end -------------------------------------------------------------------------------- /app/models/media_resource.rb: -------------------------------------------------------------------------------- 1 | class MediaResource < ActiveRecord::Base 2 | 3 | def self.upload(file, name) 4 | # 上传文件 5 | put_policy = Qiniu::Auth::PutPolicy.new('lejita', nil, 3600) 6 | token = Qiniu::Auth.generate_uptoken put_policy 7 | code, result, _ = Qiniu::Storage.upload_with_token_2( 8 | token, 9 | file.path, 10 | nil, 11 | nil, 12 | bucket: 'lejita' 13 | ) 14 | Rails.logger.info "MODEL_EIP: upload result: #{code}, #{result}" 15 | [code, result] 16 | if code == 200 17 | self.create name: name, qiniu_key: result.symbolize_keys[:key] 18 | else 19 | false 20 | end 21 | end 22 | 23 | def qiniu_url 24 | "http://static.njupt.org/#{self.key}" 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/models/page.rb: -------------------------------------------------------------------------------- 1 | class Page < ActiveRecord::Base 2 | 3 | validates_presence_of :title, :code, :content 4 | 5 | # page_type: 6 | # raw: 存html渲染 7 | # article: 使用文章模版渲染 8 | validates_inclusion_of :page_type, in: %w(raw article) 9 | 10 | belongs_to :public_account 11 | belongs_to :article_type 12 | 13 | 14 | end -------------------------------------------------------------------------------- /app/models/public_account.rb: -------------------------------------------------------------------------------- 1 | class PublicAccount < ActiveRecord::Base 2 | 3 | after_commit do 4 | Rails.cache.delete PublicAccount.cache_key(self.id) 5 | Rails.cache.delete PublicAccount.cache_key(self.name) 6 | Rails.cache.delete PublicAccount.cache_key(self.slug) 7 | end 8 | 9 | scope :order_desc ,->{ order(id: :desc) } 10 | 11 | has_many :users 12 | has_many :activities, dependent: :destroy 13 | has_one :account_button, dependent: :destroy 14 | has_many :pages 15 | belongs_to :company 16 | 17 | # 创建自定义菜单 18 | # 详细文档请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013 19 | def update_account_button 20 | Rails.logger.info "update_account_button" 21 | WechatService.instance.account_api(self).menu_create(JSON.parse(self.menu_json)) 22 | end 23 | 24 | def to_api_json 25 | { 26 | id: id, 27 | name: name, 28 | account: account, 29 | appid: appid, 30 | appsecret: appsecret, 31 | created_at: created_at.strftime('%Y-%m-%d'), 32 | company: { 33 | id: company_id, 34 | name: company.name 35 | } 36 | } 37 | end 38 | 39 | def self.fetch(id) 40 | Rails.cache.fetch(cache_key(id)) {self.find(id)} 41 | end 42 | 43 | def self.fetch_by_name(name) 44 | Rails.cache.fetch(cache_key(name)) {self.find_by_account(name)} 45 | end 46 | 47 | def self.fetch_by_slug(slug) 48 | Rails.cache.fetch(cache_key(slug)) {self.find_by_slug(slug)} 49 | end 50 | 51 | def self.cache_key(res) 52 | "account:#{res}" 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /app/models/trades/goods_order.rb: -------------------------------------------------------------------------------- 1 | class GoodsOrder < Order 2 | def generate_order_no 3 | "GD#{SecureRandom.hex(8)}" 4 | end 5 | end -------------------------------------------------------------------------------- /app/models/trades/order.rb: -------------------------------------------------------------------------------- 1 | class Order < ActiveRecord::Base 2 | enum state: [:initialized, :paid, :canceled, :refunded, :finished] 3 | 4 | has_many :payments 5 | 6 | # 订单商品快照 7 | has_many :goods_flashes 8 | 9 | def generate_new(params) 10 | clazz = case params.delete(:order_type) 11 | when :virtual 12 | GoodsOrder 13 | else 14 | Order 15 | end 16 | clazz.new params 17 | end 18 | 19 | before_create do 20 | self.order_no = generate_order_no 21 | self.state = Order.states[:initialized] 22 | end 23 | 24 | validates_presence_of :price 25 | 26 | def generate_order_no 27 | fail NotImplementedError 28 | end 29 | 30 | def state_text 31 | { 32 | initialized: '未支付', 33 | paid: '已支付', 34 | canceled: '已取消', 35 | refunded: '已退款', 36 | finished: '已完成' 37 | }[self.state.to_s.to_sym] 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /app/models/trades/payment.rb: -------------------------------------------------------------------------------- 1 | class Payment < ActiveRecord::Base 2 | validates_presence_of :total_fee 3 | 4 | belongs_to :order 5 | 6 | enum state: [:initialized, :paid, :refunded, :expired] 7 | 8 | def pay! 9 | self.update state: :paid 10 | end 11 | 12 | def self.generate(options={}) 13 | clazz = options.delete(:method).camelize.constantize 14 | clazz.generate options 15 | end 16 | end -------------------------------------------------------------------------------- /app/models/trades/ticket_order.rb: -------------------------------------------------------------------------------- 1 | class TicketOrder < Order 2 | 3 | def generate_order_no 4 | "TK#{SecureRandom.hex(8)}" 5 | end 6 | end -------------------------------------------------------------------------------- /app/models/trades/wxpub_pay_config.rb: -------------------------------------------------------------------------------- 1 | class WxpubPayConfig < ActiveRecord::Base 2 | validates_presence_of :name, :appid, :key, :mch_id 3 | 4 | after_commit do 5 | Rails.cache.delete WxpubPayConfig.cache_key(self.name) 6 | end 7 | 8 | def self.fetch(name) 9 | Rails.cache.fetch(cache_key(name)) {WxpubPayConfig.find_by_name name} 10 | end 11 | 12 | def self.cache_key(name) 13 | "wxpub_pay_config:#{name}" 14 | end 15 | end -------------------------------------------------------------------------------- /app/models/trades/wxpub_payment.rb: -------------------------------------------------------------------------------- 1 | class WxpubPayment < Payment 2 | TRADE_SUCCESS_CODE = 'SUCCESS' 3 | 4 | def notify_url 5 | "#{APP_CONFIG['domain']}/payments/wx_notify" 6 | end 7 | 8 | def fill_pay_data(openid, config_name) 9 | generate_payment_no 10 | 11 | content = { 12 | out_trade_no: payment_no, 13 | total_fee: (total_fee * 100).to_i, 14 | spbill_create_ip: '127.0.0.1', 15 | trade_type: 'JSAPI', 16 | body: order.title, 17 | notify_url: notify_url, 18 | openid: openid 19 | } 20 | 21 | pay_config = WxpubPayConfig.fetch config_name 22 | result = WxPay::Service.invoke_unifiedorder content, 23 | pay_config.as_json.symbolize_keys 24 | if result.success? 25 | js_pay_params = { 26 | prepayid: result['prepay_id'], 27 | noncestr: result['nonce_str'], 28 | key: pay_config.key 29 | } 30 | pay_params = WxPay::Service.generate_js_pay_req( 31 | js_pay_params, 32 | appid: pay_config.appid 33 | ) 34 | 35 | self.pay_data = pay_params.to_json 36 | else 37 | Rails.logger.info result.to_s 38 | end 39 | end 40 | 41 | def generate_payment_no 42 | self.payment_no = "WXPUB-#{order.order_no}-#{Time.now.to_i.to_s[5, 10]}" 43 | end 44 | 45 | def to_api_json 46 | { 47 | id: id, 48 | order_id: order_id, 49 | pay_data: pay_data 50 | } 51 | end 52 | 53 | def self.generate(options={}) 54 | openid = options.delete(:openid) 55 | cfg = options.delete :pay_config_name 56 | 57 | pay_config = WxpubPayConfig.fetch cfg 58 | options[:pay_res_id] = pay_config.id 59 | 60 | payment = self.new options 61 | payment.fill_pay_data(openid, cfg) 62 | 63 | payment 64 | end 65 | 66 | def notify_verify?(notify_params) 67 | WxPay::Sign.verify?(notify_params) && 68 | notify_params[:return_code] == TRADE_SUCCESS_CODE && 69 | notify_params[:result_code] == TRADE_SUCCESS_CODE 70 | end 71 | 72 | 73 | end -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | include ActivityConstant 3 | include ErrorConst 4 | include Userable 5 | 6 | has_and_belongs_to_many :activities 7 | has_many :orders 8 | has_many :delivery_infos 9 | 10 | def self.create_from_hash(account_id, info) 11 | self.create info.symbolize_keys 12 | .except(:tag_list, :subscribe) 13 | .merge({ 14 | public_account_id: account_id, 15 | alive: true}) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/services/storage_service.rb: -------------------------------------------------------------------------------- 1 | class StorageService 2 | include Singleton 3 | 4 | def set(key, value, expire) 5 | $redis.pipelined do 6 | $redis.set key, value.to_s 7 | $redis.expire key, expire if expire.present? 8 | end 9 | end 10 | 11 | def append(key, value, expire) 12 | set key, "#{value.to_s}\n\n-------\n\n#{get(key)}", expire 13 | end 14 | 15 | def get(key) 16 | $redis.get key 17 | end 18 | end -------------------------------------------------------------------------------- /app/services/wxpub_payment_service.rb: -------------------------------------------------------------------------------- 1 | class WxpubPaymentService 2 | include Singleton 3 | 4 | def pay(pay_config_name, openid, order) 5 | user = User.find_by_openid openid 6 | payment = Payment.generate pay_config_name: pay_config_name, 7 | method: 'wxpub_payment', 8 | total_fee: order.price + order.carriage, 9 | order_id: order.id, 10 | state: :initialized, 11 | openid: openid, 12 | user_id: user.id 13 | 14 | payment.save ? payment : nil 15 | end 16 | end -------------------------------------------------------------------------------- /app/views/admin/activities/_activity.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |

基础参数

6 |
7 |
8 | 11 | 12 | 15 | 16 | <% if @activity.id %> 17 | 20 | <% end %> 21 | 22 |
23 | 26 | 34 | <% if @activity.qrurl %> 35 | <%= image_tag @activity.qrurl, width: 96, height: 96, style: 'margin-left: 100px;' %> 36 | <% end %> 37 |
38 | 39 |
40 |
41 |
42 |

代码

43 |
44 |
45 | 46 |
47 | 48 |
49 | -------------------------------------------------------------------------------- /app/views/admin/activities/edit.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | <%= render 'activity' %> 5 |
6 | -------------------------------------------------------------------------------- /app/views/admin/activities/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | <% @activities.each do |a| %> 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | <% end %> 28 | 29 |
ID名称所属公众号事件创建时间二维码
<%= a.id %><%= a.name %><%= a.public_account.name %><%= a.event_key %><%= a.created_at %><%= image_tag(a.qrurl, width: 96, height: 96) if a.qrurl %> 23 | <%= link_to "编辑", edit_admin_activity_path(a), class: "btn btn-success" %> 24 | <%= link_to "删除", admin_activity_path(a), method: :delete, data: { confirm: '确认删除吗?' }, class: "btn btn-danger" %> 25 |
-------------------------------------------------------------------------------- /app/views/admin/activities/new.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 | <%= render 'activity' %> 4 |
5 | -------------------------------------------------------------------------------- /app/views/admin/crop_users/show.html.erb: -------------------------------------------------------------------------------- 1 | 123 -------------------------------------------------------------------------------- /app/views/admin/dash_boards/index.html.erb: -------------------------------------------------------------------------------- 1 |

赶紧开始干活吧~

-------------------------------------------------------------------------------- /app/views/admin/logins/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 32 | 33 | 34 |

WEI FISSION

35 |
36 | 39 |
40 | 43 |
44 |
45 | 46 |
47 | 48 | 51 | 52 | 53 | 58 | 59 | -------------------------------------------------------------------------------- /app/views/admin/pages/_page.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

文章

4 |
5 |
6 | 9 | 12 | 19 |
20 |
21 | 22 |
23 |
24 |

HTML

25 |
26 |
27 | 28 |
29 | 30 |
31 | -------------------------------------------------------------------------------- /app/views/admin/pages/account_pages.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | <% @pages.each do |page| %> 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | <% end %> 29 | 30 |
ID名称代码类型所属账号创建时间操作
<%= page.id %><%= page.title %><%= page.code %><%= page.page_type %><%= page.public_account.name %><%= page.created_at %> 23 | <%= link_to "预览", page_path(code: page.code), class: "btn btn-success", target: '_blank' %> 24 | <%= link_to "编辑", edit_admin_page_path(page, public_account_id: page.public_account.id), class: "btn btn-primary" %> 25 | <%= link_to "删除", admin_page_path(page, public_account_id: page.public_account.id), method: :delete, data: { confirm: '确认删除吗?' }, class: "btn btn-danger" %> 26 |
-------------------------------------------------------------------------------- /app/views/admin/pages/edit.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | <%= render 'page' %> 5 |
6 | -------------------------------------------------------------------------------- /app/views/admin/pages/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <% @accounts.each do |account| %> 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | <% end %> 24 | 25 |
ID公众号名称公众号账户页面数量操作
<%= account.id %><%= account.name %><%= account.account %><%= account.pages.count %> 19 | <%= link_to "详情", account_pages_admin_pages_path(public_account_id: account.id), class: "btn btn-primary" %> 20 | <%= link_to "新建", new_admin_page_path(public_account_id: account.id), class: "btn btn-success" %> 21 |
-------------------------------------------------------------------------------- /app/views/admin/pages/new.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 | <%= render 'page' %> 4 |
5 | -------------------------------------------------------------------------------- /app/views/admin/pay_configs/_wxpub_form.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

支付配置

4 |
5 |
6 | 9 | 12 |
13 | 16 | 19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /app/views/admin/pay_configs/edit_wxpub_pay_config.html.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | <%= render 'wxpub_form' %> 5 |
-------------------------------------------------------------------------------- /app/views/admin/pay_configs/new_wxpub_pay_config.html.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 | <%= render 'wxpub_form' %> 4 |
-------------------------------------------------------------------------------- /app/views/admin/pay_configs/wechat_list.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%= link_to "新建", new_admin_pay_config_path(type: 'WxpubPayConfig'), class: 'btn' %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | <% @cfgs.each do |cfg| %> 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | <% end %> 29 | 30 |
ID配置名称商户号创建时间操作
<%= cfg.id %><%= cfg.name %><%= cfg.mch_id %><%= cfg.created_at %> 24 | <%= link_to "编辑", edit_admin_pay_config_path(type: 'WxpubPayConfig', id: cfg.id), class: "btn btn" %> 25 | <%= link_to "删除", admin_pay_config_path(type: 'WxpubPayConfig', id: cfg.id), method: :delete, class: "btn btn-danger", data: { confirm: '确认删除吗?' } %> 26 |
-------------------------------------------------------------------------------- /app/views/admin/public_accounts/_account.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

绑定公众号

4 |
5 |
6 | 9 |
10 | 13 | 16 |
17 | 20 | 23 |
24 |
25 | 26 |
27 |
28 |

菜单JSON

29 |
30 |
31 | 32 |
33 | 34 |
35 | -------------------------------------------------------------------------------- /app/views/admin/public_accounts/edit.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | <%= render 'account' %> 5 |
6 | -------------------------------------------------------------------------------- /app/views/admin/public_accounts/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <% @accounts.each do |account| %> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | <% end %> 27 | 28 |
ID名称标识APPID创建时间操作
<%= account.id %><%= account.name %><%= account.slug %><%= account.appid %><%= account.created_at %> 21 | <%= link_to "用户管理", admin_users_path(public_account_id: account.id), class: 'btn btn-link' %> 22 | <%= link_to "编辑", edit_admin_public_account_path(account), class: "btn btn-success" %> 23 | <%= link_to "删除", admin_public_account_path(account), method: :delete, data: { confirm: '确认删除吗?' }, class: "btn btn-danger" %> 24 |
-------------------------------------------------------------------------------- /app/views/admin/public_accounts/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= render 'account' %> 3 |
4 | -------------------------------------------------------------------------------- /app/views/admin/ticket_orders/_ticket.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

支付单

4 |
5 |
6 | 9 |
10 | 13 |
14 |
15 | 16 |
17 |
18 |

支付单详情(支持HTML)

19 |
20 |
21 | 22 |
23 | 24 |
25 | 26 | -------------------------------------------------------------------------------- /app/views/admin/ticket_orders/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 | <%= render 'ticket' %> 4 |
5 | 6 | -------------------------------------------------------------------------------- /app/views/admin/ticket_orders/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <% @orders.each do |order| %> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | <% end %> 27 | 28 |
ID标题订单号状态创建时间操作
<%= order.id %><%= order.title %><%= order.order_no %><%= order.state_text %><%= order.created_at.strftime("%Y-%m-%d %H:%M") %> 21 | <%= link_to "详情", admin_ticket_order_path(order), class: 'btn' %> 22 | <%= link_to "编辑", edit_admin_ticket_order_path(order), class: "btn btn-success" %> 23 | <%= link_to "删除", admin_ticket_order_path(order), method: :delete, data: { confirm: '确认删除吗?' }, class: "btn btn-danger" %> 24 |
-------------------------------------------------------------------------------- /app/views/admin/ticket_orders/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= render 'ticket' %> 3 |
4 | 5 | -------------------------------------------------------------------------------- /app/views/admin/users/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <% @users.each do |user| %> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <% end %> 21 | 22 | <%= will_paginate @users %> 23 |
头像昵称状态加入时间操作
<%= image_tag user.headimgurl, width: 80, height: 80, class: 'user-avatar' %><%= user.nickname %><%= user.alive ? '关注中' : '已取关' %><%= user.created_at %>
-------------------------------------------------------------------------------- /app/views/admin/virtual_goods/_virtual_goods.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

虚拟商品

4 |
5 |
6 | 9 | 12 |
13 |
16 | 19 |
20 | 23 |
24 | 27 |
28 |
29 | 30 |
31 |
32 |

商品展示详情(HTML)

33 |
34 |
35 | 36 |
37 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /app/views/admin/virtual_goods/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 | 3 | <%= render 'virtual_goods' %> 4 |
5 | 6 | -------------------------------------------------------------------------------- /app/views/admin/virtual_goods/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | <% @goods.each do |goods| %> 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | <% end %> 29 | 30 |
ID标题标识状态销售数量创建时间操作
<%= goods.id %><%= goods.title %><%= goods.slug %><%= goods.state %><%= goods.sale_count %><%= goods.created_at.strftime("%Y-%m-%d %H:%M") %> 23 | <%= link_to "查看", "/pages/vgoods?goods_id=#{goods.id}", class: 'btn' %> 24 | <%= link_to "编辑", edit_admin_virtual_good_path(goods), class: "btn btn-success" %> 25 | <%= link_to "删除", admin_virtual_good_path(goods), method: :delete, data: { confirm: '确认删除吗?' }, class: "btn btn-danger" %> 26 |
-------------------------------------------------------------------------------- /app/views/admin/virtual_goods/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= render 'virtual_goods' %> 3 |
4 | 5 | -------------------------------------------------------------------------------- /app/views/admin/virtual_goods/show.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/app/views/admin/virtual_goods/show.html.erb -------------------------------------------------------------------------------- /app/views/layouts/admin.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | Wei Panel 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | <%= stylesheet_link_tag 'application', media: 'all' %> 18 | <%= javascript_include_tag 'application' %> 19 | <%= csrf_meta_tags %> 20 | 21 | 22 | 23 |
24 | 42 |
43 |
44 |
45 |
    46 | <% panel_menu.to_a.each do|href| %> 47 |
  • <%= href %>
  • 48 | <% end %> 49 |
50 |
51 |
52 | <%= yield %> 53 |
54 |
55 |
56 |
57 | 58 | 59 | 60 | 65 | 66 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Wei 5 | <%= stylesheet_link_tag 'application', media: 'all' %> 6 | <%= javascript_include_tag 'application' %> 7 | <%= csrf_meta_tags %> 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/views/pages/article.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%=raw @page.content %> 4 | 5 | -------------------------------------------------------------------------------- /app/views/types/show.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |

<%= @type.name %>

4 | <% if @type.thumb %> 5 | 6 | <% end %> 7 | 8 | <% @type.pages.each do |page| %> 9 | <%= link_to page.title, show_page_url(page.code) %> 10 | <% end %> 11 | 12 | -------------------------------------------------------------------------------- /app/workers/activity_join_worker.rb: -------------------------------------------------------------------------------- 1 | class ActivityJoinWorker 2 | include Sidekiq::Worker 3 | sidekiq_options retry: false 4 | 5 | def perform(activity_id, user_id, account_id, message, join_result) 6 | user = User.find(user_id) 7 | message = remarshal_message message 8 | account = PublicAccount.fetch(account_id) 9 | api = WechatService.instance.account_api account 10 | activity = Activity.find(activity_id) 11 | 12 | # 将用户加入到活动中去 13 | user.activities << activity unless user.activities.include? activity 14 | 15 | if $redis.get("need_reload:#{activity_id}").to_i == 1 16 | activity.load_activity 17 | $redis.del "need_reload:#{activity_id}" 18 | end 19 | 20 | activity = "Activity#{activity_id}".constantize.new( 21 | activity, 22 | user, api, account, message, join_result 23 | ) 24 | activity.start 25 | end 26 | 27 | private 28 | def remarshal_message(message_string) 29 | Wechat::Message.from_hash(Hash.from_xml(message_string)['xml'].symbolize_keys) 30 | end 31 | end -------------------------------------------------------------------------------- /app/workers/join_activity_worker.rb: -------------------------------------------------------------------------------- 1 | class JoinActivityWorker 2 | include Sidekiq::Worker 3 | sidekiq_options retry: false 4 | 5 | def perform(option) 6 | option = option.symbolize_keys 7 | 8 | user = User.find(option[:user_id]) 9 | account = PublicAccount.find(option[:account_id]) 10 | api = WechatService.new.account_api account 11 | 12 | activity = "Activity#{option[:activity_id]}".constantize.new( 13 | Activity.find(option[:activity_id]), 14 | user, api, account, option[:message], join_result 15 | ) 16 | activity.start 17 | end 18 | end -------------------------------------------------------------------------------- /app/workers/send_wechat_message_worker.rb: -------------------------------------------------------------------------------- 1 | class SendWechatMessageWorker 2 | include Sidekiq::Worker 3 | sidekiq_options retry: false 4 | 5 | def perform(account_api, message) 6 | WechatService.new.raw_api account_api 7 | account_api.custom_message_send message.reply.text(content) 8 | end 9 | end -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require 'rails/all' 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module Wei 10 | class Application < Rails::Application 11 | config.autoload_paths += Dir["#{config.root}/app/models/[a-z]*/"] 12 | config.autoload_paths += Dir["#{config.root}/app/services/"] 13 | config.autoload_paths += Dir["#{config.root}/activities/"] 14 | config.autoload_paths += %W(#{config.root}/lib/) 15 | config.assets.compile = true 16 | config.assets.precompile = %w(*.js *.css *.css.erb) 17 | 18 | config.active_record.raise_in_transactional_callbacks = true 19 | 20 | config.serve_static_files = true 21 | 22 | if Rails.env == 'production' 23 | config.default_host = 'weixin.njupt.org' 24 | else 25 | config.default_host = 'localhost' 26 | end 27 | 28 | 29 | 30 | config.paths['config/routes.rb'].concat(Dir[config.root.join('config/routes/*.rb'), "#{config.root}/lib/**/*.rb"]) 31 | config.time_zone = 'Beijing' 32 | config.i18n.available_locales = ['zh-CN', :en] 33 | config.i18n.default_locale = 'zh-CN' 34 | 35 | # Configure the default encoding used in templates for Ruby 1.9. 36 | config.encoding = 'utf-8' 37 | 38 | # Configure sensitive parameters which will be filtered from the log file. 39 | config.filter_parameters += [:password] 40 | 41 | config.middleware.insert_before 0, "Rack::Cors" do 42 | allow do 43 | origins '*' 44 | resource '*', :headers => :any, :methods => [:get, :post, :options, :put, :delete, :patch] 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /config/config.yml: -------------------------------------------------------------------------------- 1 | defaults: &defaults 2 | domain: 'http://localhost:3000' 3 | 4 | development: 5 | <<: *defaults 6 | domain: 'http://wx.njupt.org' 7 | 8 | test: 9 | <<: *defaults 10 | 11 | production: 12 | <<: *defaults 13 | domain: 'http://weixin.njupt.org' -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # MySQL. Versions 5.0+ are recommended. 2 | # 3 | # Install the MYSQL driver 4 | # gem install mysql2 5 | # 6 | # Ensure the MySQL gem is defined in your Gemfile 7 | # gem 'mysql2' 8 | # 9 | # And be sure to use new-style password hashing: 10 | # http://dev.mysql.com/doc/refman/5.0/en/old-client.html 11 | # 12 | default: &default 13 | adapter: mysql2 14 | encoding: utf8mb4 15 | pool: 5 16 | username: root 17 | password: 999999 18 | host: 127.0.0.1 19 | 20 | development: 21 | <<: *default 22 | database: wei_dev 23 | 24 | # Warning: The database defined as "test" will be erased and 25 | # re-generated from your development database when you run "rake". 26 | # Do not set this db to the same as development or production. 27 | test: 28 | <<: *default 29 | database: wei_test 30 | 31 | # As with config/secrets.yml, you never want to store sensitive information, 32 | # like your database password, in your source code. If your source code is 33 | # ever seen by anyone, they now have access to your database. 34 | # 35 | # Instead, provide the password as a unix environment variable when you boot 36 | # the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database 37 | # for a full rundown on how to provide these environment variables in a 38 | # production deployment. 39 | # 40 | # On Heroku and other platform providers, you may have a full connection URL 41 | # available as an environment variable. For example: 42 | # 43 | # DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase" 44 | # 45 | # You can use this database configuration with: 46 | # 47 | # production: 48 | # url: <%= ENV['DATABASE_URL'] %> 49 | # 50 | production: 51 | <<: *default 52 | database: wei_pd 53 | username: root 54 | password: <%= ENV['DATABASE_URL'] %> 55 | -------------------------------------------------------------------------------- /config/deploy.rb: -------------------------------------------------------------------------------- 1 | 2 | lock '3.5.0' 3 | 4 | set :application, 'wei' 5 | set :repo_url, 'git@github.com:plugine/wei.git' 6 | 7 | set :rvm_ruby_version, '2.3.0' 8 | 9 | # Default branch is :master 10 | # ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call 11 | set :branch, ENV['branch'] || 'master' 12 | 13 | set :deploy_to, "/var/apps/#{fetch(:application)}" 14 | 15 | # Default value for :scm is :git 16 | set :scm, :git 17 | set :deploy_via, :remote_cache 18 | set :copy_exclude, %w(.git) 19 | set :normalize_asset_timestamps, false 20 | 21 | # Default value for :format is :pretty 22 | set :format, :pretty 23 | 24 | # Default value for :log_level is :debug 25 | set :log_level, :debug 26 | 27 | # Default value for :pty is false 28 | set :pty, false 29 | 30 | # Default value for :linked_files is [] 31 | # set :linked_files, %w{config/database.yml} 32 | 33 | set :rbenv_map_bins, %w{rake gem bundle ruby rails sidekiq sidekiqctl} 34 | 35 | # Default value for linked_dirs is [] 36 | set :linked_dirs, %w(log tmp/activities tmp/pids tmp/cache tmp/sockets public/assets public/uploads db/exports) 37 | 38 | set(:custom_links, [ 39 | { 40 | source: '/var/uploads', 41 | target: "#{fetch(:deploy_to)}/shared/public/uploads" 42 | } 43 | ]) 44 | 45 | # Default value for keep_releases is 5 46 | set :keep_releases, 5 47 | 48 | set :puma_init_active_record, true 49 | set :puma_daemonize, true 50 | set :puma_bind, %w(tcp://0.0.0.0:9292 unix:///tmp/puma.sock) 51 | 52 | namespace :deploy do 53 | desc 'Restart application' 54 | task :restart do 55 | on roles(:app), in: :sequence, wait: 5 do 56 | end 57 | end 58 | 59 | namespace :symlink do 60 | desc 'custom_links' 61 | task :custom do 62 | on roles(:app) do 63 | fetch(:custom_links).each do |link| 64 | source = link[:source] 65 | target = link[:target] 66 | unless test "[ -L #{target} ]" 67 | execute :rmdir, target if test "[ -d #{target} ]" 68 | execute :ln, '-nsf', source, target 69 | end 70 | end 71 | end 72 | end 73 | end 74 | 75 | after :restart, :'puma:restart' 76 | after :publishing, :restart 77 | after 'symlink:shared', 'symlink:custom' 78 | after :restart, :clear_cache do 79 | on roles(:web), in: :groups, limit: 3, wait: 10 do 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /config/deploy/production.rb: -------------------------------------------------------------------------------- 1 | 2 | hosts = %w(root@five) 3 | role :app, hosts 4 | role :web, hosts 5 | role :db, hosts 6 | 7 | set :rails_env, :production 8 | 9 | set :repo_url, 'git@github.com:plugine/wei.git' 10 | 11 | set :puma_state, "#{shared_path}/tmp/pids/puma.state" 12 | set :puma_pid, "#{shared_path}/tmp/pids/puma.pid" 13 | set :puma_bind, 'unix:///tmp/puma.sock' #根据nginx配置链接的sock进行设置,需要唯一 14 | set :puma_conf, "#{shared_path}/puma.rb" 15 | set :puma_access_log, "#{shared_path}/log/puma_error.log" 16 | set :puma_error_log, "#{shared_path}/log/puma_access.log" 17 | set :puma_role, :app 18 | set :puma_env, fetch(:rack_env, fetch(:rails_env, 'production')) 19 | set :puma_threads, [0, 16] 20 | set :puma_workers, 0 21 | set :puma_init_active_record, false 22 | set :puma_preload_app, true 23 | 24 | set :sidekiq_role, :app 25 | set :sidekiq_config, "#{current_path}/config/sidekiq.yml" 26 | set :sidekiq_env, 'production' -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports and disable caching. 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send. 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger. 20 | config.active_support.deprecation = :log 21 | 22 | # Raise an error on page load if there are pending migrations. 23 | config.active_record.migration_error = :page_load 24 | 25 | # Debug mode disables concatenation and preprocessing of assets. 26 | # This option may cause significant delays in view rendering with a large 27 | # number of complex assets. 28 | config.assets.debug = true 29 | 30 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 31 | # yet still be able to expire them through the digest params. 32 | config.assets.digest = true 33 | 34 | # Adds additional error checking when serving assets at runtime. 35 | # Checks for improperly declared sprockets dependencies. 36 | # Raises helpful error messages. 37 | config.assets.raise_runtime_errors = true 38 | 39 | # Raises error for missing translations 40 | # config.action_view.raise_on_missing_translations = true 41 | end 42 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static file server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = 'public, max-age=3600' 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Randomize the order test cases are executed. 35 | config.active_support.test_order = :random 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | # Rails.application.config.assets.precompile += %w( search.js ) 12 | -------------------------------------------------------------------------------- /config/initializers/auto_load_activities.rb: -------------------------------------------------------------------------------- 1 | dir = "#{Rails.root}/tmp/activities/" 2 | 3 | Dir.mkdir(dir) unless Dir.exist?(dir) 4 | (Dir.glob "#{dir}/**/*").each do |file| 5 | begin 6 | load file 7 | rescue Exception => e 8 | Rails.logger.info "error load activity #{file}, #{e.inspect}" 9 | end 10 | end -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /config/initializers/config.rb: -------------------------------------------------------------------------------- 1 | APP_CONFIG = YAML.load_file(Rails.root.join('config/config.yml'))[Rails.env] -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json 4 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /config/initializers/kaminary.rb: -------------------------------------------------------------------------------- 1 | Kaminari.configure do |config| 2 | config.default_per_page = 25 3 | config.max_per_page = nil 4 | config.window = 4 5 | config.outer_window = 0 6 | config.left = 0 7 | config.right = 0 8 | config.page_method_name = :page 9 | config.param_name = :page 10 | end 11 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/initializers/qiniu.rb: -------------------------------------------------------------------------------- 1 | require 'qiniu' 2 | Qiniu.establish_connection! access_key: 'i-xPUCecSovn11r8ynAjFpcW-aWfa3Cf_LLr_Cav', 3 | secret_key: 'd2Mztf3lfyw91aCVJkfzOr8qV34FRfYlEQEB9rSn' -------------------------------------------------------------------------------- /config/initializers/redis.rb: -------------------------------------------------------------------------------- 1 | redis_url = 'redis://localhost:6379/0' 2 | ssdb_url = 'redis://localhost:8888/0' 3 | 4 | $redis = Redis.new(url: redis_url) 5 | $ssdb = Redis.new(url: ssdb_url) -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_wei_session' 4 | -------------------------------------------------------------------------------- /config/initializers/sidekiq.rb: -------------------------------------------------------------------------------- 1 | redis_url = 'redis://localhost:6379/0' 2 | 3 | Sidekiq.configure_server do |config| 4 | config.redis = { url: redis_url, namespace: 'wei' } 5 | end 6 | 7 | Sidekiq.configure_client do |config| 8 | config.redis = { url: redis_url, namespace: 'wei' } 9 | end 10 | 11 | Sidekiq.default_worker_options = { retry: 3, backtrace: true } 12 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /config/locales/simple_form.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | simple_form: 3 | "yes": 'Yes' 4 | "no": 'No' 5 | required: 6 | text: 'required' 7 | mark: '*' 8 | # You can uncomment the line below if you need to overwrite the whole required html. 9 | # When using html, text and mark won't be used. 10 | # html: '*' 11 | error_notification: 12 | default_message: "Please review the problems below:" 13 | # Examples 14 | # labels: 15 | # defaults: 16 | # password: 'Password' 17 | # user: 18 | # new: 19 | # email: 'E-mail to sign in.' 20 | # edit: 21 | # email: 'E-mail.' 22 | # hints: 23 | # defaults: 24 | # username: 'User name to sign in.' 25 | # password: 'No special characters, please.' 26 | # include_blanks: 27 | # defaults: 28 | # age: 'Rather not say' 29 | # prompts: 30 | # defaults: 31 | # age: 'Select your age' 32 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | require 'sidekiq/web' 2 | 3 | Sidekiq::Web.use Rack::Auth::Basic do |username, password| 4 | username == 'haelo' && password == 'haelo' 5 | end if Rails.env.production? 6 | 7 | Wei::Application.routes.draw do 8 | 9 | get '/admin' => 'admin/logins#index' 10 | 11 | get '/wechat/auth/:storage_name' => 'wechats#auth' 12 | 13 | resource :wechat, only: [:show, :create] do 14 | get :wx_config, on: :collection 15 | end 16 | mount Sidekiq::Web => '/admin/sidekiq' 17 | 18 | resources :pages, only: [:show], param: :code 19 | resources :storages, param: :key, only: [:show, :create] do 20 | post :append, on: :collection 21 | end 22 | resources :types, only: [:show], param: :code 23 | resources :orders, onlt: [:show, :create] 24 | 25 | resources :payments, only: [:create] do 26 | post :wx_notify, on: :collection 27 | end 28 | 29 | resource :delivery_infos, only: [:create] 30 | end 31 | -------------------------------------------------------------------------------- /config/routes/admin.rb: -------------------------------------------------------------------------------- 1 | Wei::Application.routes.draw do 2 | namespace :admin do 3 | resources :logins, only: [:index, :create] 4 | 5 | resources :panels, only: [:index] 6 | resources :public_accounts 7 | resources :dash_boards, only: [:index, :update] 8 | 9 | resources :pages do 10 | get :account_pages, on: :collection 11 | end 12 | 13 | resources :activities do 14 | get :refresh_qr, on: :member 15 | end 16 | 17 | resources :users 18 | 19 | resources :ticket_orders 20 | 21 | resources :buttons 22 | 23 | resource :crop_users 24 | 25 | resources :pay_configs do 26 | collection do 27 | get :wechat_list 28 | end 29 | end 30 | 31 | resources :virtual_goods 32 | end 33 | end -------------------------------------------------------------------------------- /config/routes/weixin.rb: -------------------------------------------------------------------------------- 1 | Wei::Application.routes.draw do 2 | namespace :weixin do 3 | resource :weixin, only: [:index, :create] 4 | end 5 | end -------------------------------------------------------------------------------- /config/schedule.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/config/schedule.rb -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: f39e4fbcca76cbe217082112edbcb5e58101dc75d0c75c7547d0fb823d64e234b24878b52d21aad92ab2241c3333d9dacfd67133c65ec3f41c8197875c3993b8 15 | 16 | test: 17 | secret_key_base: c38e3b60f9af50a433eefaca386036825aecd855d0b244b037cd892e25379ee648e966c3a3c1250937f8c9217063f4118c9ef948a32acd93622e88162116d711 18 | 19 | production: 20 | secret_key_base: 7db61b53bc83b716197592b6cf5581a3b7fff2434a1b4d6166598c30bd690626cb5b041244760578ecf1755992f93478a80a91ad1317ab5bb837b64e597c338c 21 | 22 | -------------------------------------------------------------------------------- /config/sidekiq.yml: -------------------------------------------------------------------------------- 1 | --- 2 | :concurrency: 100 3 | :pidfile: tmp/pids/sidekiq.pid 4 | qa: 5 | :concurrency: 5 6 | production: 7 | :concurrency: 200 8 | :queues: 9 | - default 10 | -------------------------------------------------------------------------------- /config/wechat.yml: -------------------------------------------------------------------------------- 1 | default: &default 2 | appid: "my_appid" 3 | secret: "my_secret" 4 | token: "my_token" 5 | access_token: "tmp/wechat_access_token" 6 | jsapi_ticket: "tmp/wechat_jsapi_ticket" 7 | encoding_aes_key: "my_encoding_aes_key" 8 | encrypt_mode: false 9 | timeout: 30, 10 | skip_verify_ssl: true 11 | 12 | development: 13 | <<: *default 14 | 15 | test: 16 | <<: *default 17 | 18 | # for production 19 | production: 20 | appid: "appid" 21 | secret: "secret" 22 | token: "token" 23 | access_token: "tmp/wechat_access_token4" 24 | jsapi_ticket: "tmp/wechat_jsapi_ticket4" 25 | #trusted_domain_fullname: "https://bhapp.boohee.cn" 26 | -------------------------------------------------------------------------------- /db/migrate/20180317110326_create_crop_users.rb: -------------------------------------------------------------------------------- 1 | class CreateCropUsers < ActiveRecord::Migration 2 | def change 3 | create_table :crop_users do |t| 4 | t.string :account, null: false 5 | t.string :password_digest, null: false 6 | t.string :phone, null: false 7 | 8 | t.integer :company_id 9 | t.timestamps 10 | end 11 | 12 | add_index :crop_users, :account 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20180317110637_create_companys.rb: -------------------------------------------------------------------------------- 1 | class CreateCompanys < ActiveRecord::Migration 2 | def change 3 | create_table :companies do |t| 4 | t.string :name, null: false 5 | t.date :expire_at, default: Date.today + 1.year 6 | t.boolean :enabled, default: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20180317114644_create_public_accounts.rb: -------------------------------------------------------------------------------- 1 | class CreatePublicAccounts < ActiveRecord::Migration 2 | def change 3 | create_table :public_accounts do |t| 4 | t.string :name, null: false 5 | t.string :account, null: false 6 | t.string :appid, null: false 7 | t.string :appsecret, null: false 8 | 9 | t.integer :company_id 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20180317115226_create_events.rb: -------------------------------------------------------------------------------- 1 | class CreateEvents < ActiveRecord::Migration 2 | def change 3 | create_table :events do |t| 4 | t.string :event_type, null: false 5 | t.string :action_type, null: false 6 | t.string :condition 7 | t.string :extra 8 | t.integer :priority 9 | 10 | t.integer :public_account_id 11 | 12 | t.timestamps null: false 13 | 14 | t.index :event_type 15 | t.index :public_account_id 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20180317115550_create_activities.rb: -------------------------------------------------------------------------------- 1 | class CreateActivities < ActiveRecord::Migration 2 | def change 3 | create_table :activities do |t| 4 | t.string :name, null: false 5 | t.string :author 6 | t.boolean :enabled, default: false 7 | t.text :desc 8 | t.text :consts 9 | t.text :template, null: false 10 | t.string :qrurl 11 | t.integer :public_account_id 12 | 13 | t.timestamps null: false 14 | 15 | t.index :public_account_id 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20180317120003_create_users.rb: -------------------------------------------------------------------------------- 1 | 2 | # 参数 说明 3 | # subscribe 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。 4 | # openid 用户的标识,对当前公众号唯一 5 | # nickname 用户的昵称 6 | # sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 7 | # city 用户所在城市 8 | # country 用户所在国家 9 | # province 用户所在省份 10 | # language 用户的语言,简体中文为zh_CN 11 | # headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 12 | # subscribe_time 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间 13 | # unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 14 | # remark 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注 15 | # groupid 用户所在的分组ID(兼容旧的用户分组接口) 16 | # tagid_list 用户被打上的标签ID列表 17 | # subscribe_scene 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENEPROFILE LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_OTHERS 其他 18 | # qr_scene 二维码扫码场景(开发者自定义) 19 | # qr_scene_str 二维码扫码场景描述(开发者自定义) 20 | 21 | 22 | class CreateUsers < ActiveRecord::Migration 23 | def change 24 | create_table :users do |t| 25 | t.string :from, default: 'wechat' 26 | t.integer :public_account_id 27 | t.boolean :alive 28 | t.timestamp :died_at 29 | 30 | t.string :openid 31 | t.string :nickname 32 | t.integer :sex 33 | t.string :country 34 | t.string :province 35 | t.string :city 36 | t.string :language 37 | t.string :headimgurl 38 | t.timestamp :subscribe_time 39 | t.string :union_id 40 | t.string :remark 41 | t.integer :groupid 42 | t.text :tagid_list 43 | t.string :subscribe_scene 44 | t.string :qr_scene 45 | t.string :qr_scene_str 46 | 47 | t.timestamps null: false 48 | 49 | t.index :public_account_id 50 | t.index :openid 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /db/migrate/20180317120110_create_join_table_activity_user.rb: -------------------------------------------------------------------------------- 1 | class CreateJoinTableActivityUser < ActiveRecord::Migration 2 | def change 3 | create_join_table :activities, :users do |t| 4 | t.integer :activity_id 5 | t.integer :user_id 6 | 7 | t.index [:activity_id, :user_id] 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20180405073440_create_pages.rb: -------------------------------------------------------------------------------- 1 | class CreatePages < ActiveRecord::Migration 2 | def change 3 | create_table :pages do |t| 4 | t.string :title, null: false 5 | t.string :code, null: false, limit: 30 6 | t.text :content, null: false 7 | t.string :page_type, default: 'raw', limit: 10 8 | 9 | t.timestamps null: false 10 | 11 | t.integer :public_account_id 12 | t.integer :article_type_id 13 | end 14 | 15 | add_index :pages, :public_account_id 16 | add_index :pages, :article_type_id 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20180414104327_create_article_types.rb: -------------------------------------------------------------------------------- 1 | class CreateArticleTypes < ActiveRecord::Migration 2 | def change 3 | create_table :article_types do |t| 4 | t.string :name 5 | t.string :code 6 | t.string :thumb 7 | 8 | t.integer :public_account_id 9 | 10 | t.timestamps null: false 11 | end 12 | 13 | add_index :article_types, :public_account_id 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20180414120123_create_media_resources.rb: -------------------------------------------------------------------------------- 1 | class CreateMediaResources < ActiveRecord::Migration 2 | def change 3 | create_table :media_resources do |t| 4 | t.string :name 5 | t.string :qiniu_key 6 | 7 | t.timestamps null: false 8 | 9 | t.integer :public_account_id 10 | end 11 | 12 | add_index :media_resources, :public_account_id 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20180415100503_add_menu_to_public_account.rb: -------------------------------------------------------------------------------- 1 | class AddMenuToPublicAccount < ActiveRecord::Migration 2 | def change 3 | add_column :public_accounts, :menu_json, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180415100611_add_event_key_to_public_account.rb: -------------------------------------------------------------------------------- 1 | class AddEventKeyToPublicAccount < ActiveRecord::Migration 2 | def change 3 | add_column :activities, :event_key, :string, default: '' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180427160606_change_user_nickname_limit.rb: -------------------------------------------------------------------------------- 1 | class ChangeUserNicknameLimit < ActiveRecord::Migration 2 | def change 3 | change_column :users, :nickname, :string, limit: 191 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180503105812_change_user_column.rb: -------------------------------------------------------------------------------- 1 | class ChangeUserColumn < ActiveRecord::Migration 2 | def change 3 | remove_column :users, :died_at 4 | add_column :users, :dead_at, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20180505154123_create_wxpub_pay_config.rb: -------------------------------------------------------------------------------- 1 | class CreateWxpubPayConfig < ActiveRecord::Migration 2 | def change 3 | create_table :wxpub_pay_configs do |t| 4 | t.string :name, null: false 5 | t.string :appid, null: false 6 | t.string :key, null: false 7 | t.string :mch_id, null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20180505161029_add_timestamps_to_wxpub_pay_configs.rb: -------------------------------------------------------------------------------- 1 | class AddTimestampsToWxpubPayConfigs < ActiveRecord::Migration 2 | def change 3 | add_timestamps :wxpub_pay_configs 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180506112053_create_orders.rb: -------------------------------------------------------------------------------- 1 | class CreateOrders < ActiveRecord::Migration 2 | def change 3 | create_table :orders do |t| 4 | t.string :order_no, null: false, limit: 255 5 | t.decimal :price, precision: 8, scale: 2 6 | t.string :type 7 | t.string :real_name 8 | t.string :phone 9 | t.integer :state 10 | t.string :address, limit: 512 11 | t.datetime :paid_at 12 | t.decimal :carriage, precision: 10, scale: 2, default: 0.0 13 | t.string :note, limit: 512 14 | t.string :operator_note, limit: 512 15 | 16 | 17 | t.timestamps 18 | 19 | t.integer :user_id 20 | t.integer :crop_user_id 21 | end 22 | 23 | add_index :orders, :order_no 24 | add_index :orders, :phone 25 | add_index :orders, [:type, :state] 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /db/migrate/20180506113942_create_payment.rb: -------------------------------------------------------------------------------- 1 | class CreatePayment < ActiveRecord::Migration 2 | def change 3 | create_table :payments do |t| 4 | t.decimal :total_fee, precision: 8, scale: 2 5 | t.string :type 6 | t.integer :state 7 | 8 | t.integer :user_id 9 | t.integer :order_id 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20180506123258_add_payment_detail_to_payments.rb: -------------------------------------------------------------------------------- 1 | class AddPaymentDetailToPayments < ActiveRecord::Migration 2 | def change 3 | add_column :payments, :pay_data, :string, limit: 512 4 | add_column :payments, :pay_detail, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20180506130317_add_payment_no_to_payments.rb: -------------------------------------------------------------------------------- 1 | class AddPaymentNoToPayments < ActiveRecord::Migration 2 | def change 3 | add_column :payments, :payment_no, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180507144603_add_title_to_orders.rb: -------------------------------------------------------------------------------- 1 | class AddTitleToOrders < ActiveRecord::Migration 2 | def change 3 | add_column :orders, :title, :string, limit: 191 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180507172555_change_order_attr_type.rb: -------------------------------------------------------------------------------- 1 | class ChangeOrderAttrType < ActiveRecord::Migration 2 | def change 3 | change_column :orders, :operator_note, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180508143853_add_slug_to_public_account.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToPublicAccount < ActiveRecord::Migration 2 | def change 3 | add_column :public_accounts, :slug, :string, limit: 50 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180509162937_add_pay_res_id_to_payments.rb: -------------------------------------------------------------------------------- 1 | class AddPayResIdToPayments < ActiveRecord::Migration 2 | def change 3 | add_column :payments, :pay_res_id, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180510103721_create_goods.rb: -------------------------------------------------------------------------------- 1 | class CreateGoods < ActiveRecord::Migration 2 | def change 3 | create_table :goods do |t| 4 | t.string :title, limit: 191 5 | t.string :slug, limit: 40 6 | t.integer :state, default: 0 7 | t.decimal :market_price, precision: 10, scale: 2 8 | t.decimal :price, precision:10, scale: 2 9 | t.string :cover_img, limit: 255 10 | t.string :unit_name, limit: 20 11 | t.integer :sale_count, default: 0 12 | t.string :pics, limit: 800 13 | t.text :content_html 14 | 15 | t.timestamps 16 | end 17 | 18 | add_index :goods, :title 19 | add_index :goods, :slug 20 | add_index :goods, :state 21 | add_index :goods, :price 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /db/migrate/20180510105746_create_goods_flash.rb: -------------------------------------------------------------------------------- 1 | class CreateGoodsFlash < ActiveRecord::Migration 2 | def change 3 | create_table :goods_flashes do |t| 4 | t.boolean :paid 5 | t.decimal :price, precision: 10, scale: 2 6 | 7 | t.integer :goods_id 8 | t.integer :order_id 9 | 10 | t.timestamps null: false 11 | end 12 | 13 | add_index :goods_flashes, :goods_id 14 | add_index :goods_flashes, :order_id 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20180510151913_add_type_to_goods.rb: -------------------------------------------------------------------------------- 1 | class AddTypeToGoods < ActiveRecord::Migration 2 | def change 3 | add_column :goods, :type, :string, limit: 255 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180528025128_create_reminds.rb: -------------------------------------------------------------------------------- 1 | class CreateReminds < ActiveRecord::Migration 2 | def change 3 | create_table :reminds do |t| 4 | t.string :title, limit: 255 5 | t.string :category, limit: 100, default: '默认' 6 | t.integer :state, default: 0 7 | t.integer :priority, default: 0 8 | t.text :content 9 | t.datetime :remind_at, null: false 10 | 11 | t.timestamps 12 | t.integer :connection_resource_id 13 | end 14 | 15 | add_index :reminds, :remind_at 16 | add_index :reminds, :connection_resource_id 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20180529071311_create_delivery_info.rb: -------------------------------------------------------------------------------- 1 | class CreateDeliveryInfo < ActiveRecord::Migration 2 | def change 3 | create_table :delivery_infos do |t| 4 | t.string :province 5 | t.string :city 6 | t.string :street 7 | t.string :name 8 | t.string :phone 9 | 10 | t.integer :user_id 11 | 12 | # this could be order id 13 | t.integer :resource_id 14 | t.integer :activity_id 15 | t.string :comment 16 | end 17 | 18 | add_index :delivery_infos, :activity_id 19 | add_index :delivery_infos, :user_id 20 | add_index :delivery_infos, :name 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | 4 | company = Company.find_by_name 'haelo' 5 | company = Company.create name: 'haelo' unless company 6 | 7 | if CropUser.count == 0 8 | company.crop_users.create account: 'haelo', password: 'haelo', phone: '18351882074' 9 | end -------------------------------------------------------------------------------- /img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/img/1.jpg -------------------------------------------------------------------------------- /lib/activities/.store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/lib/activities/.store -------------------------------------------------------------------------------- /lib/activities/1_2.rb: -------------------------------------------------------------------------------- 1 | class Activity2 2 | include ErrorConst 3 | include Activitiable 4 | 5 | def initialize(activity, user, api, account, message, join_result) 6 | @activity = activity 7 | @user = user 8 | @api = api 9 | @account = account 10 | @message = message 11 | @join_result = join_result 12 | end 13 | 14 | def start 15 | say "hello you are in activity, you result is #{join_result}" 16 | say "welcome to my homeland!" 17 | end 18 | 19 | end 20 | -------------------------------------------------------------------------------- /lib/activities/2_2.rb: -------------------------------------------------------------------------------- 1 | class Activity2 2 | include ErrorConst 3 | include Activitiable 4 | 5 | def initialize(activity, user, api, account, message, join_result) 6 | @activity = activity 7 | @user = user 8 | @api = api 9 | @account = account 10 | @message = message 11 | @join_result = join_result 12 | end 13 | 14 | text :welcome, 'Hi #{user.nickname}~\n欢迎参加我的活动' 15 | 16 | def start 17 | say welcome 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/activities/2_5.rb: -------------------------------------------------------------------------------- 1 | class Activity5 2 | include ErrorConst 3 | include Activitiable 4 | 5 | def initialize(activity, user, api, account, message, join_result) 6 | @activity = activity 7 | @user = user 8 | @api = api 9 | @account = account 10 | @message = message 11 | @join_result = join_result 12 | end 13 | 14 | def start 15 | say '欢迎参加活动' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/lib/tasks/.keep -------------------------------------------------------------------------------- /lib/templates/erb/scaffold/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%%= simple_form_for(@<%= singular_table_name %>) do |f| %> 2 | <%%= f.error_notification %> 3 | 4 |
5 | <%- attributes.each do |attribute| -%> 6 | <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %> 7 | <%- end -%> 8 |
9 | 10 |
11 | <%%= f.button :submit %> 12 |
13 | <%% end %> 14 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "axios": { 6 | "version": "0.18.0", 7 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", 8 | "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", 9 | "requires": { 10 | "follow-redirects": "1.4.1", 11 | "is-buffer": "1.1.6" 12 | } 13 | }, 14 | "debug": { 15 | "version": "3.1.0", 16 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 17 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 18 | "requires": { 19 | "ms": "2.0.0" 20 | } 21 | }, 22 | "follow-redirects": { 23 | "version": "1.4.1", 24 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", 25 | "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", 26 | "requires": { 27 | "debug": "3.1.0" 28 | } 29 | }, 30 | "is-buffer": { 31 | "version": "1.1.6", 32 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 33 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 34 | }, 35 | "ms": { 36 | "version": "2.0.0", 37 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 38 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /public/static/fonts/element-icons.27c7209.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/fonts/element-icons.27c7209.ttf -------------------------------------------------------------------------------- /public/static/fonts/element-icons.6f0a763.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/fonts/element-icons.6f0a763.ttf -------------------------------------------------------------------------------- /public/static/fonts/fontawesome-webfont.674f50d.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/fonts/fontawesome-webfont.674f50d.eot -------------------------------------------------------------------------------- /public/static/fonts/fontawesome-webfont.af7ae50.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/fonts/fontawesome-webfont.af7ae50.woff2 -------------------------------------------------------------------------------- /public/static/fonts/fontawesome-webfont.b06871f.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/fonts/fontawesome-webfont.b06871f.ttf -------------------------------------------------------------------------------- /public/static/fonts/fontawesome-webfont.fee66e7.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/fonts/fontawesome-webfont.fee66e7.woff -------------------------------------------------------------------------------- /public/static/img/401.089007e.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/img/401.089007e.gif -------------------------------------------------------------------------------- /public/static/img/404.a57b6f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/img/404.a57b6f3.png -------------------------------------------------------------------------------- /public/static/js/18.e9397ef0e4fcd641c3ef.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([18,56,57],{IctB:function(e,t,r){var n=r("L21O");"string"==typeof n&&(n=[[e.i,n,""]]),n.locals&&(e.exports=n.locals);r("rjj0")("10228a24",n,!0)},L21O:function(e,t,r){(e.exports=r("FZ+f")(!1)).push([e.i,"\n.errPage-container[data-v-73d032e8] {\n padding: 30px;\n}\n",""])},XuU3:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={render:function(){var e=this.$createElement;return(this._self._c||e)("div",[this._v("\n "+this._s(this.a.a)+"\n ")])},staticRenderFns:[]},a=r("VU/8")({name:"errorTestA"},n,!1,null,null,null);t.default=a.exports},it3z:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={created:function(){this.b=b}},a={render:function(){var e=this.$createElement;return(this._self._c||e)("div")},staticRenderFns:[]},s=r("VU/8")(n,a,!1,null,null,null);t.default=s.exports},o25k:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=r("XuU3"),a=r("it3z"),s={name:"errorLog",components:{errorA:n.default,errorB:a.default}},i={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"errPage-container"},[r("errorA"),e._v(" "),r("errorB"),e._v(" "),r("h3",[e._v(e._s(e.$t("errorLog.tips")))]),e._v(" "),r("code",[e._v("\n "+e._s(e.$t("errorLog.description"))+"\n "),r("a",{staticClass:"link-type",attrs:{target:"_blank",href:"https://panjiachen.github.io/vue-element-admin-site/#/error?id=%e4%bb%a3%e7%a0%81"}},[e._v("\n "+e._s(e.$t("errorLog.documentation"))+"\n ")])]),e._v(" "),e._m(0)],1)},staticRenderFns:[function(){var e=this.$createElement,t=this._self._c||e;return t("a",{attrs:{href:"#"}},[t("img",{attrs:{src:"https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif"}})])}]};var o=r("VU/8")(s,i,!1,function(e){r("IctB")},"data-v-73d032e8",null);t.default=o.exports}}); -------------------------------------------------------------------------------- /public/static/js/20.1b1ef5b605cd82b469de.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([20],{"9DYS":function(t,e,a){(t.exports=a("FZ+f")(!1)).push([t.i,"\n.json-editor[data-v-5c878a0a]{\n height: 100%;\n position: relative;\n}\n.json-editor[data-v-5c878a0a] .CodeMirror {\n height: auto;\n min-height: 300px;\n}\n.json-editor[data-v-5c878a0a] .CodeMirror-scroll{\n min-height: 300px;\n}\n.json-editor[data-v-5c878a0a] .cm-s-rubyblue span.cm-string {\n color: #F08047;\n}\n",""])},MECs:function(t,e,a){(t.exports=a("FZ+f")(!1)).push([t.i,"\n.editor-container[data-v-3e084632]{\n position: relative;\n height: 100%;\n}\n",""])},lKtc:function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=a("mvHQ"),o=a.n(r),n=a("8U58"),s=a.n(n),i=(a("GUiZ"),a("4/hK"),a("0tbE"),a("uOPQ"),a("ryyk"),{name:"jsonEditor",data:function(){return{jsonEditor:!1}},props:["value"],watch:{value:function(t){t!==this.jsonEditor.getValue()&&this.jsonEditor.setValue(o()(this.value,null,2))}},mounted:function(){var t=this;this.jsonEditor=s.a.fromTextArea(this.$refs.textarea,{lineNumbers:!0,mode:"ruby",gutters:["CodeMirror-lint-markers"],theme:"darcula",lint:!0}),this.jsonEditor.setValue(o()(this.value,null,2)),this.jsonEditor.on("change",function(e){t.$emit("changed",e.getValue()),t.$emit("input",e.getValue())})},methods:{getValue:function(){return this.jsonEditor.getValue()}}}),l={render:function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"json-editor"},[e("textarea",{ref:"textarea"})])},staticRenderFns:[]};var d={name:"jsonEditor-demo",components:{JsonEditor:a("VU/8")(i,l,!1,function(t){a("qY9C")},"data-v-5c878a0a",null).exports},data:function(){return{value:JSON.parse('[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]')}}},m={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"components-container"},[t._m(0),t._v(" "),a("div",{staticClass:"editor-container"},[a("json-editor",{ref:"jsonEditor",model:{value:t.value,callback:function(e){t.value=e},expression:"value"}})],1)])},staticRenderFns:[function(){var t=this.$createElement,e=this._self._c||t;return e("code",[this._v("JsonEditor is base on "),e("a",{attrs:{href:"https://github.com/codemirror/CodeMirror",target:"_blank"}},[this._v("CodeMirrorr")]),this._v(" , lint base on json-lint ")])}]};var c=a("VU/8")(d,m,!1,function(t){a("tC+n")},"data-v-3e084632",null);e.default=c.exports},qY9C:function(t,e,a){var r=a("9DYS");"string"==typeof r&&(r=[[t.i,r,""]]),r.locals&&(t.exports=r.locals);a("rjj0")("2c4274be",r,!0)},"tC+n":function(t,e,a){var r=a("MECs");"string"==typeof r&&(r=[[t.i,r,""]]),r.locals&&(t.exports=r.locals);a("rjj0")("5d2f6ec0",r,!0)}}); -------------------------------------------------------------------------------- /public/static/js/25.c4fa26fdb1662ee7f139.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([25,45],{"6cSl":function(t,e,n){var a=n("JBQj");"string"==typeof a&&(a=[[t.i,a,""]]),a.locals&&(t.exports=a.locals);n("rjj0")("e50e0212",a,!0)},JBQj:function(t,e,n){(t.exports=n("FZ+f")(!1)).push([t.i,"\n.tab-container[data-v-44d1c6f7]{\n margin: 30px;\n}\n",""])},esQe:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("nv77"),l={props:{type:{type:String,default:"all"}},data:function(){return{list:null,loading:!1}},created:function(){this.getList()},methods:{del:function(t){var e=this;confirm("确定要删除这个公众号?")&&Object(a.b)(t).then(function(t){e.getList()})},getList:function(){var t=this;this.loading=!0,this.$emit("create"),Object(a.d)().then(function(e){t.list=e.data.public_accounts,t.loading=!1})}}},i={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("el-table",{staticStyle:{width:"100%"},attrs:{data:t.list,border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{directives:[{name:"loading",rawName:"v-loading",value:t.loading,expression:"loading"}],attrs:{align:"center",label:"ID",width:"65","element-loading-text":"加载中"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.id))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"130px",align:"center",label:"名称"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.name))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"150px",align:"center",label:"账号"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.account))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"110px",align:"center",label:"appID"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.appid))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"110px",align:"center",label:"Secret"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.appsecret))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"min-width":"180px",label:"创建时间"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.created_at))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"class-name":"status-col",label:"操作",width:"110"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("router-link",{attrs:{to:"/public_account/edit/"+e.row.id}},[t._v("编辑")]),t._v(" "),n("a",{on:{click:function(n){t.del(e.row.id)}}},[t._v("删除")])]}}])})],1)},staticRenderFns:[]},r=n("VU/8")(l,i,!1,null,null,null);e.default=r.exports},kJ8J:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a={name:"tab",components:{tabPane:n("esQe").default},data:function(){return{tabMapOptions:[{label:"所有",key:"all"}],activeName:"all",createdTimes:0}},methods:{}},l={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"tab-container"},[n("el-tabs",{staticStyle:{"margin-top":"15px"},attrs:{type:"border-card"},model:{value:t.activeName,callback:function(e){t.activeName=e},expression:"activeName"}},t._l(t.tabMapOptions,function(e){return n("el-tab-pane",{key:e.key,attrs:{label:e.label,name:e.key}},[n("keep-alive",[t.activeName==e.key?n("tab-pane",{attrs:{type:e.key}}):t._e()],1)],1)}))],1)},staticRenderFns:[]};var i=n("VU/8")(a,l,!1,function(t){n("6cSl")},"data-v-44d1c6f7",null);e.default=i.exports}}); -------------------------------------------------------------------------------- /public/static/js/26.5b5ff59b18376fe1de73.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([26,60],{"5KhA":function(t,e,n){var a=n("dqKh");"string"==typeof a&&(a=[[t.i,a,""]]),a.locals&&(t.exports=a.locals);n("rjj0")("e50e0212",a,!0)},dqKh:function(t,e,n){(t.exports=n("FZ+f")(!1)).push([t.i,"\n.tab-container[data-v-44d1c6f7]{\n margin: 30px;\n}\n",""])},eI3e:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("Ty/O"),l={props:{type:{type:String,default:"all"}},data:function(){return{list:null,loading:!1}},created:function(){this.getList()},methods:{del:function(t){var e=this;confirm("确定要删除这个活动?")&&Object(a.b)(t).then(function(t){e.getList()})},getList:function(){var t=this;this.loading=!0,this.$emit("create"),Object(a.d)({}).then(function(e){console.log(e),t.list=e.data.activities,t.loading=!1})}}},i={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("el-table",{staticStyle:{width:"100%"},attrs:{data:t.list,border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{directives:[{name:"loading",rawName:"v-loading",value:t.loading,expression:"loading"}],attrs:{align:"center",label:"ID",width:"65","element-loading-text":"加载中"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.id))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"200px",align:"center",label:"活动名称"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.name))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"150px",align:"center",label:"公众号"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.public_account.name))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"110px",align:"center",label:"活动描述"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.desc))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"120px",label:"专属序列号"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.idx))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"min-width":"180px",label:"创建时间"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.created_at))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"class-name":"status-col",label:"操作",width:"110"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("router-link",{attrs:{to:"/activity/edit/"+e.row.id}},[t._v("编辑")]),t._v(" "),n("a",{on:{click:function(n){t.del(e.row.id)}}},[t._v("删除")])]}}])})],1)},staticRenderFns:[]},r=n("VU/8")(l,i,!1,null,null,null);e.default=r.exports},sZNU:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a={name:"tab",components:{tabPane:n("eI3e").default},data:function(){return{tabMapOptions:[{label:"所有",key:"all"}],activeName:"all",createdTimes:0}},methods:{}},l={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"tab-container"},[n("el-tabs",{staticStyle:{"margin-top":"15px"},attrs:{type:"border-card"},model:{value:t.activeName,callback:function(e){t.activeName=e},expression:"activeName"}},t._l(t.tabMapOptions,function(e){return n("el-tab-pane",{key:e.key,attrs:{label:e.label,name:e.key}},[n("keep-alive",[t.activeName==e.key?n("tab-pane",{attrs:{type:e.key}}):t._e()],1)],1)}))],1)},staticRenderFns:[]};var i=n("VU/8")(a,l,!1,function(t){n("5KhA")},"data-v-44d1c6f7",null);e.default=i.exports}}); -------------------------------------------------------------------------------- /public/static/js/27.26694b0425b3ba2a31f5.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([27],{"2aNK":function(t,a,n){var e=n("avs9");"string"==typeof e&&(e=[[t.i,e,""]]),e.locals&&(t.exports=e.locals);n("rjj0")("57d27077",e,!0)},MOmO:function(t,a,n){t.exports=n.p+"static/img/401.089007e.gif"},avs9:function(t,a,n){(t.exports=n("FZ+f")(!1)).push([t.i,"\n.errPage-container[data-v-1c485e74] {\n width: 800px;\n margin: 100px auto;\n}\n.errPage-container .pan-back-btn[data-v-1c485e74] {\n background: #008489;\n color: #fff;\n}\n.errPage-container .pan-gif[data-v-1c485e74] {\n margin: 0 auto;\n display: block;\n}\n.errPage-container .pan-img[data-v-1c485e74] {\n display: block;\n margin: 0 auto;\n}\n.errPage-container .text-jumbo[data-v-1c485e74] {\n font-size: 60px;\n font-weight: 700;\n color: #484848;\n}\n.errPage-container .list-unstyled[data-v-1c485e74] {\n font-size: 14px;\n}\n.errPage-container .list-unstyled li[data-v-1c485e74] {\n padding-bottom: 5px;\n}\n.errPage-container .list-unstyled a[data-v-1c485e74] {\n color: #008489;\n text-decoration: none;\n}\n.errPage-container .list-unstyled a[data-v-1c485e74]:hover {\n text-decoration: underline;\n}\n",""])},eRLo:function(t,a,n){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var e=n("MOmO"),i=n.n(e),r={name:"page401",data:function(){return{errGif:i.a+"?"+ +new Date,ewizardClap:"https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646",dialogVisible:!1}},methods:{back:function(){this.$route.query.noGoBack?this.$router.push({path:"/dashboard"}):this.$router.go(-1)}}},o={render:function(){var t=this,a=t.$createElement,n=t._self._c||a;return n("div",{staticClass:"errPage-container"},[n("el-button",{staticClass:"pan-back-btn",attrs:{icon:"arrow-left"},on:{click:t.back}},[t._v("返回")]),t._v(" "),n("el-row",[n("el-col",{attrs:{span:12}},[n("h1",{staticClass:"text-jumbo text-ginormous"},[t._v("Oops!")]),t._v("\n gif来源"),n("a",{attrs:{href:"https://zh.airbnb.com/",target:"_blank"}},[t._v("airbnb")]),t._v(" 页面\n "),n("h2",[t._v("你没有权限去该页面")]),t._v(" "),n("h6",[t._v("如有不满请联系你领导")]),t._v(" "),n("ul",{staticClass:"list-unstyled"},[n("li",[t._v("或者你可以去:")]),t._v(" "),n("li",{staticClass:"link-type"},[n("router-link",{attrs:{to:"/dashboard"}},[t._v("回首页")])],1),t._v(" "),n("li",{staticClass:"link-type"},[n("a",{attrs:{href:"https://www.taobao.com/"}},[t._v("随便看看")])]),t._v(" "),n("li",[n("a",{attrs:{href:"#"},on:{click:function(a){a.preventDefault(),t.dialogVisible=!0}}},[t._v("点我看图")])])])]),t._v(" "),n("el-col",{attrs:{span:12}},[n("img",{attrs:{src:t.errGif,width:"313",height:"428",alt:"Girl has dropped her ice cream."}})])],1),t._v(" "),n("el-dialog",{attrs:{title:"随便看",visible:t.dialogVisible},on:{"update:visible":function(a){t.dialogVisible=a}}},[n("img",{staticClass:"pan-img",attrs:{src:t.ewizardClap}})])],1)},staticRenderFns:[]};var s=n("VU/8")(r,o,!1,function(t){n("2aNK")},"data-v-1c485e74",null);a.default=s.exports}}); -------------------------------------------------------------------------------- /public/static/js/31.083409a324e4f31da9ad.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([31],{Fx1r:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i={name:"tinymce-demo",components:{Tinymce:n("5aCZ").a},data:function(){return{content:'

Welcome to the TinyMCE demo!

TinyMCE Logo

'}}},o={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"components-container"},[n("code",[t._v("\n "+t._s(t.$t("components.tinymceTips"))+"\n "),n("a",{staticClass:"link-type",attrs:{target:"_blank",href:"https://panjiachen.github.io/vue-element-admin-site/#/rich-editor"}},[t._v(" "+t._s(t.$t("components.documentation")))])]),t._v(" "),n("div",[n("tinymce",{attrs:{height:300},model:{value:t.content,callback:function(e){t.content=e},expression:"content"}})],1),t._v(" "),n("div",{staticClass:"editor-content",domProps:{innerHTML:t._s(t.content)}})])},staticRenderFns:[]};var a=n("VU/8")(i,o,!1,function(t){n("vavH")},"data-v-b4b191a8",null);e.default=a.exports},SfsB:function(t,e,n){(t.exports=n("FZ+f")(!1)).push([t.i,"\n.editor-content[data-v-b4b191a8]{\n margin-top: 20px;\n}\n",""])},vavH:function(t,e,n){var i=n("SfsB");"string"==typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);n("rjj0")("09c310ca",i,!0)}}); -------------------------------------------------------------------------------- /public/static/js/32.0438da92f8b0246edd6d.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([32],{"2Pjr":function(t,a,i){var n=i("aVp1");"string"==typeof n&&(n=[[t.i,n,""]]),n.locals&&(t.exports=n.locals);i("rjj0")("020d2a80",n,!0)},aVp1:function(t,a,i){(t.exports=i("FZ+f")(!1)).push([t.i,"\n.chart-container[data-v-88ee5b00]{\n position: relative;\n padding: 20px;\n width: 100%;\n height: 85vh;\n}\n",""])},vGRE:function(t,a,i){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var n=i("XLwt"),e=i.n(n),r={mixins:[i("0W7K").a],props:{className:{type:String,default:"chart"},id:{type:String,default:"chart"},width:{type:String,default:"200px"},height:{type:String,default:"200px"}},data:function(){return{chart:null}},mounted:function(){this.initChart()},beforeDestroy:function(){this.chart&&(this.chart.dispose(),this.chart=null)},methods:{initChart:function(){this.chart=e.a.init(document.getElementById(this.id));for(var t=[],a=[],i=[],n=0;n<50;n++)t.push(n),a.push(5*(Math.sin(n/5)*(n/5-10)+n/6)),i.push(3*(Math.sin(n/5)*(n/5+10)+n/6));this.chart.setOption({backgroundColor:"#08263a",xAxis:[{show:!1,data:t},{show:!1,data:t}],visualMap:{show:!1,min:0,max:50,dimension:0,inRange:{color:["#4a657a","#308e92","#b1cfa5","#f5d69f","#f5898b","#ef5055"]}},yAxis:{axisLine:{show:!1},axisLabel:{textStyle:{color:"#4a657a"}},splitLine:{show:!0,lineStyle:{color:"#08263f"}},axisTick:{show:!1}},series:[{name:"back",type:"bar",data:i,z:1,itemStyle:{normal:{opacity:.4,barBorderRadius:5,shadowBlur:3,shadowColor:"#111"}}},{name:"Simulate Shadow",type:"line",data:a,z:2,showSymbol:!1,animationDelay:0,animationEasing:"linear",animationDuration:1200,lineStyle:{normal:{color:"transparent"}},areaStyle:{normal:{color:"#08263a",shadowBlur:50,shadowColor:"#000"}}},{name:"front",type:"bar",data:a,xAxisIndex:1,z:3,itemStyle:{normal:{barBorderRadius:5}}}],animationEasing:"elasticOut",animationEasingUpdate:"elasticOut",animationDelay:function(t){return 20*t},animationDelayUpdate:function(t){return 20*t}})}}},s={render:function(){var t=this.$createElement;return(this._self._c||t)("div",{class:this.className,style:{height:this.height,width:this.width},attrs:{id:this.id}})},staticRenderFns:[]},o={name:"keyboardChart",components:{Chart:i("VU/8")(r,s,!1,null,null,null).exports}},l={render:function(){var t=this.$createElement,a=this._self._c||t;return a("div",{staticClass:"chart-container"},[a("chart",{attrs:{height:"100%",width:"100%"}})],1)},staticRenderFns:[]};var h=i("VU/8")(o,l,!1,function(t){i("2Pjr")},"data-v-88ee5b00",null);a.default=h.exports}}); -------------------------------------------------------------------------------- /public/static/js/34.ec5f53056ffff3d9f9f3.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([34],{FS2D:function(n,e,t){var i=t("Z7kv");"string"==typeof i&&(i=[[n.i,i,""]]),i.locals&&(n.exports=i.locals);t("rjj0")("5aac7248",i,!0)},Z7kv:function(n,e,t){(n.exports=t("FZ+f")(!1)).push([n.i,"\n.social-signup-container[data-v-77e3040d] {\n margin: 20px 0;\n}\n.social-signup-container .sign-btn[data-v-77e3040d] {\n display: inline-block;\n cursor: pointer;\n}\n.social-signup-container .icon[data-v-77e3040d] {\n color: #fff;\n font-size: 30px;\n margin-top: 6px;\n}\n.social-signup-container .wx-svg-container[data-v-77e3040d],\n .social-signup-container .qq-svg-container[data-v-77e3040d] {\n display: inline-block;\n width: 40px;\n height: 40px;\n line-height: 40px;\n text-align: center;\n padding-top: 1px;\n border-radius: 4px;\n margin-bottom: 20px;\n margin-right: 5px;\n}\n.social-signup-container .wx-svg-container[data-v-77e3040d] {\n background-color: #8dc349;\n}\n.social-signup-container .qq-svg-container[data-v-77e3040d] {\n background-color: #6BA2D6;\n margin-left: 50px;\n}\n",""])},dZXH:function(n,e,t){"use strict";function i(n,e,t,i){var o=void 0!==window.screenLeft?window.screenLeft:screen.left,c=void 0!==window.screenTop?window.screenTop:screen.top,a=(window.innerWidth?window.innerWidth:document.documentElement.clientWidth?document.documentElement.clientWidth:screen.width)/2-t/2+o,s=(window.innerHeight?window.innerHeight:document.documentElement.clientHeight?document.documentElement.clientHeight:screen.height)/2-i/2+c,r=window.open(n,e,"toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width="+t+", height="+i+", top="+s+", left="+a);window.focus&&r.focus()}Object.defineProperty(e,"__esModule",{value:!0});var o={name:"social-signin",methods:{wechatHandleClick:function(n){this.$store.commit("SET_AUTH_TYPE",n);i("https://open.weixin.qq.com/connect/qrconnect?appid=xxxxx&redirect_uri="+encodeURIComponent("xxx/redirect?redirect="+window.location.origin+"/authredirect")+"&response_type=code&scope=snsapi_login#wechat_redirect",n,540,540)},tencentHandleClick:function(n){this.$store.commit("SET_AUTH_TYPE",n);i("https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=xxxxx&redirect_uri="+encodeURIComponent("xxx/redirect?redirect="+window.location.origin+"/authredirect"),n,540,540)}}},c={render:function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"social-signup-container"},[t("div",{staticClass:"sign-btn",on:{click:function(e){n.wechatHandleClick("wechat")}}},[t("span",{staticClass:"wx-svg-container"},[t("svg-icon",{staticClass:"icon",attrs:{"icon-class":"wechat"}})],1),n._v(" 微信\n ")]),n._v(" "),t("div",{staticClass:"sign-btn",on:{click:function(e){n.tencentHandleClick("tencent")}}},[t("span",{staticClass:"qq-svg-container"},[t("svg-icon",{staticClass:"icon",attrs:{"icon-class":"qq"}})],1),n._v(" QQ\n ")])])},staticRenderFns:[]};var a=t("VU/8")(o,c,!1,function(n){t("FS2D")},"data-v-77e3040d",null);e.default=a.exports}}); -------------------------------------------------------------------------------- /public/static/js/37.3fedb74047a770badf1a.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([37],{"1Rx3":function(a,t,e){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=e("wxe2"),n=e("bEjd"),s=e("7EAa"),l=e("+xof"),d=e("k96P"),o=e("Eoil"),i=e("Ndbe"),c=e("jfHn"),p=e("1uyy"),u={newVisitis:{expectedData:[100,120,161,134,105,160,165],actualData:[120,82,91,154,162,140,145]},messages:{expectedData:[200,192,120,144,160,130,140],actualData:[180,160,151,106,145,150,130]},purchases:{expectedData:[80,100,121,104,105,90,100],actualData:[120,90,100,138,142,130,130]},shoppings:{expectedData:[130,140,141,142,145,150,160],actualData:[120,82,91,154,162,140,130]}},h={name:"dashboard-admin",components:{GithubCorner:r.a,PanelGroup:n.default,LineChart:s.default,RaddarChart:l.default,PieChart:d.default,BarChart:o.default,TransactionTable:i.default,TodoList:c.default,BoxCard:p.default},data:function(){return{lineChartData:u.newVisitis}},methods:{handleSetLineChartData:function(a){this.lineChartData=u[a]}}},f={render:function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("div",{staticClass:"dashboard-editor-container"},[e("github-corner"),a._v(" "),e("panel-group",{on:{handleSetLineChartData:a.handleSetLineChartData}}),a._v(" "),e("el-row",{staticStyle:{background:"#fff",padding:"16px 16px 0","margin-bottom":"32px"}},[e("line-chart",{attrs:{"chart-data":a.lineChartData}})],1),a._v(" "),e("el-row",{attrs:{gutter:32}},[e("el-col",{attrs:{xs:24,sm:24,lg:8}},[e("div",{staticClass:"chart-wrapper"},[e("raddar-chart")],1)]),a._v(" "),e("el-col",{attrs:{xs:24,sm:24,lg:8}},[e("div",{staticClass:"chart-wrapper"},[e("pie-chart")],1)]),a._v(" "),e("el-col",{attrs:{xs:24,sm:24,lg:8}},[e("div",{staticClass:"chart-wrapper"},[e("bar-chart")],1)])],1),a._v(" "),e("el-row",{attrs:{gutter:8}},[e("el-col",{staticStyle:{"padding-right":"8px","margin-bottom":"30px"},attrs:{xs:{span:24},sm:{span:24},md:{span:24},lg:{span:12},xl:{span:12}}},[e("transaction-table")],1),a._v(" "),e("el-col",{attrs:{xs:{span:12},sm:{span:12},md:{span:12},lg:{span:6},xl:{span:5}}},[e("todo-list")],1),a._v(" "),e("el-col",{attrs:{xs:{span:12},sm:{span:12},md:{span:12},lg:{span:6},xl:{span:5}}},[e("box-card")],1)],1)],1)},staticRenderFns:[]};var x=e("VU/8")(h,f,!1,function(a){e("4rXP")},"data-v-383e8e70",null);t.default=x.exports},"4rXP":function(a,t,e){var r=e("53lJ");"string"==typeof r&&(r=[[a.i,r,""]]),r.locals&&(a.exports=r.locals);e("rjj0")("b5136818",r,!0)},"53lJ":function(a,t,e){(a.exports=e("FZ+f")(!1)).push([a.i,"\n.dashboard-editor-container[data-v-383e8e70] {\n padding: 32px;\n background-color: #f0f2f5;\n}\n.dashboard-editor-container .chart-wrapper[data-v-383e8e70] {\n background: #fff;\n padding: 16px 16px 0;\n margin-bottom: 32px;\n}\n",""])}}); -------------------------------------------------------------------------------- /public/static/js/39.ee6ce5803307ff5cbed7.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([39],{"0WvE":function(n,a,t){(n.exports=t("FZ+f")(!1)).push([n.i,"\n.emptyGif[data-v-0f338bc4] {\n display: block;\n width: 45%;\n margin: 0 auto;\n}\n.dashboard-editor-container[data-v-0f338bc4] {\n background-color: #e3e3e3;\n min-height: 100vh;\n padding: 50px 60px 0px;\n}\n.dashboard-editor-container .pan-info-roles[data-v-0f338bc4] {\n font-size: 12px;\n font-weight: 700;\n color: #333;\n display: block;\n}\n.dashboard-editor-container .info-container[data-v-0f338bc4] {\n position: relative;\n margin-left: 190px;\n height: 150px;\n line-height: 200px;\n}\n.dashboard-editor-container .info-container .display_name[data-v-0f338bc4] {\n font-size: 48px;\n line-height: 48px;\n color: #212121;\n position: absolute;\n top: 25px;\n}\n",""])},DY7s:function(n,a,t){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var e=t("Dd8w"),i=t.n(e),o=t("NYxO"),s=t("kCe2"),r=t("wxe2"),d={name:"dashboard-editor",components:{PanThumb:s.a,GithubCorner:r.a},data:function(){return{emptyGif:"https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3"}},computed:i()({},Object(o.b)(["name","avatar","roles"]))},c={render:function(){var n=this,a=n.$createElement,t=n._self._c||a;return t("div",{staticClass:"dashboard-editor-container"},[t("div",{staticClass:" clearfix"},[t("pan-thumb",{staticStyle:{float:"left"},attrs:{image:n.avatar}},[n._v(" Your roles:\n "),n._l(n.roles,function(a){return t("span",{key:a,staticClass:"pan-info-roles"},[n._v(n._s(a))])})],2),n._v(" "),t("github-corner"),n._v(" "),t("div",{staticClass:"info-container"},[t("span",{staticClass:"display_name"},[n._v(n._s(n.name))]),n._v(" "),t("span",{staticStyle:{"font-size":"20px","padding-top":"20px",display:"inline-block"}},[n._v("editor : dashboard")])])],1),n._v(" "),t("div",[t("img",{staticClass:"emptyGif",attrs:{src:n.emptyGif}})])])},staticRenderFns:[]};var l=t("VU/8")(d,c,!1,function(n){t("ngpk")},"data-v-0f338bc4",null);a.default=l.exports},ngpk:function(n,a,t){var e=t("0WvE");"string"==typeof e&&(e=[[n.i,e,""]]),e.locals&&(n.exports=e.locals);t("rjj0")("27cba980",e,!0)}}); -------------------------------------------------------------------------------- /public/static/js/41.6c5429798933a5e742bd.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([41],{VuMv:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("viA7"),i={name:"exportZip",data:function(){return{list:null,listLoading:!0,downloadLoading:!1,filename:""}},created:function(){this.fetchData()},methods:{fetchData:function(){var t=this;this.listLoading=!0,Object(a.c)().then(function(e){t.list=e.data.items,t.listLoading=!1})},handleDownload:function(){var t=this;this.downloadLoading=!0,n.e(64).then(n.bind(null,"hNCb")).then(function(e){var n=t.list,a=t.formatJson(["id","title","author","pageviews","display_time"],n);e.export_txt_to_zip(["Id","Title","Author","Readings","Date"],a,t.filename,t.filename),t.downloadLoading=!1})},formatJson:function(t,e){return e.map(function(e){return t.map(function(t){return e[t]})})}}},l={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"app-container"},[n("el-input",{staticStyle:{width:"300px"},attrs:{placeholder:t.$t("zip.placeholder"),"prefix-icon":"el-icon-document"},model:{value:t.filename,callback:function(e){t.filename=e},expression:"filename"}}),t._v(" "),n("el-button",{staticStyle:{"margin-bottom":"20px"},attrs:{type:"primary",icon:"document",loading:t.downloadLoading},on:{click:t.handleDownload}},[t._v(t._s(t.$t("zip.export"))+" zip")]),t._v(" "),n("el-table",{directives:[{name:"loading",rawName:"v-loading.body",value:t.listLoading,expression:"listLoading",modifiers:{body:!0}}],attrs:{data:t.list,"element-loading-text":"拼命加载中",border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{attrs:{align:"center",label:"ID",width:"95"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(e.$index)+"\n ")]}}])}),t._v(" "),n("el-table-column",{attrs:{label:"Title"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(e.row.title)+"\n ")]}}])}),t._v(" "),n("el-table-column",{attrs:{label:"Author",width:"95",align:"center"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("el-tag",[t._v(t._s(e.row.author))])]}}])}),t._v(" "),n("el-table-column",{attrs:{label:"Readings",width:"115",align:"center"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(e.row.pageviews)+"\n ")]}}])}),t._v(" "),n("el-table-column",{attrs:{align:"center",label:"Date",width:"220"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("i",{staticClass:"el-icon-time"}),t._v(" "),n("span",[t._v(t._s(e.row.display_time))])]}}])})],1)],1)},staticRenderFns:[]},o=n("VU/8")(i,l,!1,null,null,null);e.default=o.exports}}); -------------------------------------------------------------------------------- /public/static/js/42.aad19d829f1525196a06.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([42],{nOMn:function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=a("//Fk"),i=a.n(n),o=a("EX+S"),l={data:function(){return{dataObj:{token:"",key:""},image_uri:[],fileList:[]}},methods:{beforeUpload:function(){var t=this;return new i.a(function(e,a){Object(o.a)().then(function(a){var n=a.data.qiniu_key,i=a.data.qiniu_token;t._data.dataObj.token=i,t._data.dataObj.key=n,e(!0)}).catch(function(t){console.log(t),a(!1)})})}}},s={render:function(){var t=this.$createElement,e=this._self._c||t;return e("el-upload",{attrs:{action:"https://upload.qbox.me",data:this.dataObj,drag:"",multiple:!0,"before-upload":this.beforeUpload}},[e("i",{staticClass:"el-icon-upload"}),this._v(" "),e("div",{staticClass:"el-upload__text"},[this._v("将文件拖到此处,或"),e("em",[this._v("点击上传")])])])},staticRenderFns:[]},u=a("VU/8")(l,s,!1,null,null,null);e.default=u.exports}}); -------------------------------------------------------------------------------- /public/static/js/43.f681da8d65449515125f.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([43],{rbgu:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={name:"createForm",components:{AccountEditor:n("/s8l").default}},c={render:function(){var e=this.$createElement;return(this._self._c||e)("account-editor",{attrs:{"is-edit":!1}})},staticRenderFns:[]},s=n("VU/8")(r,c,!1,null,null,null);t.default=s.exports}}); -------------------------------------------------------------------------------- /public/static/js/44.a6f9c496b2cd6151bab9.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([44],{Seyn:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={name:"createForm",components:{AccountEditor:n("/s8l").default}},c={render:function(){var e=this.$createElement;return(this._self._c||e)("account-editor",{attrs:{"is-edit":!0}})},staticRenderFns:[]},s=n("VU/8")(r,c,!1,null,null,null);t.default=s.exports}}); -------------------------------------------------------------------------------- /public/static/js/45.909fae5661195bb66539.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([45],{esQe:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=n("nv77"),a={props:{type:{type:String,default:"all"}},data:function(){return{list:null,loading:!1}},created:function(){this.getList()},methods:{del:function(t){var e=this;confirm("确定要删除这个公众号?")&&Object(l.b)(t).then(function(t){e.getList()})},getList:function(){var t=this;this.loading=!0,this.$emit("create"),Object(l.d)().then(function(e){t.list=e.data.public_accounts,t.loading=!1})}}},i={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("el-table",{staticStyle:{width:"100%"},attrs:{data:t.list,border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{directives:[{name:"loading",rawName:"v-loading",value:t.loading,expression:"loading"}],attrs:{align:"center",label:"ID",width:"65","element-loading-text":"加载中"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.id))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"130px",align:"center",label:"名称"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.name))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"150px",align:"center",label:"账号"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.account))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"110px",align:"center",label:"appID"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.appid))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"110px",align:"center",label:"Secret"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.appsecret))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"min-width":"180px",label:"创建时间"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.created_at))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"class-name":"status-col",label:"操作",width:"110"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("router-link",{attrs:{to:"/public_account/edit/"+e.row.id}},[t._v("编辑")]),t._v(" "),n("a",{on:{click:function(n){t.del(e.row.id)}}},[t._v("删除")])]}}])})],1)},staticRenderFns:[]},o=n("VU/8")(a,i,!1,null,null,null);e.default=o.exports}}); -------------------------------------------------------------------------------- /public/static/js/46.73c0807083516474f1a4.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([46],{V9V6:function(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=s("Dd8w"),i=s.n(n),o=s("NYxO"),r={name:"permission",data:function(){return{switchRoles:""}},computed:i()({},Object(o.b)(["roles"])),watch:{switchRoles:function(e){var t=this;this.$store.dispatch("ChangeRoles",e).then(function(){t.$router.push({path:"/permission/index?"+ +new Date})})}}},l={render:function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"app-container"},[s("div",{staticStyle:{"margin-bottom":"15px"}},[e._v(e._s(e.$t("permission.roles"))+": "+e._s(e.roles))]),e._v("\n "+e._s(e.$t("permission.switchRoles"))+":\n "),s("el-radio-group",{model:{value:e.switchRoles,callback:function(t){e.switchRoles=t},expression:"switchRoles"}},[s("el-radio-button",{attrs:{label:"editor"}})],1)],1)},staticRenderFns:[]},a=s("VU/8")(r,l,!1,null,null,null);t.default=a.exports}}); -------------------------------------------------------------------------------- /public/static/js/47.ab57a2ae83266d3bdbca.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([47],{"+abo":function(e,n,o){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var l={name:"authredirect",created:function(){var e=window.location.search.slice(1);window.opener.location.href=window.location.origin+"/login#"+e,window.close()}},i=o("VU/8")(l,null,!1,null,null,null);n.default=i.exports}}); -------------------------------------------------------------------------------- /public/static/js/48.0580e34abd87ee02a658.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([48],{qDRm:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var l={name:"editForm",components:{ArticleDetail:n("f15a").default}},r={render:function(){var e=this.$createElement;return(this._self._c||e)("article-detail",{attrs:{"is-edit":!0}})},staticRenderFns:[]},a=n("VU/8")(l,r,!1,null,null,null);t.default=a.exports}}); -------------------------------------------------------------------------------- /public/static/js/49.8468d7d0e0431d39f0c4.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([49],{uoWj:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={name:"createForm",components:{ArticleDetail:n("f15a").default}},l={render:function(){var e=this.$createElement;return(this._self._c||e)("article-detail",{attrs:{"is-edit":!1}})},staticRenderFns:[]},a=n("VU/8")(r,l,!1,null,null,null);t.default=a.exports}}); -------------------------------------------------------------------------------- /public/static/js/50.523e1fc86e72c1f11582.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([50],{zNV3:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var l=n("viA7"),a={name:"selectExcel",data:function(){return{list:null,listLoading:!0,multipleSelection:[],downloadLoading:!1,filename:""}},created:function(){this.fetchData()},methods:{fetchData:function(){var e=this;this.listLoading=!0,Object(l.c)(this.listQuery).then(function(t){e.list=t.data.items,e.listLoading=!1})},handleSelectionChange:function(e){this.multipleSelection=e},handleDownload:function(){var e=this;this.multipleSelection.length?(this.downloadLoading=!0,Promise.all([n.e(3),n.e(63)]).then(n.bind(null,"zWO4")).then(function(t){var n=e.multipleSelection,l=e.formatJson(["id","title","author","pageviews","display_time"],n);t.export_json_to_excel(["Id","Title","Author","Readings","Date"],l,e.filename),e.$refs.multipleTable.clearSelection(),e.downloadLoading=!1})):this.$message({message:"Please select at least one item",type:"warning"})},formatJson:function(e,t){return t.map(function(t){return e.map(function(e){return t[e]})})}}},i={render:function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-container"},[n("el-input",{staticStyle:{width:"340px"},attrs:{placeholder:e.$t("excel.placeholder"),"prefix-icon":"el-icon-document"},model:{value:e.filename,callback:function(t){e.filename=t},expression:"filename"}}),e._v(" "),n("el-button",{staticStyle:{"margin-bottom":"20px"},attrs:{type:"primary",icon:"document",loading:e.downloadLoading},on:{click:e.handleDownload}},[e._v(e._s(e.$t("excel.selectedExport")))]),e._v(" "),n("el-table",{directives:[{name:"loading",rawName:"v-loading.body",value:e.listLoading,expression:"listLoading",modifiers:{body:!0}}],ref:"multipleTable",attrs:{data:e.list,"element-loading-text":"拼命加载中",border:"",fit:"","highlight-current-row":""},on:{"selection-change":e.handleSelectionChange}},[n("el-table-column",{attrs:{type:"selection",align:"center"}}),e._v(" "),n("el-table-column",{attrs:{align:"center",label:"Id",width:"95"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.$index)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Title"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.title)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Author",width:"110",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("el-tag",[e._v(e._s(t.row.author))])]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Readings",width:"115",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.pageviews)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{align:"center",label:"PDate",width:"220"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("i",{staticClass:"el-icon-time"}),e._v(" "),n("span",[e._v(e._s(t.row.display_time))])]}}])})],1)],1)},staticRenderFns:[]},o=n("VU/8")(a,i,!1,null,null,null);t.default=o.exports}}); -------------------------------------------------------------------------------- /public/static/js/51.b1e224295159fb12b66c.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([51],{oz0I:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var l=n("viA7"),a=n("0xDb"),i={name:"exportExcel",data:function(){return{list:null,listLoading:!0,downloadLoading:!1,filename:""}},created:function(){this.fetchData()},methods:{fetchData:function(){var e=this;this.listLoading=!0,Object(l.c)().then(function(t){e.list=t.data.items,e.listLoading=!1})},handleDownload:function(){var e=this;this.downloadLoading=!0,Promise.all([n.e(3),n.e(63)]).then(n.bind(null,"zWO4")).then(function(t){var n=e.list,l=e.formatJson(["id","title","author","pageviews","display_time"],n);t.export_json_to_excel(["Id","Title","Author","Readings","Date"],l,e.filename),e.downloadLoading=!1})},formatJson:function(e,t){return t.map(function(t){return e.map(function(e){return"timestamp"===e?Object(a.b)(t[e]):t[e]})})}}},o={render:function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-container"},[n("el-input",{staticStyle:{width:"340px"},attrs:{placeholder:e.$t("excel.placeholder"),"prefix-icon":"el-icon-document"},model:{value:e.filename,callback:function(t){e.filename=t},expression:"filename"}}),e._v(" "),n("el-button",{staticStyle:{"margin-bottom":"20px"},attrs:{type:"primary",icon:"document",loading:e.downloadLoading},on:{click:e.handleDownload}},[e._v(e._s(e.$t("excel.export"))+" excel")]),e._v(" "),n("el-table",{directives:[{name:"loading",rawName:"v-loading.body",value:e.listLoading,expression:"listLoading",modifiers:{body:!0}}],attrs:{data:e.list,"element-loading-text":"拼命加载中",border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{attrs:{align:"center",label:"Id",width:"95"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.$index)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Title"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.title)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Author",width:"110",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("el-tag",[e._v(e._s(t.row.author))])]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Readings",width:"115",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.pageviews)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{align:"center",label:"Date",width:"220"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("i",{staticClass:"el-icon-time"}),e._v(" "),n("span",[e._v(e._s(e._f("parseTime")(t.row.timestamp,"{y}-{m}-{d} {h}:{i}")))])]}}])})],1)],1)},staticRenderFns:[]},r=n("VU/8")(i,o,!1,null,null,null);t.default=r.exports}}); -------------------------------------------------------------------------------- /public/static/js/52.ca61fc721e5420181995.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([52],{plNp:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a={render:function(){var e=this.$createElement,t=this._self._c||e;return t("transition",{attrs:{name:"fade",mode:"out-in"}},[t("keep-alive",{attrs:{include:this.cachedViews}},[t("router-view")],1)],1)},staticRenderFns:[]},i=n("VU/8")({name:"TableMain",computed:{cachedViews:function(){return this.$store.state.tagsView.cachedViews}}},a,!1,null,null,null);t.default=i.exports}}); -------------------------------------------------------------------------------- /public/static/js/53.1609bd4f497ec249dce1.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([53],{"k+/a":function(a,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n={render:function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("div",{staticClass:"app-container"},[t("div",{staticClass:"filter-container"},[t("el-checkbox-group",{model:{value:a.formThead,callback:function(e){a.formThead=e},expression:"formThead"}},[t("el-checkbox",{attrs:{label:"apple"}},[a._v("apple")]),a._v(" "),t("el-checkbox",{attrs:{label:"banana"}},[a._v("banana")]),a._v(" "),t("el-checkbox",{attrs:{label:"orange"}},[a._v("orange")])],1)],1),a._v(" "),t("el-table",{staticStyle:{width:"100%"},attrs:{data:a.tableData,border:"",fit:"","highlight-current-row":""}},[t("el-table-column",{attrs:{prop:"name",label:"fruitName",width:"180"}}),a._v(" "),a._l(a.formThead,function(e){return t("el-table-column",{key:e,attrs:{label:e},scopedSlots:a._u([{key:"default",fn:function(t){return[a._v("\n "+a._s(t.row[e])+"\n ")]}}])})})],2)],1)},staticRenderFns:[]},l=t("VU/8")({data:function(){return{tableData:[{name:"fruit-1",apple:"apple-10",banana:"banana-10",orange:"orange-10"},{name:"fruit-2",apple:"apple-20",banana:"banana-20",orange:"orange-20"}],formThead:["apple","banana"]}}},n,!1,null,null,null);e.default=l.exports}}); -------------------------------------------------------------------------------- /public/static/js/54.50b3bb605bc81a107ccc.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([54],{SKUv:function(a,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=["apple","banana"],l={data:function(){return{tableData:[{name:"fruit-1",apple:"apple-10",banana:"banana-10",orange:"orange-10"},{name:"fruit-2",apple:"apple-20",banana:"banana-20",orange:"orange-20"}],key:1,formTheadOptions:["apple","banana","orange"],checkboxVal:n,formThead:n}},watch:{checkboxVal:function(a){this.formThead=this.formTheadOptions.filter(function(e){return a.indexOf(e)>=0}),this.key=this.key+1}}},r={render:function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("div",{staticClass:"app-container"},[t("div",{staticClass:"filter-container"},[t("el-checkbox-group",{model:{value:a.checkboxVal,callback:function(e){a.checkboxVal=e},expression:"checkboxVal"}},[t("el-checkbox",{attrs:{label:"apple"}},[a._v("apple")]),a._v(" "),t("el-checkbox",{attrs:{label:"banana"}},[a._v("banana")]),a._v(" "),t("el-checkbox",{attrs:{label:"orange"}},[a._v("orange")])],1)],1),a._v(" "),t("el-table",{key:a.key,staticStyle:{width:"100%"},attrs:{data:a.tableData,border:"",fit:"","highlight-current-row":""}},[t("el-table-column",{attrs:{prop:"name",label:"fruitName",width:"180"}}),a._v(" "),a._l(a.formThead,function(e){return t("el-table-column",{key:e,attrs:{label:e},scopedSlots:a._u([{key:"default",fn:function(t){return[a._v("\n "+a._s(t.row[e])+"\n ")]}}])})})],2)],1)},staticRenderFns:[]},o=t("VU/8")(l,r,!1,null,null,null);e.default=o.exports}}); -------------------------------------------------------------------------------- /public/static/js/55.b35c7faec6edb3d3f0f2.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([55],{"+NrA":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=n("viA7"),a={props:{type:{type:String,default:"CN"}},data:function(){return{list:null,listQuery:{page:1,limit:5,type:this.type,sort:"+id"},loading:!1}},filters:{statusFilter:function(t){return{published:"success",draft:"info",deleted:"danger"}[t]}},created:function(){this.getList()},methods:{getList:function(){var t=this;this.loading=!0,this.$emit("create"),Object(l.c)(this.listQuery).then(function(e){t.list=e.data.items,t.loading=!1})}}},s={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("el-table",{staticStyle:{width:"100%"},attrs:{data:t.list,border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{directives:[{name:"loading",rawName:"v-loading",value:t.loading,expression:"loading"}],attrs:{align:"center",label:"ID",width:"65","element-loading-text":"请给我点时间!"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.id))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"180px",align:"center",label:"Date"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(t._f("parseTime")(e.row.timestamp,"{y}-{m}-{d} {h}:{i}")))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"min-width":"300px",label:"Title"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.title))]),t._v(" "),n("el-tag",[t._v(t._s(e.row.type))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"110px",align:"center",label:"Author"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.author))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"120px",label:"Importance"},scopedSlots:t._u([{key:"default",fn:function(e){return t._l(+e.row.importance,function(t){return n("svg-icon",{key:t,attrs:{"icon-class":"star"}})})}}])}),t._v(" "),n("el-table-column",{attrs:{align:"center",label:"Readings",width:"95"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.pageviews))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"class-name":"status-col",label:"Status",width:"110"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("el-tag",{attrs:{type:t._f("statusFilter")(e.row.status)}},[t._v(t._s(e.row.status))])]}}])})],1)},staticRenderFns:[]},i=n("VU/8")(a,s,!1,null,null,null);e.default=i.exports}}); -------------------------------------------------------------------------------- /public/static/js/56.e1c6e0bb1c5348cdf8d5.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([56],{it3z:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={created:function(){this.b=b}},i={render:function(){var e=this.$createElement;return(this._self._c||e)("div")},staticRenderFns:[]},l=n("VU/8")(r,i,!1,null,null,null);t.default=l.exports}}); -------------------------------------------------------------------------------- /public/static/js/57.309813805e444a862bb5.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([57],{XuU3:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={render:function(){var e=this.$createElement;return(this._self._c||e)("div",[this._v("\n "+this._s(this.a.a)+"\n ")])},staticRenderFns:[]},s=n("VU/8")({name:"errorTestA"},r,!1,null,null,null);t.default=s.exports}}); -------------------------------------------------------------------------------- /public/static/js/58.3b57dcecdda7f3784325.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([58],{SSzF:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={name:"createForm",components:{ActivityEditor:n("DlHa").default}},i={render:function(){var e=this.$createElement;return(this._self._c||e)("activity-editor",{attrs:{"is-edit":!1}})},staticRenderFns:[]},a=n("VU/8")(r,i,!1,null,null,null);t.default=a.exports}}); -------------------------------------------------------------------------------- /public/static/js/59.1513bd1147b53441889f.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([59],{qp82:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={name:"createForm",components:{ActivityEditor:n("DlHa").default}},i={render:function(){var e=this.$createElement;return(this._self._c||e)("activity-editor",{attrs:{"is-edit":!0}})},staticRenderFns:[]},a=n("VU/8")(r,i,!1,null,null,null);t.default=a.exports}}); -------------------------------------------------------------------------------- /public/static/js/60.4da6604318400d2cdc0c.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([60],{eI3e:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=n("Ty/O"),a={props:{type:{type:String,default:"all"}},data:function(){return{list:null,loading:!1}},created:function(){this.getList()},methods:{del:function(t){var e=this;confirm("确定要删除这个活动?")&&Object(l.b)(t).then(function(t){e.getList()})},getList:function(){var t=this;this.loading=!0,this.$emit("create"),Object(l.d)({}).then(function(e){console.log(e),t.list=e.data.activities,t.loading=!1})}}},i={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("el-table",{staticStyle:{width:"100%"},attrs:{data:t.list,border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{directives:[{name:"loading",rawName:"v-loading",value:t.loading,expression:"loading"}],attrs:{align:"center",label:"ID",width:"65","element-loading-text":"加载中"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.id))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"200px",align:"center",label:"活动名称"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.name))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"150px",align:"center",label:"公众号"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.public_account.name))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"110px",align:"center",label:"活动描述"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.desc))])]}}])}),t._v(" "),n("el-table-column",{attrs:{width:"120px",label:"专属序列号"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.idx))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"min-width":"180px",label:"创建时间"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",[t._v(t._s(e.row.created_at))])]}}])}),t._v(" "),n("el-table-column",{attrs:{"class-name":"status-col",label:"操作",width:"110"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("router-link",{attrs:{to:"/activity/edit/"+e.row.id}},[t._v("编辑")]),t._v(" "),n("a",{on:{click:function(n){t.del(e.row.id)}}},[t._v("删除")])]}}])})],1)},staticRenderFns:[]},o=n("VU/8")(a,i,!1,null,null,null);e.default=o.exports}}); -------------------------------------------------------------------------------- /public/static/js/manifest.b6fcd46717a62f0ca049.js: -------------------------------------------------------------------------------- 1 | !function(e){var a=window.webpackJsonp;window.webpackJsonp=function(c,b,n){for(var r,t,o,i=0,u=[];i code[class*="language-"], 58 | pre[class*="language-"] { 59 | background: #f5f2f0; 60 | } 61 | 62 | /* Inline code */ 63 | :not(pre) > code[class*="language-"] { 64 | padding: .1em; 65 | border-radius: .3em; 66 | } 67 | 68 | .token.comment, 69 | .token.prolog, 70 | .token.doctype, 71 | .token.cdata { 72 | color: slategray; 73 | } 74 | 75 | .token.punctuation { 76 | color: #999; 77 | } 78 | 79 | .namespace { 80 | opacity: .7; 81 | } 82 | 83 | .token.property, 84 | .token.tag, 85 | .token.boolean, 86 | .token.number, 87 | .token.constant, 88 | .token.symbol, 89 | .token.deleted { 90 | color: #905; 91 | } 92 | 93 | .token.selector, 94 | .token.attr-name, 95 | .token.string, 96 | .token.char, 97 | .token.builtin, 98 | .token.inserted { 99 | color: #690; 100 | } 101 | 102 | .token.operator, 103 | .token.entity, 104 | .token.url, 105 | .language-css .token.string, 106 | .style .token.string { 107 | color: #a67f59; 108 | background: hsla(0, 0%, 100%, .5); 109 | } 110 | 111 | .token.atrule, 112 | .token.attr-value, 113 | .token.keyword { 114 | color: #07a; 115 | } 116 | 117 | .token.function { 118 | color: #DD4A68; 119 | } 120 | 121 | .token.regex, 122 | .token.important, 123 | .token.variable { 124 | color: #e90; 125 | } 126 | 127 | .token.important, 128 | .token.bold { 129 | font-weight: bold; 130 | } 131 | .token.italic { 132 | font-style: italic; 133 | } 134 | 135 | .token.entity { 136 | cursor: help; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cool.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cool.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cry.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cry.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-embarassed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-embarassed.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-foot-in-mouth.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-foot-in-mouth.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-frown.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-frown.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-innocent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-innocent.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-kiss.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-kiss.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-laughing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-laughing.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-money-mouth.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-money-mouth.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-sealed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-sealed.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-smile.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-smile.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-surprised.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-surprised.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-tongue-out.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-tongue-out.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-undecided.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-undecided.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-wink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-wink.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/plugins/emoticons/img/smiley-yell.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-yell.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-mobile.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-mobile.woff -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.eot -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.ttf -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.woff -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.eot -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.ttf -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.woff -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/img/anchor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/img/anchor.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/img/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/img/loader.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/img/object.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/img/object.gif -------------------------------------------------------------------------------- /public/static/tinymce4.7.5/skins/lightgray/img/trans.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/static/tinymce4.7.5/skins/lightgray/img/trans.gif -------------------------------------------------------------------------------- /public/upload/invite_4_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_1.png -------------------------------------------------------------------------------- /public/upload/invite_4_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_11.png -------------------------------------------------------------------------------- /public/upload/invite_4_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_12.png -------------------------------------------------------------------------------- /public/upload/invite_4_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_13.png -------------------------------------------------------------------------------- /public/upload/invite_4_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_14.png -------------------------------------------------------------------------------- /public/upload/invite_4_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_15.png -------------------------------------------------------------------------------- /public/upload/invite_4_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_2.png -------------------------------------------------------------------------------- /public/upload/invite_4_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_4.png -------------------------------------------------------------------------------- /public/upload/invite_4_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_6.png -------------------------------------------------------------------------------- /public/upload/invite_4_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/public/upload/invite_4_8.png -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/test/controllers/.keep -------------------------------------------------------------------------------- /test/controllers/admin/logins_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class Admin::LoginsControllerTest < ActionController::TestCase 4 | setup do 5 | @user = create(:crop_user, company: create(:company)) 6 | end 7 | 8 | test 'test login' do 9 | post :create, account: @user.account, password: '123456' 10 | assert_response :success 11 | assert_equal 200, JSON.parse(response.body)['code'] 12 | end 13 | end -------------------------------------------------------------------------------- /test/controllers/admin/public_accounts_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class Admin::PublicAccountsControllerTest < ActionController::TestCase 4 | setup do 5 | @company = create(:company) 6 | @user = create(:crop_user, company: @company) 7 | @account = create(:public_account, company: @company) 8 | end 9 | 10 | test 'should get index' do 11 | get :index, Authentication: @user.token 12 | assert JSON.parse(response.body)['public_accounts'].length > 0 13 | end 14 | 15 | test 'should update a public account' do 16 | account = create(:public_account, company: @company) 17 | post :update, Authentication: @user.token, id: account, name: '123' 18 | account.reload 19 | assert_equal '123', account.name 20 | assert_response :success 21 | end 22 | 23 | test 'should raise permission error' do 24 | account = create(:public_account, company: create(:company)) 25 | post :update, Authentication: @user.token, id: account, name: '123' 26 | assert_equal 401, JSON.parse(response.body)['code'] 27 | end 28 | end -------------------------------------------------------------------------------- /test/factories/activities.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :activity do 3 | name "MyString" 4 | desc "MyText" 5 | consts "MyText" 6 | template "@_do_nothing = 1" 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /test/factories/article_types.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :article_type do 3 | 4 | end 5 | 6 | end 7 | -------------------------------------------------------------------------------- /test/factories/companies.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :company do 3 | name {(rand * 10000).to_i.to_s} 4 | 5 | enabled true 6 | end 7 | end -------------------------------------------------------------------------------- /test/factories/crop_users.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :crop_user do 3 | account {(rand*10000).to_i.to_s} 4 | password '123456' 5 | phone '18351921939' 6 | end 7 | end -------------------------------------------------------------------------------- /test/factories/events.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :event do 3 | event_type "MyString" 4 | action_type "MyString" 5 | condition "MyString" 6 | extra "MyString" 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /test/factories/media_resources.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :media_resource do 3 | 4 | end 5 | 6 | end 7 | -------------------------------------------------------------------------------- /test/factories/public_accounts.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :public_account do 3 | name {(rand*1000).to_i.to_s} 4 | account {(rand*1000).to_i.to_s} 5 | appid 'wx992037f0a32db788' 6 | appsecret 'ebf11ea81d4887f9fd26987241262913' 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /test/factories/users.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :user do 3 | 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/fixtures/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/test/fixtures/.keep -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/test/helpers/.keep -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/test/integration/.keep -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/test/mailers/.keep -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/test/models/.keep -------------------------------------------------------------------------------- /test/models/activity_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ActivityTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/article_type_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ArticleTypeTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/event_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class EventTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/media_resource_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class MediaResourceTest < ActiveSupport::TestCase 4 | # test 'should upload file to qiniu' do 5 | # file = File.open "#{Rails.root}/Gemfile" 6 | # assert MediaResource.upload file, 'heheda' 7 | # end 8 | end 9 | -------------------------------------------------------------------------------- /test/models/public_account_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PublicAccountTest < ActiveSupport::TestCase 4 | 5 | end 6 | -------------------------------------------------------------------------------- /test/models/user_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class UserTest < ActiveSupport::TestCase 4 | setup do 5 | account = create(:public_account) 6 | @activity = create(:activity, public_account: account) 7 | end 8 | 9 | test 'user should join activity' do 10 | user = create(:user) 11 | user.activities << @activity 12 | user.activities << @activity unless user.activities.include? @activity 13 | user.reload 14 | @activity.reload 15 | 16 | assert_equal @activity, user.activities.first 17 | assert_equal 1, user.activities.count 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV['RAILS_ENV'] ||= 'test' 2 | 3 | require 'simplecov' 4 | SimpleCov.start 'rails' 5 | 6 | require File.expand_path('../../config/environment', __FILE__) 7 | 8 | require 'rails/test_help' 9 | require 'mocha/setup' 10 | require 'minitest/mock' 11 | require 'sidekiq/testing' 12 | 13 | require 'minitest/reporters' 14 | 15 | Dir[Rails.root.join("test/support/**/*.rb")].each { |f| require f } 16 | 17 | Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new({ color: true })] 18 | 19 | 20 | Sidekiq::Testing.inline! 21 | 22 | class ActiveSupport::TestCase 23 | include FactoryGirl::Syntax::Methods 24 | Sidekiq::Testing.disable! 25 | 26 | def setup 27 | super 28 | end 29 | 30 | setup do 31 | Rails.cache.clear 32 | end 33 | 34 | teardown do 35 | $redis.flushdb 36 | $ssdb.flushdb 37 | end 38 | 39 | end 40 | 41 | require 'pp' 42 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plugine/wei/73c2f178834b3d7660dd845650b089afb2386303/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------