gjj
2023-02-07 08690e2fd123a710406a101a2a5bd98fa0992502
项目迁移
1 files modified
496 files added
86138 ■■■■■ changed files
.babelrc 12 ●●●●● patch | view | raw | blame | history
.editorconfig 9 ●●●●● patch | view | raw | blame | history
.eslintignore 4 ●●●● patch | view | raw | blame | history
.eslintrc.js 34 ●●●●● patch | view | raw | blame | history
.gitignore 14 ●●●●● patch | view | raw | blame | history
.postcssrc.js 10 ●●●●● patch | view | raw | blame | history
README.md 21 ●●●●● patch | view | raw | blame | history
build/build.js 41 ●●●●● patch | view | raw | blame | history
build/check-versions.js 54 ●●●●● patch | view | raw | blame | history
build/logo.png patch | view | raw | blame | history
build/utils.js 109 ●●●●● patch | view | raw | blame | history
build/vue-loader.conf.js 22 ●●●●● patch | view | raw | blame | history
build/webpack.base.conf.js 92 ●●●●● patch | view | raw | blame | history
build/webpack.dev.conf.js 97 ●●●●● patch | view | raw | blame | history
build/webpack.prod.conf.js 145 ●●●●● patch | view | raw | blame | history
config/dev.env.js 8 ●●●●● patch | view | raw | blame | history
config/index.js 87 ●●●●● patch | view | raw | blame | history
config/prod.env.js 6 ●●●●● patch | view | raw | blame | history
favicon.ico patch | view | raw | blame | history
index.html 25 ●●●●● patch | view | raw | blame | history
myproject@1.0.0 patch | view | raw | blame | history
package-lock.json 14372 ●●●●● patch | view | raw | blame | history
package.json 104 ●●●●● patch | view | raw | blame | history
src/App.vue 19 ●●●●● patch | view | raw | blame | history
src/api/businessIntelligence/index.js 72 ●●●●● patch | view | raw | blame | history
src/api/common.js 314 ●●●●● patch | view | raw | blame | history
src/api/customermanagement/business.js 129 ●●●●● patch | view | raw | blame | history
src/api/customermanagement/contacts.js 62 ●●●●● patch | view | raw | blame | history
src/api/customermanagement/contract.js 62 ●●●●● patch | view | raw | blame | history
src/api/customermanagement/customerManage.js 125 ●●●●● patch | view | raw | blame | history
src/api/customermanagement/offer.js 62 ●●●●● patch | view | raw | blame | history
src/api/customermanagement/product.js 14 ●●●●● patch | view | raw | blame | history
src/api/login.js 62 ●●●●● patch | view | raw | blame | history
src/api/moduleManage/moduleManage.js 35 ●●●●● patch | view | raw | blame | history
src/api/pwsApi/ewsAnalyze.js 11 ●●●●● patch | view | raw | blame | history
src/api/pwsApi/subscriptions.js 18 ●●●●● patch | view | raw | blame | history
src/api/systemManagement/departmentManage.js 63 ●●●●● patch | view | raw | blame | history
src/api/systemManagement/employeeManage.js 62 ●●●●● patch | view | raw | blame | history
src/api/systemManagement/log.js 14 ●●●●● patch | view | raw | blame | history
src/api/systemManagement/officalAuthority.js 42 ●●●●● patch | view | raw | blame | history
src/assets/401_images/1.gif patch | view | raw | blame | history
src/assets/401_images/401.gif patch | view | raw | blame | history
src/assets/404_images/404.png patch | view | raw | blame | history
src/assets/404_images/404_cloud.png patch | view | raw | blame | history
src/assets/aside/business.png patch | view | raw | blame | history
src/assets/aside/business_active.png patch | view | raw | blame | history
src/assets/aside/check.png patch | view | raw | blame | history
src/assets/aside/company.png patch | view | raw | blame | history
src/assets/aside/company_active.png patch | view | raw | blame | history
src/assets/aside/customer.png patch | view | raw | blame | history
src/assets/aside/customer_active.png patch | view | raw | blame | history
src/assets/aside/delete.png patch | view | raw | blame | history
src/assets/aside/dilivery.png patch | view | raw | blame | history
src/assets/aside/export.png patch | view | raw | blame | history
src/assets/aside/financial.png patch | view | raw | blame | history
src/assets/aside/financial_active.png patch | view | raw | blame | history
src/assets/aside/import.png patch | view | raw | blame | history
src/assets/aside/order.png patch | view | raw | blame | history
src/assets/aside/order_active.png patch | view | raw | blame | history
src/assets/aside/personnel.png patch | view | raw | blame | history
src/assets/aside/personnel_active.png patch | view | raw | blame | history
src/assets/aside/product.png patch | view | raw | blame | history
src/assets/aside/product_active.png patch | view | raw | blame | history
src/assets/aside/system.png patch | view | raw | blame | history
src/assets/aside/system_active.png patch | view | raw | blame | history
src/assets/aside/total.png patch | view | raw | blame | history
src/assets/aside/total_active.png patch | view | raw | blame | history
src/assets/aside/workbench.png patch | view | raw | blame | history
src/assets/aside/workbench_active.png patch | view | raw | blame | history
src/assets/css/normalize.css 460 ●●●●● patch | view | raw | blame | history
src/assets/fonts/demo.css 539 ●●●●● patch | view | raw | blame | history
src/assets/fonts/demo_index.html 329 ●●●●● patch | view | raw | blame | history
src/assets/fonts/iconfont.css 341 ●●●●● patch | view | raw | blame | history
src/assets/fonts/iconfont.eot patch | view | raw | blame | history
src/assets/fonts/iconfont.js 1 ●●●● patch | view | raw | blame | history
src/assets/fonts/iconfont.json 58 ●●●●● patch | view | raw | blame | history
src/assets/fonts/iconfont.svg 47 ●●●●● patch | view | raw | blame | history
src/assets/fonts/iconfont.ttf patch | view | raw | blame | history
src/assets/fonts/iconfont.woff patch | view | raw | blame | history
src/assets/fonts/iconfont.woff2 patch | view | raw | blame | history
src/assets/img/accessory.png patch | view | raw | blame | history
src/assets/img/add_examine.png patch | view | raw | blame | history
src/assets/img/add_journal.png patch | view | raw | blame | history
src/assets/img/add_notice.png patch | view | raw | blame | history
src/assets/img/add_schedule.png patch | view | raw | blame | history
src/assets/img/add_task.png patch | view | raw | blame | history
src/assets/img/archive_project.png patch | view | raw | blame | history
src/assets/img/business_detail.png patch | view | raw | blame | history
src/assets/img/business_dot.png patch | view | raw | blame | history
src/assets/img/button_add_black.png patch | view | raw | blame | history
src/assets/img/button_add_white.png patch | view | raw | blame | history
src/assets/img/c_business.png patch | view | raw | blame | history
src/assets/img/c_contact.png patch | view | raw | blame | history
src/assets/img/c_contract.png patch | view | raw | blame | history
src/assets/img/c_curomer.png patch | view | raw | blame | history
src/assets/img/c_filtrate.png patch | view | raw | blame | history
src/assets/img/c_log.png patch | view | raw | blame | history
src/assets/img/c_receivables.png patch | view | raw | blame | history
src/assets/img/cancel_associated.png patch | view | raw | blame | history
src/assets/img/check_cancel.png patch | view | raw | blame | history
src/assets/img/check_create.png patch | view | raw | blame | history
src/assets/img/check_fail.png patch | view | raw | blame | history
src/assets/img/check_revoke.png patch | view | raw | blame | history
src/assets/img/check_suc.png patch | view | raw | blame | history
src/assets/img/check_wait.png patch | view | raw | blame | history
src/assets/img/close.png patch | view | raw | blame | history
src/assets/img/close2x.png patch | view | raw | blame | history
src/assets/img/clue_detail.png patch | view | raw | blame | history
src/assets/img/collapse_gray.png patch | view | raw | blame | history
src/assets/img/collapse_right.png patch | view | raw | blame | history
src/assets/img/collapse_white.png patch | view | raw | blame | history
src/assets/img/comment.png patch | view | raw | blame | history
src/assets/img/contacts_detail.png patch | view | raw | blame | history
src/assets/img/contract_detail.png patch | view | raw | blame | history
src/assets/img/crm_multiuser.png patch | view | raw | blame | history
src/assets/img/customer_detail.png patch | view | raw | blame | history
src/assets/img/deadline.png patch | view | raw | blame | history
src/assets/img/delete_task.png patch | view | raw | blame | history
src/assets/img/empty.png patch | view | raw | blame | history
src/assets/img/examine_head.png patch | view | raw | blame | history
src/assets/img/field_business_manager.png patch | view | raw | blame | history
src/assets/img/field_contacts_manager.png patch | view | raw | blame | history
src/assets/img/field_contract_manager.png patch | view | raw | blame | history
src/assets/img/field_customer_manager.png patch | view | raw | blame | history
src/assets/img/field_leads_manager.png patch | view | raw | blame | history
src/assets/img/field_other_manager.png patch | view | raw | blame | history
src/assets/img/field_product_manager.png patch | view | raw | blame | history
src/assets/img/field_receivables_manager.png patch | view | raw | blame | history
src/assets/img/file_excle.png patch | view | raw | blame | history
src/assets/img/file_img.png patch | view | raw | blame | history
src/assets/img/file_pdf.png patch | view | raw | blame | history
src/assets/img/file_ppt.png patch | view | raw | blame | history
src/assets/img/file_txt.png patch | view | raw | blame | history
src/assets/img/file_unknown.png patch | view | raw | blame | history
src/assets/img/file_video.png patch | view | raw | blame | history
src/assets/img/file_word.png patch | view | raw | blame | history
src/assets/img/file_zip.png patch | view | raw | blame | history
src/assets/img/fold.png patch | view | raw | blame | history
src/assets/img/follow_log.png patch | view | raw | blame | history
src/assets/img/follow_record.png patch | view | raw | blame | history
src/assets/img/goOut.png patch | view | raw | blame | history
src/assets/img/head.png patch | view | raw | blame | history
src/assets/img/jd_business.png patch | view | raw | blame | history
src/assets/img/jianbao.png patch | view | raw | blame | history
src/assets/img/journal_comment.png patch | view | raw | blame | history
src/assets/img/loading.gif patch | view | raw | blame | history
src/assets/img/login/login.png patch | view | raw | blame | history
src/assets/img/login/login_bg.png patch | view | raw | blame | history
src/assets/img/login/logo.png patch | view | raw | blame | history
src/assets/img/logo.jpg patch | view | raw | blame | history
src/assets/img/logo.png patch | view | raw | blame | history
src/assets/img/logo_bg.png patch | view | raw | blame | history
src/assets/img/loudou.png patch | view | raw | blame | history
src/assets/img/mobile.png patch | view | raw | blame | history
src/assets/img/money_detail.png patch | view | raw | blame | history
src/assets/img/more_dot.png patch | view | raw | blame | history
src/assets/img/no_data.png patch | view | raw | blame | history
src/assets/img/no_task.png patch | view | raw | blame | history
src/assets/img/nopermission.png patch | view | raw | blame | history
src/assets/img/person_dot.png patch | view | raw | blame | history
src/assets/img/post.png patch | view | raw | blame | history
src/assets/img/product_detail.png patch | view | raw | blame | history
src/assets/img/project/archive_project.png patch | view | raw | blame | history
src/assets/img/project/head.png patch | view | raw | blame | history
src/assets/img/project/my_task.png patch | view | raw | blame | history
src/assets/img/project/project_add.png patch | view | raw | blame | history
src/assets/img/project/project_filtrate.png patch | view | raw | blame | history
src/assets/img/project/relevance_file.png patch | view | raw | blame | history
src/assets/img/project/schedule.png patch | view | raw | blame | history
src/assets/img/project/send_contacts.png patch | view | raw | blame | history
src/assets/img/project/smiling_face.png patch | view | raw | blame | history
src/assets/img/project/t_set.png patch | view | raw | blame | history
src/assets/img/project/task_accessory.png patch | view | raw | blame | history
src/assets/img/project/task_add.png patch | view | raw | blame | history
src/assets/img/project/task_circle.png patch | view | raw | blame | history
src/assets/img/project/task_close.png patch | view | raw | blame | history
src/assets/img/project/task_download.png patch | view | raw | blame | history
src/assets/img/project/task_ellipsis.png patch | view | raw | blame | history
src/assets/img/project/task_end_time.png patch | view | raw | blame | history
src/assets/img/project/task_priority.png patch | view | raw | blame | history
src/assets/img/project/task_subtask.png patch | view | raw | blame | history
src/assets/img/project/task_tag.png patch | view | raw | blame | history
src/assets/img/qushi.png patch | view | raw | blame | history
src/assets/img/relevance_business.png patch | view | raw | blame | history
src/assets/img/relevance_file.png patch | view | raw | blame | history
src/assets/img/scene_add.png patch | view | raw | blame | history
src/assets/img/scene_set.png patch | view | raw | blame | history
src/assets/img/sea_detail.png patch | view | raw | blame | history
src/assets/img/section_reset_name.png patch | view | raw | blame | history
src/assets/img/selection_add_user.png patch | view | raw | blame | history
src/assets/img/selection_alloc.png patch | view | raw | blame | history
src/assets/img/selection_convert_customer.png patch | view | raw | blame | history
src/assets/img/selection_deal_status.png patch | view | raw | blame | history
src/assets/img/selection_delete.png patch | view | raw | blame | history
src/assets/img/selection_delete_user.png patch | view | raw | blame | history
src/assets/img/selection_disable.png patch | view | raw | blame | history
src/assets/img/selection_edit.png patch | view | raw | blame | history
src/assets/img/selection_export.png patch | view | raw | blame | history
src/assets/img/selection_get.png patch | view | raw | blame | history
src/assets/img/selection_lock.png patch | view | raw | blame | history
src/assets/img/selection_putseas.png patch | view | raw | blame | history
src/assets/img/selection_reset.png patch | view | raw | blame | history
src/assets/img/selection_start.png patch | view | raw | blame | history
src/assets/img/selection_transfer.png patch | view | raw | blame | history
src/assets/img/selection_unlock.png patch | view | raw | blame | history
src/assets/img/send_business.png patch | view | raw | blame | history
src/assets/img/send_contacts.png patch | view | raw | blame | history
src/assets/img/send_file.png patch | view | raw | blame | history
src/assets/img/send_img.png patch | view | raw | blame | history
src/assets/img/setting.png patch | view | raw | blame | history
src/assets/img/smiling_face.png patch | view | raw | blame | history
src/assets/img/sprite/vue-emoji.png patch | view | raw | blame | history
src/assets/img/step_success.png patch | view | raw | blame | history
src/assets/img/step_wait.png patch | view | raw | blame | history
src/assets/img/structure.png patch | view | raw | blame | history
src/assets/img/system/app/call_disable.png patch | view | raw | blame | history
src/assets/img/system/app/call_enable.png patch | view | raw | blame | history
src/assets/img/system/app/crm_disable.png patch | view | raw | blame | history
src/assets/img/system/app/crm_enable.png patch | view | raw | blame | history
src/assets/img/system/app/hrm.png patch | view | raw | blame | history
src/assets/img/system/app/inventory.png patch | view | raw | blame | history
src/assets/img/system/app/oa_disable.png patch | view | raw | blame | history
src/assets/img/system/app/oa_enable.png patch | view | raw | blame | history
src/assets/img/system/app/phone.png patch | view | raw | blame | history
src/assets/img/system/app/project_disable.png patch | view | raw | blame | history
src/assets/img/system/app/project_enable.png patch | view | raw | blame | history
src/assets/img/system/customer_pool_module.png patch | view | raw | blame | history
src/assets/img/system/examine_module.png patch | view | raw | blame | history
src/assets/img/system/leads_module.png patch | view | raw | blame | history
src/assets/img/system/leads_pool_module.png patch | view | raw | blame | history
src/assets/img/system/log_module.png patch | view | raw | blame | history
src/assets/img/system/notice_module.png patch | view | raw | blame | history
src/assets/img/system/schedule_module.png patch | view | raw | blame | history
src/assets/img/system/task_module.png patch | view | raw | blame | history
src/assets/img/t_set.png patch | view | raw | blame | history
src/assets/img/tablefilter.png patch | view | raw | blame | history
src/assets/img/task_accessory.png patch | view | raw | blame | history
src/assets/img/task_add.png patch | view | raw | blame | history
src/assets/img/task_close.png patch | view | raw | blame | history
src/assets/img/task_edit_def.png patch | view | raw | blame | history
src/assets/img/task_ellipsis.png patch | view | raw | blame | history
src/assets/img/unfold.png patch | view | raw | blame | history
src/assets/img/update_files.png patch | view | raw | blame | history
src/assets/img/work_examine.png patch | view | raw | blame | history
src/assets/img/work_log.png patch | view | raw | blame | history
src/assets/img/work_notice.png patch | view | raw | blame | history
src/assets/img/work_schedule.png patch | view | raw | blame | history
src/assets/img/work_statistics.png patch | view | raw | blame | history
src/assets/img/work_task.png patch | view | raw | blame | history
src/assets/img/zhibiao.png patch | view | raw | blame | history
src/components/CreateCom/CrmRelative.vue 377 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/CrmRelativeCell.vue 179 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/CrmRelativeTable.vue 590 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhBusinessStatus.vue 67 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhCustomerAddress.vue 397 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhDate.vue 29 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhDateTime.vue 43 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhFiles.vue 203 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhInput.vue 36 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhInputSelect.vue 201 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhMultipleSelect.vue 45 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhProduct.vue 391 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhProuctCate.vue 61 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhReceivablesPlan.vue 70 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhRelativeInput.vue 226 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhRelativeInputS.vue 214 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhSelect.vue 67 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhStrucUserCell.vue 134 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhStructure.vue 246 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhStructureCell.vue 142 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhTextarea.vue 41 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhUser.vue 240 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/XhUserCell.vue 162 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/arrayMixin.js 44 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/index.js 21 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/objMixin.js 42 ●●●●● patch | view | raw | blame | history
src/components/CreateCom/stringMixin.js 49 ●●●●● patch | view | raw | blame | history
src/components/CreateSections.vue 72 ●●●●● patch | view | raw | blame | history
src/components/CreateView.vue 83 ●●●●● patch | view | raw | blame | history
src/components/DetailCell.vue 84 ●●●●● patch | view | raw | blame | history
src/components/EditImage.vue 156 ●●●●● patch | view | raw | blame | history
src/components/Examine/CheckFlow.vue 237 ●●●●● patch | view | raw | blame | history
src/components/Examine/CreateExamineInfo.vue 244 ●●●●● patch | view | raw | blame | history
src/components/Examine/ExamineHandle.vue 246 ●●●●● patch | view | raw | blame | history
src/components/Examine/ExamineInfo.vue 443 ●●●●● patch | view | raw | blame | history
src/components/HelloWorld.vue 113 ●●●●● patch | view | raw | blame | history
src/components/MapView.vue 93 ●●●●● patch | view | raw | blame | history
src/components/SlideView.vue 129 ●●●●● patch | view | raw | blame | history
src/components/common/SIdentify.vue 164 ●●●●● patch | view | raw | blame | history
src/components/emoji.vue 130 ●●●●● patch | view | raw | blame | history
src/components/flexbox/flexbox-item.vue 62 ●●●●● patch | view | raw | blame | history
src/components/flexbox/flexbox.vue 81 ●●●●● patch | view | raw | blame | history
src/components/flexbox/index.js 7 ●●●●● patch | view | raw | blame | history
src/components/relatedBusiness.vue 240 ●●●●● patch | view | raw | blame | history
src/components/reminder.vue 60 ●●●●● patch | view | raw | blame | history
src/components/selectEmployee/membersDep.vue 622 ●●●●● patch | view | raw | blame | history
src/components/timeTypeSelect/index.vue 184 ●●●●● patch | view | raw | blame | history
src/components/vuePictureViewer/img/pre_close.png patch | view | raw | blame | history
src/components/vuePictureViewer/img/pre_down.png patch | view | raw | blame | history
src/components/vuePictureViewer/img/pre_left.png patch | view | raw | blame | history
src/components/vuePictureViewer/img/pre_max.png patch | view | raw | blame | history
src/components/vuePictureViewer/img/pre_min.png patch | view | raw | blame | history
src/components/vuePictureViewer/img/pre_right.png patch | view | raw | blame | history
src/components/vuePictureViewer/img/pre_rotate.png patch | view | raw | blame | history
src/components/vuePictureViewer/index.vue 753 ●●●●● patch | view | raw | blame | history
src/directives/empty/empty.scss 7 ●●●●● patch | view | raw | blame | history
src/directives/empty/empty.vue 97 ●●●●● patch | view | raw | blame | history
src/directives/empty/index.js 102 ●●●●● patch | view | raw | blame | history
src/directives/focus.js 7 ●●●●● patch | view | raw | blame | history
src/directives/index.js 24 ●●●●● patch | view | raw | blame | history
src/directives/photo/index.js 91 ●●●●● patch | view | raw | blame | history
src/directives/photo/photo.scss 7 ●●●●● patch | view | raw | blame | history
src/directives/photo/photo.vue 79 ●●●●● patch | view | raw | blame | history
src/directives/scrollx/index.js 135 ●●●●● patch | view | raw | blame | history
src/directives/style.scss 2 ●●●●● patch | view | raw | blame | history
src/filters/index.js 35 ●●●●● patch | view | raw | blame | history
src/main.js 88 ●●●●● patch | view | raw | blame | history
src/router/index.js 190 ●●●●● patch | view | raw | blame | history
src/store/getters.js 48 ●●●●● patch | view | raw | blame | history
src/store/index.js 24 ●●●●● patch | view | raw | blame | history
src/store/modules/app.js 85 ●●●●● patch | view | raw | blame | history
src/store/modules/customer.js 61 ●●●●● patch | view | raw | blame | history
src/store/modules/oa.js 70 ●●●●● patch | view | raw | blame | history
src/store/modules/permission.js 141 ●●●●● patch | view | raw | blame | history
src/store/modules/user.js 134 ●●●●● patch | view | raw | blame | history
src/styles/animate.css 3623 ●●●●● patch | view | raw | blame | history
src/styles/calendars.scss 168 ●●●●● patch | view | raw | blame | history
src/styles/element-ui.scss 122 ●●●●● patch | view | raw | blame | history
src/styles/element-variables.scss 38 ●●●●● patch | view | raw | blame | history
src/styles/emoji-sprite.scss 3558 ●●●●● patch | view | raw | blame | history
src/styles/iconPath.scss 171 ●●●●● patch | view | raw | blame | history
src/styles/index.scss 223 ●●●●● patch | view | raw | blame | history
src/styles/mixin.scss 44 ●●●●● patch | view | raw | blame | history
src/styles/transition.scss 46 ●●●●● patch | view | raw | blame | history
src/styles/xr-theme.css 9 ●●●●● patch | view | raw | blame | history
src/styles/xr-theme.scss 33 ●●●●● patch | view | raw | blame | history
src/utils/auth.js 35 ●●●●● patch | view | raw | blame | history
src/utils/baseconfig.js 5 ●●●●● patch | view | raw | blame | history
src/utils/cache.js 46 ●●●●● patch | view | raw | blame | history
src/utils/dist/request.dev.js 119 ●●●●● patch | view | raw | blame | history
src/utils/dom.js 45 ●●●●● patch | view | raw | blame | history
src/utils/emoji-data.js 3 ●●●●● patch | view | raw | blame | history
src/utils/emoji.js 30 ●●●●● patch | view | raw | blame | history
src/utils/index.js 501 ●●●●● patch | view | raw | blame | history
src/utils/request.js 113 ●●●●● patch | view | raw | blame | history
src/utils/types.js 11 ●●●●● patch | view | raw | blame | history
src/utils/validate.js 27 ●●●●● patch | view | raw | blame | history
src/views/401.vue 129 ●●●●● patch | view | raw | blame | history
src/views/404.vue 88 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/addressBook/department.vue 104 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/addressBook/index.vue 187 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/addressBook/staff.vue 75 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/components/fileCell/index.vue 124 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/components/relatedBusinessCell/index.vue 115 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/content.vue 222 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/examineCategorySelect.vue 148 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/examineCell.vue 304 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/examineCreateView.vue 1096 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/examineDetail.vue 586 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/examineSection.vue 170 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/relatedBusiness.vue 141 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/xhExpenses.vue 408 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/components/xhLeaves.vue 278 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/examine/index.vue 197 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/journal/content.vue 217 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/journal/index.vue 383 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/journal/journalCell.vue 814 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/journal/newDialog.vue 616 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/notice/details.vue 180 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/notice/edit.vue 206 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/notice/index.vue 267 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/notice/newDialog.vue 340 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/notice/noticeCell.vue 199 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/schedule/components/createSchedule.vue 647 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/schedule/components/details.vue 234 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/schedule/index.vue 394 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/styles/content.scss 24 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/styles/tabs.scss 22 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/myTask.vue 283 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/newDialog.vue 443 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/particulars.vue 2080 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/subTask.vue 324 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/tag/editTag.vue 134 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/tag/newTag.vue 158 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/tag/tagIndex.vue 394 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/components/taskCell.vue 332 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/index.vue 266 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/task/mixins/listTaskDetail.js 64 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/workbench/index.vue 247 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/workbench/schedule.vue 236 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/workbench/tabsContent.vue 262 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/workbench/tabsJournal.vue 78 ●●●●● patch | view | raw | blame | history
src/views/OAManagement/workbench/task.vue 241 ●●●●● patch | view | raw | blame | history
src/views/PWS/EwsAnalyze.vue 411 ●●●●● patch | view | raw | blame | history
src/views/PWS/Subscriptions.vue 315 ●●●●● patch | view | raw | blame | history
src/views/clients/business/BusinessDetail.vue 726 ●●●●● patch | view | raw | blame | history
src/views/clients/business/BusinessIndex.vue 483 ●●●●● patch | view | raw | blame | history
src/views/clients/business/components/BusinessFollow.vue 208 ●●●●● patch | view | raw | blame | history
src/views/clients/businessChances/BusinessChancesDetail.vue 694 ●●●●● patch | view | raw | blame | history
src/views/clients/businessChances/BusinessChancesIndex.vue 557 ●●●●● patch | view | raw | blame | history
src/views/clients/businessChances/components/BusinessFollow.vue 208 ●●●●● patch | view | raw | blame | history
src/views/clients/businessContracts/BusinessContractsDetail.vue 217 ●●●●● patch | view | raw | blame | history
src/views/clients/businessContracts/BusinessContractsIndex.vue 264 ●●●●● patch | view | raw | blame | history
src/views/clients/businessContracts/components/ContractFollow.vue 197 ●●●●● patch | view | raw | blame | history
src/views/clients/businessCustomer/BusinessCustomerDetail.vue 271 ●●●●● patch | view | raw | blame | history
src/views/clients/businessCustomer/BusinessCustomerManage.vue 561 ●●●●● patch | view | raw | blame | history
src/views/clients/businessCustomer/components/BusinessCheck.vue 170 ●●●●● patch | view | raw | blame | history
src/views/clients/businessCustomer/components/CustomerFollow.vue 142 ●●●●● patch | view | raw | blame | history
src/views/clients/clue/ClueDetail.vue 181 ●●●●● patch | view | raw | blame | history
src/views/clients/clue/ClueIndex.vue 131 ●●●●● patch | view | raw | blame | history
src/views/clients/clue/components/ClueFollow.vue 169 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMAllDetail.vue 179 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMBaseInfo.vue 481 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMCreateFileView.vue 696 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMCreateView.vue 2201 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMDetailHead.vue 596 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMExport.vue 340 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMFullScreenDetail.vue 161 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMImport.vue 804 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMListHead.vue 74 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMTableFilter.vue 221 ●●●●● patch | view | raw | blame | history
src/views/clients/components/CRMTableHead.vue 636 ●●●●● patch | view | raw | blame | history
src/views/clients/components/MixAdd.vue 819 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeApproval.vue 239 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeBusiness.vue 409 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeContacts.vue 349 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeContract.vue 327 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeFiles.vue 318 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeHandle.vue 161 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeOffers.vue 324 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeProduct.vue 391 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeReturnMoney.vue 451 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeSchedule.vue 230 ●●●●● patch | view | raw | blame | history
src/views/clients/components/RelativeTeam.vue 286 ●●●●● patch | view | raw | blame | history
src/views/clients/components/Sections.vue 145 ●●●●● patch | view | raw | blame | history
src/views/clients/components/duplicateCheck/checkContent.vue 336 ●●●●● patch | view | raw | blame | history
src/views/clients/components/duplicateCheck/index.vue 124 ●●●●● patch | view | raw | blame | history
src/views/clients/components/fieldsManager/FieldsSet.vue 538 ●●●●● patch | view | raw | blame | history
src/views/clients/components/filterForm/filterContent.vue 156 ●●●●● patch | view | raw | blame | history
src/views/clients/components/filterForm/index.vue 648 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/ExamineLog.vue 207 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/JournalLog.vue 279 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/RecordLog.vue 169 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/ScheduleLog.vue 199 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/TaskLog.vue 192 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/components/FollowRecordCell.vue 437 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/components/FollowRecordTable.vue 449 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/components/FollowScheduleCell.vue 252 ●●●●● patch | view | raw | blame | history
src/views/clients/components/followLog/styles/followcell.scss 174 ●●●●● patch | view | raw | blame | history
src/views/clients/components/sceneForm/SceneCreate.vue 640 ●●●●● patch | view | raw | blame | history
src/views/clients/components/sceneForm/SceneList.vue 160 ●●●●● patch | view | raw | blame | history
src/views/clients/components/sceneForm/SceneSet.vue 648 ●●●●● patch | view | raw | blame | history
src/views/clients/components/selectionHandle/AllocHandle.vue 154 ●●●●● patch | view | raw | blame | history
src/views/clients/components/selectionHandle/DealStatusHandle.vue 150 ●●●●● patch | view | raw | blame | history
src/views/clients/components/selectionHandle/TeamsHandle.vue 230 ●●●●● patch | view | raw | blame | history
src/views/clients/components/selectionHandle/TransferHandle.vue 219 ●●●●● patch | view | raw | blame | history
src/views/clients/contacts/ContactsDetail.vue 240 ●●●●● patch | view | raw | blame | history
src/views/clients/contacts/ContactsIndex.vue 315 ●●●●● patch | view | raw | blame | history
src/views/clients/contacts/components/ContactsFollow.vue 184 ●●●●● patch | view | raw | blame | history
src/views/clients/contract/ContractDetail.vue 217 ●●●●● patch | view | raw | blame | history
src/views/clients/contract/ContractIndex.vue 265 ●●●●● patch | view | raw | blame | history
src/views/clients/contract/components/ContractFollow.vue 197 ●●●●● patch | view | raw | blame | history
src/views/clients/customer/CustomerDetail.vue 329 ●●●●● patch | view | raw | blame | history
src/views/clients/customer/clientsManage.vue 663 ●●●●● patch | view | raw | blame | history
src/views/clients/customer/components/BusinessCheck.vue 170 ●●●●● patch | view | raw | blame | history
src/views/clients/customer/components/CustomerFollow.vue 184 ●●●●● patch | view | raw | blame | history
src/views/clients/customer/test.vue 151 ●●●●● patch | view | raw | blame | history
src/views/clients/mixins/detail.js 127 ●●●●● patch | view | raw | blame | history
src/views/clients/mixins/followLogType.js 102 ●●●●● patch | view | raw | blame | history
src/views/clients/mixins/loading.js 29 ●●●●● patch | view | raw | blame | history
src/views/clients/mixins/table.js 791 ●●●●● patch | view | raw | blame | history
src/views/clients/model/crmTypeModel.js 12 ●●●●● patch | view | raw | blame | history
src/views/clients/offers/OfferIndex.vue 261 ●●●●● patch | view | raw | blame | history
src/views/clients/product/ProductIndex.vue 591 ●●●●● patch | view | raw | blame | history
src/views/clients/sealContract/SealContractDetail.vue 217 ●●●●● patch | view | raw | blame | history
src/views/clients/sealContract/SealContractIndex.vue 257 ●●●●● patch | view | raw | blame | history
src/views/clients/sealOffers/SealOfferIndex.vue 260 ●●●●● patch | view | raw | blame | history
src/views/clients/styles/crmdetail.scss 48 ●●●●● patch | view | raw | blame | history
src/views/clients/styles/detailview.scss 15 ●●●●● patch | view | raw | blame | history
src/views/clients/styles/followcell.scss 170 ●●●●● patch | view | raw | blame | history
src/views/clients/styles/followlog.scss 122 ●●●●● patch | view | raw | blame | history
src/views/clients/styles/relativecrm.scss 148 ●●●●● patch | view | raw | blame | history
src/views/clients/styles/table.scss 146 ●●●●● patch | view | raw | blame | history
src/views/company/ApartmentManage.vue 466 ●●●●● patch | view | raw | blame | history
src/views/company/employeeManage/EmployeeManage.vue 1800 ●●●●● patch | view | raw | blame | history
src/views/company/employeeManage/components/EmployeeDetail.vue 231 ●●●●● patch | view | raw | blame | history
src/views/company/offcialAuthority.vue 418 ●●●●● patch | view | raw | blame | history
src/views/company/staffLog.vue 254 ●●●●● patch | view | raw | blame | history
src/views/company/systemSetting.vue 196 ●●●●● patch | view | raw | blame | history
src/views/home/Home.vue 518 ●●●●● patch | view | raw | blame | history
src/views/login/index.vue 733 ●●●●● patch | view | raw | blame | history
src/views/login/logining.vue 67 ●●●●● patch | view | raw | blame | history
src/views/module/ModuleManage.vue 484 ●●●●● patch | view | raw | blame | history
src/views/welcome/Welcome.vue 13 ●●●●● patch | view | raw | blame | history
static/.gitkeep patch | view | raw | blame | history
static/client.js 62 ●●●●● patch | view | raw | blame | history
webpack-dev-server patch | view | raw | blame | history
.babelrc
New file
@@ -0,0 +1,12 @@
{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime"]
}
.editorconfig
New file
@@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
.eslintignore
New file
@@ -0,0 +1,4 @@
/build/
/config/
/dist/
/*.js
.eslintrc.js
New file
@@ -0,0 +1,34 @@
// https://eslint.org/docs/user-guide/configuring
module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint'
  },
  env: {
    browser: true,
  },
  extends: [
    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
    'plugin:vue/essential',
    // https://github.com/standard/standard/blob/master/docs/RULES-en.md
    'standard'
  ],
  globals: {
    "BMap": "readonly",
    "BMAP_STATUS_SUCCESS": "readonly",
    "fullcalendar": "readonly"
  },
  // required to lint *.vue files
  plugins: [
    'vue'
  ],
  // add your custom rules here
  rules: {
    // allow async-await
    'generator-star-spacing': 'off',
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
  }
}
.gitignore
New file
@@ -0,0 +1,14 @@
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
.postcssrc.js
New file
@@ -0,0 +1,10 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
  "plugins": {
    "postcss-import": {},
    "postcss-url": {},
    // to edit target browsers: use "browserslist" field in package.json
    "autoprefixer": {}
  }
}
README.md
@@ -1,4 +1,21 @@
## Probim-crm
# myproject
CRM前端
> DCGY-CRM
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
build/build.js
New file
@@ -0,0 +1,41 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
  if (err) throw err
  webpack(webpackConfig, (err, stats) => {
    spinner.stop()
    if (err) throw err
    process.stdout.write(stats.toString({
      colors: true,
      modules: false,
      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
      chunks: false,
      chunkModules: false
    }) + '\n\n')
    if (stats.hasErrors()) {
      console.log(chalk.red('  Build failed with errors.\n'))
      process.exit(1)
    }
    console.log(chalk.cyan('  Build complete.\n'))
    console.log(chalk.yellow(
      '  Tip: built files are meant to be served over an HTTP server.\n' +
      '  Opening index.html over file:// won\'t work.\n'
    ))
  })
})
build/check-versions.js
New file
@@ -0,0 +1,54 @@
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
  return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
  {
    name: 'node',
    currentVersion: semver.clean(process.version),
    versionRequirement: packageConfig.engines.node
  }
]
if (shell.which('npm')) {
  versionRequirements.push({
    name: 'npm',
    currentVersion: exec('npm --version'),
    versionRequirement: packageConfig.engines.npm
  })
}
module.exports = function () {
  const warnings = []
  for (let i = 0; i < versionRequirements.length; i++) {
    const mod = versionRequirements[i]
    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
      warnings.push(mod.name + ': ' +
        chalk.red(mod.currentVersion) + ' should be ' +
        chalk.green(mod.versionRequirement)
      )
    }
  }
  if (warnings.length) {
    console.log('')
    console.log(chalk.yellow('To use this template, you must update following to modules:'))
    console.log()
    for (let i = 0; i < warnings.length; i++) {
      const warning = warnings[i]
      console.log('  ' + warning)
    }
    console.log()
    process.exit(1)
  }
}
build/logo.png
build/utils.js
New file
@@ -0,0 +1,109 @@
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory
  return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
  options = options || {}
  const cssLoader = {
    loader: 'css-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }
  const px2remLoader = {
    loader: 'px2rem-loader',
    options: {
      remUnit: 192
    }
  }
  const postcssLoader = {
    loader: 'postcss-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }
  // generate loader string to be used with extract text plugin
  function generateLoaders (loader, loaderOptions) {
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader, px2remLoader] : [cssLoader, px2remLoader]
    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }
    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader',
        publicPath: '../../'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }
  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
  const output = []
  const loaders = exports.cssLoaders(options)
  for (const extension in loaders) {
    const loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      use: loader
    })
  }
  return output
}
exports.createNotifierCallback = () => {
  const notifier = require('node-notifier')
  return (severity, errors) => {
    if (severity !== 'error') return
    const error = errors[0]
    const filename = error.file && error.file.split('!').pop()
    notifier.notify({
      title: packageConfig.name,
      message: severity + ': ' + error.name,
      subtitle: filename || '',
      icon: path.join(__dirname, 'logo.png')
    })
  }
}
build/vue-loader.conf.js
New file
@@ -0,0 +1,22 @@
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
  ? config.build.productionSourceMap
  : config.dev.cssSourceMap
module.exports = {
  loaders: utils.cssLoaders({
    sourceMap: sourceMapEnabled,
    extract: isProduction
  }),
  cssSourceMap: sourceMapEnabled,
  cacheBusting: config.dev.cacheBusting,
  transformToRequire: {
    video: ['src', 'poster'],
    source: 'src',
    img: 'src',
    image: 'xlink:href'
  }
}
build/webpack.base.conf.js
New file
@@ -0,0 +1,92 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
  return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
  test: /\.(js|vue)$/,
  loader: 'eslint-loader',
  enforce: 'pre',
  include: [resolve('src'), resolve('test')],
  options: {
    formatter: require('eslint-friendly-formatter'),
    emitWarning: !config.dev.showEslintErrorsInOverlay
  }
})
module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [
      ...(config.dev.useEslint ? [createLintingRule()] : []),
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
}
build/webpack.dev.conf.js
New file
@@ -0,0 +1,97 @@
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  },
  // cheap-module-eval-source-map is faster for development
  devtool: config.dev.devtool,
  // these devServer options should be customized in /config/index.js
  devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,
    quiet: true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,
    },
    disableHostCheck: true
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
    new webpack.NoEmitOnErrorsPlugin(),
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      favicon: 'favicon.ico',
      inject: true
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})
module.exports = new Promise((resolve, reject) => {
  portfinder.basePort = process.env.PORT || config.dev.port
  portfinder.getPort((err, port) => {
    if (err) {
      reject(err)
    } else {
      // publish the new Port, necessary for e2e tests
      process.env.PORT = port
      // add port to devServer config
      devWebpackConfig.devServer.port = port
      // Add FriendlyErrorsPlugin
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
        },
        onErrors: config.dev.notifyOnErrors
        ? utils.createNotifierCallback()
        : undefined
      }))
      resolve(devWebpackConfig)
    }
  })
})
build/webpack.prod.conf.js
New file
@@ -0,0 +1,145 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  },
  devtool: config.build.productionSourceMap ? config.build.devtool : false,
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: false
        }
      },
      sourceMap: config.build.productionSourceMap,
      parallel: true
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      // Setting the following option to `false` will not extract CSS from codesplit chunks.
      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
      allChunks: true,
    }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // keep module.id stable when vendor modules does not change
    new webpack.HashedModuleIdsPlugin(),
    // enable scope hoisting
    new webpack.optimize.ModuleConcatenationPlugin(),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks (module) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity
    }),
    // This instance extracts shared chunks from code splitted chunks and bundles them
    // in a separate chunk, similar to the vendor chunk
    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
    new webpack.optimize.CommonsChunkPlugin({
      name: 'app',
      async: 'vendor-async',
      children: true,
      minChunks: 3
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})
if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')
  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}
if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
config/dev.env.js
New file
@@ -0,0 +1,8 @@
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '"/api/"',
})
config/index.js
New file
@@ -0,0 +1,87 @@
'use strict'
const { debug } = require('console')
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
  dev: {
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
        // target: 'http://192.168.2.107:8080',
        target: 'http://api.crm.urlink.com.cn',
        changeOrigin: true,
        logLevel: 'debug',
        pathRewrite: {
          '^/api': '/api'
        }
      }
    },
    // Various Dev Server settings
    host: '127.0.0.1', // can be overwritten by process.env.HOST
    port: 80, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: false,
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
    // Use Eslint Loader?
    // If true, your code will be linted during bundling and
    // linting errors and warnings will be shown in the console.
    useEslint: true,
    // If true, eslint errors and warnings will also be shown in the error overlay
    // in the browser.
    showEslintErrorsInOverlay: false,
    /**
     * Source Maps
     */
    // https://webpack.js.org/configuration/devtool/#development
    devtool: 'cheap-module-eval-source-map',
    // If you have problems debugging vue-files in devtools,
    // set this to false - it *may* help
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
    cacheBusting: true,
    cssSourceMap: true
  },
  build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),
    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: './',
    /**
     * Source Maps
     */
    productionSourceMap: true,
    // https://webpack.js.org/configuration/devtool/#production
    devtool: '#source-map',
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }
}
config/prod.env.js
New file
@@ -0,0 +1,6 @@
'use strict'
module.exports = {
  NODE_ENV: '"production"',
  // BASE_API: '"http://www.probim.cn:6683/api/"'
  BASE_API: '"http://api.crm.urlink.com.cn/api/"'
}
favicon.ico
index.html
New file
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <title>北京友联华宇科技有限公司CRM</title>
  <link rel="shortcut icon"  href="favicon.ico"/>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vue-slider-component@latest/theme/default.css" />
  <script src="./static/client.js"></script>
</head>
<body>
  <!-- <script type="text/javascript" src="//api.map.baidu.com/api?v=3.0&ak=P7azLi4fZLciLuZU8GZsKRoLztn6LnCO"></script> -->
  <!-- 企业微信扫码登录 -->
  <script
      src="https://rescdn.qqmail.com/node/ww/wwopenmng/js/sso/wwLogin-1.0.0.js"
      type="text/javascript"
  ></script>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>
</html>
myproject@1.0.0
package-lock.json
New file
Diff too large
package.json
New file
@@ -0,0 +1,104 @@
{
  "name": "myproject",
  "version": "1.0.0",
  "description": "DCGY-CRM",
  "author": "gjj <Ganjj@probim.com.cn>",
  "private": true,
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "lint": "eslint --ext .js,.vue src",
    "build": "node build/build.js"
  },
  "dependencies": {
    "@fullcalendar/core": "^5.5.1",
    "@fullcalendar/daygrid": "^5.5.0",
    "@fullcalendar/vue": "^5.5.0",
    "axios": "^0.21.1",
    "element-ui": "^2.14.1",
    "es6-promise": "^4.2.8",
    "js-cookie": "^2.2.1",
    "lib-flexible": "^0.3.2",
    "lockr": "^0.8.5",
    "moment": "^2.29.1",
    "node-sass": "^4.14.1",
    "nprogress": "^0.2.0",
    "v-distpicker": "^1.2.9",
    "vue": "^2.6.12",
    "vue-baidu-map": "^0.21.22",
    "vue-bus": "^1.2.1",
    "vue-calendar-component": "^2.8.2",
    "vue-fullcalendar": "^1.0.9",
    "vue-lazyload": "^1.3.3",
    "vue-moment": "^4.1.0",
    "vue-router": "^3.4.9",
    "vuedraggable": "^2.24.3",
    "vuex": "^3.6.0",
    "xlsx": "^0.14.1",
    "xss": "^1.0.6"
  },
  "devDependencies": {
    "autoprefixer": "^7.1.2",
    "babel-core": "^6.26.3",
    "babel-eslint": "^8.2.1",
    "babel-helper-vue-jsx-merge-props": "^2.0.3",
    "babel-loader": "^7.1.5",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-plugin-transform-vue-jsx": "^3.5.0",
    "babel-preset-env": "^1.3.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-stage-2": "^6.22.0",
    "babel-runtime": "^6.26.0",
    "chalk": "^2.0.1",
    "copy-webpack-plugin": "^4.0.1",
    "css-loader": "^0.28.11",
    "eslint": "^4.15.0",
    "eslint-config-standard": "^10.2.1",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-node": "^5.2.0",
    "eslint-plugin-promise": "^3.4.0",
    "eslint-plugin-standard": "^3.0.1",
    "eslint-plugin-vue": "^4.0.0",
    "extract-text-webpack-plugin": "^3.0.0",
    "file-loader": "^1.1.4",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "html-webpack-plugin": "^2.30.1",
    "less": "^3.9",
    "less-loader": "^5.0.0",
    "node-notifier": "^5.1.2",
    "optimize-css-assets-webpack-plugin": "^3.2.0",
    "ora": "^1.2.0",
    "portfinder": "^1.0.13",
    "postcss-import": "^11.0.0",
    "postcss-loader": "^2.0.8",
    "postcss-url": "^7.2.1",
    "px2rem-loader": "^0.1.9",
    "rimraf": "^2.6.0",
    "sass-loader": "^7.3.1",
    "semver": "^5.3.0",
    "shelljs": "^0.7.6",
    "uglifyjs-webpack-plugin": "^1.1.1",
    "url-loader": "^0.5.8",
    "vue-hot-reload-api": "^1.3.2",
    "vue-html-loader": "^1.2.4",
    "vue-loader": "^13.7.3",
    "vue-style-loader": "^3.1.2",
    "vue-template-compiler": "^2.5.2",
    "webpack": "^3.12.0",
    "webpack-bundle-analyzer": "^2.9.0",
    "webpack-dev-server": "^2.9.1",
    "webpack-merge": "^4.1.0"
  },
  "engines": {
    "node": ">= 6.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}
src/App.vue
New file
@@ -0,0 +1,19 @@
<template>
  <div id="app">
     <router-view/>
  </div>
</template>
<script>
export default {
  name: 'App'
}
</script>
<style>
#app {
  width: 100%;
  position: relative;
  height: 100%;
}
</style>
src/api/businessIntelligence/index.js
New file
@@ -0,0 +1,72 @@
import request from '@/utils/request'
export function GetOtherCustomerPageList (data) {
  return request({
    url: '/Customer/GetOtherCustomerPageList?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime +
    '&StartFollowTime=' + data.StartFollowTime +
    '&EndFolowTime=' + data.EndFolowTime +
    (data.ProvinceCode ? '&ProvinceCode=' + data.ProvinceCode : '') +
    (data.CustomerBusinessStatus
      ? '&CustomerBusinessStatus=' + data.CustomerBusinessStatus : '') +
    (data.CustomerSource ? '&CustomerSource=' + data.CustomerSource : '') + (data.CustomerType ? '&CustomerType=' + data.CustomerType : '') +
    (data.CostomerCategory ? '&CostomerCategory=' + data.CostomerCategory : '') +
    (data.CustomerIndustry ? '&CustomerIndustry=' + data.CustomerIndustry : '') +
    (data.CompanyType ? '&CompanyType=' + data.CompanyType : '') + (data.DepartmentUserType
      ? '&DepartmentUserType=' + data.DepartmentUserType : '') +
      (data.Id
        ? '&Id=' + data.Id : ''),
    method: 'get'
  })
}
export function GetOtherSalesChanceList (data) {
  return request({
    url: '/SalesChance/GetOtherSalesChanceList?PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
    '&Name=' + data.Name +
    (data.SalesChanceStage
      ? '&SalesChanceStage=' + data.SalesChanceStage : '') +
    (data.ProvinceCode
      ? '&ProvinceCode=' + data.ProvinceCode : '') +
    (data.SalesChanceType
      ? '&SalesChanceType=' + data.SalesChanceType : '') +
    (data.ChanceUploadStatus
      ? '&ChanceUploadStatus=' + data.ChanceUploadStatus : '') +
    (data.ChanceReportStatus
      ? '&ChanceReportStatus=' + data.ChanceReportStatus : '') +
    (data.SalesChanceSubmissionMethod
      ? '&SalesChanceSubmissionMethod=' + data.SalesChanceSubmissionMethod : '') +
    (data.ProjectProperty
      ? '&ProjectProperty=' + data.ProjectProperty : '') +
    (data.UploadStatusName
      ? '&UploadStatusName=' + data.UploadStatusName : '') +
    (data.ReportStatusName
      ? '&ReportStatusName=' + data.ReportStatusName : '') +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime + (data.DepartmentUserType
      ? '&DepartmentUserType=' + data.DepartmentUserType : '') +
      (data.Id
        ? '&Id=' + data.Id : ''),
    method: 'get'
  })
}
export function GetOtherAgreementList (data) {
  return request({
    url: '/Agreement/GetOtherAgreementList?SelectOwnedType=' + data.SelectOwnedType + '&AuditStatus=' + data.AuditStatus +
    '&PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SealStatus=' + data.SealStatus +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime + (data.SealType
      ? '&SealType=' + data.SealType : '') + (data.DepartmentUserType
      ? '&DepartmentUserType=' + data.DepartmentUserType : '') +
        (data.Id
          ? '&Id=' + data.Id : ''),
    method: 'get'
  })
}
src/api/common.js
New file
@@ -0,0 +1,314 @@
import request from '@/utils/request'
import { ResouceUrl } from '@/utils/baseconfig'
/**
 *
 * @param {*} data
 */
export function UploadFileAsync (data) {
  var param = new FormData()
  param.append('file', data.file)
  return request({
    url: ResouceUrl + '/api/File/UploadFileAsync',
    method: 'post',
    data: param,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}
export function UploadImageAsync (data) {
  var param = new FormData()
  param.append('file', data.file)
  return request({
    url: ResouceUrl + '/api/File/UploadImageAsync',
    method: 'post',
    data: param,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}
export function GetBusinessFollowRecordList (data) {
  return request({
    url: '/FollowRecord/GetBusinessFollowRecordList?SourceId=' + data.SourceId + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize + '&BusinessOperationType=' + data.BusinessOperationType,
    method: 'get'
  })
}
export function DeleteFollowRecord (data) {
  return request({
    url: '/FollowRecord/DeleteFollowRecord',
    method: 'post',
    data: data
  })
}
// 获取省
export function GetProvincesList (data) {
  return request({
    url: '/ProvinceCity/GetProvincesList',
    method: 'get'
  })
}
// 获取市
export function GetCityList (data) {
  return request({
    url: '/ProvinceCity/GetCityList?provinceId=' + data.provinceId,
    method: 'get'
  })
}
// 获取区
export function GetAreaList (data) {
  return request({
    url: '/ProvinceCity/GetAreaList?cityId=' + data.cityId,
    method: 'get'
  })
}
export function GetCusomterNumber (data) {
  return request({
    url: '/Number/GetCusomterNumber',
    method: 'get'
  })
}
export function GetSalesChanceNumber (data) {
  return request({
    url: '/Number/GetSalesChanceNumber',
    method: 'get'
  })
}
export function GetContacterNumber (data) {
  return request({
    url: '/Number/GetContacterNumber',
    method: 'get'
  })
}
export function GetAgreementNumber (data) {
  return request({
    url: '/Number/GetAgreementNumber',
    method: 'get'
  })
}
export function GetQuotationName (data) {
  return request({
    url: '/Number/GetQuotationName?salesChanceId=' + data.salesChanceId,
    method: 'get'
  })
}
export function GetAgreenmentName (data) {
  return request({
    url: '/Number/GetAgreenmentName?salesChanceId=' + data.salesChanceId,
    method: 'get'
  })
}
export function GetQuotationNumber (data) {
  return request({
    url: '/Number/GetQuotationNumber',
    method: 'get'
  })
}
export function GetSalesChanceName (data) {
  return request({
    url: '/Number/GetSalesChanceName?customerId=' + data.customerId,
    method: 'get'
  })
}
export function CustomerRepeatCheck (data) {
  return request({
    url: '/Customer/CustomerRepeatCheck?Name=' + data.Name,
    method: 'get'
  })
}
export function GetIndustryListChildrenData (data) {
  return request({
    url: '/Data/GetIndustryListChildrenData',
    method: 'get'
  })
}
export function ImportCustomerExcel (data) {
  var param = new FormData()
  // Object.keys(data).forEach(key => {
  param.append('file', data.file)
  // })
  return request({
    url: '/Excel/ImportCustomerExcel?excelImportType=' + data.excelImportType,
    method: 'post',
    data: param,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}
export function ImportContacterExcel (data) {
  var param = new FormData()
  // Object.keys(data).forEach(key => {
  param.append('file', data.file)
  // })
  return request({
    url: '/Excel/ImportContacterExcel?excelImportType=' + data.excelImportType,
    method: 'post',
    data: param,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}
export function ImportSalesChanceExcel (data) {
  var param = new FormData()
  // Object.keys(data).forEach(key => {
  param.append('file', data.file)
  // })
  return request({
    url: '/Excel/ImportSalesChanceExcel?excelImportType=' + data.excelImportType,
    method: 'post',
    data: param,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}
export function DownloadCustomerExcelModel (data) {
  return request({
    url: '/Excel/DownloadCustomerExcelModel',
    method: 'get',
    responseType: 'blob'
  })
}
export function DownloadContacgerExcelModel (data) {
  return request({
    url: '/Excel/DownloadContacgerExcelModel',
    method: 'get',
    responseType: 'blob'
  })
}
export function DownloadSalesChanceExcelModel (data) {
  return request({
    url: '/Excel/DownloadSalesChanceExcelModel',
    method: 'get',
    responseType: 'blob'
  })
}
export function OutputCustomerToExcel (data) {
  return request({
    url: '/Excel/OutputCustomerToExcel?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime +
    '&StartFollowTime=' + data.StartFollowTime +
    '&EndFolowTime=' + data.EndFolowTime,
    method: 'get',
    responseType: 'blob'
  })
}
export function OutputContacterToExcel (data) {
  return request({
    url: '/Excel/OutputContacterToExcel?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
    (data.BrachUserId
      ? '&BrachUserId=' + data.BrachUserId : '') +
    '&Name=' + data.Name,
    method: 'get',
    responseType: 'blob'
  })
}
export function OutputSalesChanceToExcel (data) {
  return request({
    url: '/Excel/OutputSalesChanceToExcel?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
    '&Name=' + data.Name +
    (data.BrachUserId
      ? '&BrachUserId=' + data.BrachUserId : '') +
    (data.SalesChanceStage
      ? '&SalesChanceStage=' + data.SalesChanceStage : '') +
    (data.ProvinceCode
      ? '&ProvinceCode=' + data.ProvinceCode : '') +
    (data.SalesChanceType
      ? '&SalesChanceType=' + data.SalesChanceType : '') +
    (data.ChanceUploadStatus
      ? '&ChanceUploadStatus=' + data.ChanceUploadStatus : '') +
    (data.ChanceReportStatus
      ? '&ChanceReportStatus=' + data.ChanceReportStatus : '') +
    (data.SalesChanceSubmissionMethod
      ? '&SalesChanceSubmissionMethod=' + data.SalesChanceSubmissionMethod : '') +
    (data.ProjectProperty
      ? '&ProjectProperty=' + data.ProjectProperty : '') +
    (data.UploadStatusName
      ? '&UploadStatusName=' + data.UploadStatusName : '') +
    (data.ReportStatusName
      ? '&ReportStatusName=' + data.ReportStatusName : '') +
    (data.CreateStartTime
      ? '&CreateStartTime=' + data.CreateStartTime : '') +
    (data.CreateEndTime
      ? '&CreateEndTime=' + data.CreateEndTime : '') +
    (data.DepartmentUserType
      ? '&DepartmentUserType=' + data.DepartmentUserType : '') +
      (data.Id
        ? '&Id=' + data.Id : ''),
    method: 'get',
    responseType: 'blob'
  })
}
export function OutputOtherSalesChanceToExcel (data) {
  return request({
    url: '/Excel/OutputOtherSalesChanceToExcel?PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
    '&Name=' + data.Name +
    (data.BrachUserId
      ? '&BrachUserId=' + data.BrachUserId : '') +
    (data.SalesChanceStage
      ? '&SalesChanceStage=' + data.SalesChanceStage : '') +
    (data.ProvinceCode
      ? '&ProvinceCode=' + data.ProvinceCode : '') +
    (data.SalesChanceType
      ? '&SalesChanceType=' + data.SalesChanceType : '') +
    (data.ChanceUploadStatus
      ? '&ChanceUploadStatus=' + data.ChanceUploadStatus : '') +
    (data.ChanceReportStatus
      ? '&ChanceReportStatus=' + data.ChanceReportStatus : '') +
    (data.SalesChanceSubmissionMethod
      ? '&SalesChanceSubmissionMethod=' + data.SalesChanceSubmissionMethod : '') +
    (data.ProjectProperty
      ? '&ProjectProperty=' + data.ProjectProperty : '') +
    (data.UploadStatusName
      ? '&UploadStatusName=' + data.UploadStatusName : '') +
    (data.ReportStatusName
      ? '&ReportStatusName=' + data.ReportStatusName : '') +
    (data.CreateStartTime
      ? '&CreateStartTime=' + data.CreateStartTime : '') +
      (data.CreateEndTime
        ? '&CreateEndTime=' + data.CreateEndTime : '') +
   (data.DepartmentUserType
     ? '&DepartmentUserType=' + data.DepartmentUserType : '') +
      (data.Id
        ? '&Id=' + data.Id : ''),
    method: 'get',
    responseType: 'blob'
  })
}
export function DownloadSubscriptions (data) {
  return request({
    url: '/AutoDesk/download/subscriptions/' + data.taskId,
    method: 'get',
    responseType: 'blob'
  })
}
export function GetProjectPropertyData (data) {
  return request({
    url: '/Data/GetProjectPropertyData',
    method: 'get'
  })
}
export function GetExtendProjectPropertyData (data) {
  return request({
    url: '/Data/GetExtendProjectPropertyData',
    method: 'get'
  })
}
export function GetWxSpUserList (data) {
  return request({
    url: '/Data/GetWxSpUserList',
    method: 'get'
  })
}
src/api/customermanagement/business.js
New file
@@ -0,0 +1,129 @@
import request from '@/utils/request'
export function GetSalesChanceList (data) {
  return request({
    url: '/SalesChance/GetSalesChanceList?PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
     (data.BrachUserId
       ? '&BrachUserId=' + data.BrachUserId : '') +
    '&Name=' + data.Name +
    (data.SalesChanceStage
      ? '&SalesChanceStage=' + data.SalesChanceStage : '') +
    (data.ProvinceCode
      ? '&ProvinceCode=' + data.ProvinceCode : '') +
    (data.SalesChanceType
      ? '&SalesChanceType=' + data.SalesChanceType : '') +
    (data.ChanceUploadStatus
      ? '&ChanceUploadStatus=' + data.ChanceUploadStatus : '') +
    (data.ChanceReportStatus
      ? '&ChanceReportStatus=' + data.ChanceReportStatus : '') +
    (data.SalesChanceSubmissionMethod
      ? '&SalesChanceSubmissionMethod=' + data.SalesChanceSubmissionMethod : '') +
    (data.ProjectProperty
      ? '&ProjectProperty=' + data.ProjectProperty : '') +
    (data.UploadStatusName
      ? '&UploadStatusName=' + data.UploadStatusName : '') +
    (data.ReportStatusName
      ? '&ReportStatusName=' + data.ReportStatusName : '') +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime,
    method: 'get'
  })
}
export function AddSalesChance (data) {
  return request({
    url: '/SalesChance/AddSalesChance',
    method: 'post',
    data: data
  })
}
export function UpdateSalesChance (data) {
  return request({
    url: '/SalesChance/UpdateSalesChance',
    method: 'post',
    data: data
  })
}
export function DeleteSalesChance (data) {
  return request({
    url: '/SalesChance/DeleteSalesChance',
    method: 'post',
    data: data
  })
}
export function GetSalesChanceDetail (data) {
  return request({
    url: '/SalesChance/GetSalesChanceDetail?Id=' + data.Id,
    method: 'get'
  })
}
export function GetSalesChanceFollowList (data) {
  return request({
    url: '/SalesChance/GetSalesChanceFollowList?Id=' + data.Id + '&Name=' + data.Name + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetSalesChanceAgreementList (data) {
  return request({
    url: '/SalesChance/GetSalesChanceAgreementList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetSalesChanceProductList (data) {
  return request({
    url: '/SalesChance/GetSalesChanceProductList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetSalesDocumentFileList (data) {
  return request({
    url: '/SalesChance/GetSalesDocumentFileList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetSalesChanceOperationLogList (data) {
  return request({
    url: '/SalesChance/GetSalesChanceOperationLogList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetSalesChanceQuotationSheetList (data) {
  return request({
    url: '/SalesChance/GetSalesChanceQuotationSheetList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetSalesChanceJobScheduleList (data) {
  return request({
    url: '/SalesChance/GetSalesChanceJobScheduleList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function ChangeSalesChanceStage (data) {
  return request({
    url: '/SalesChance/ChangeSalesChanceStage',
    method: 'post',
    data: data
  })
}
export function GetAutoSalesChanceLogList (data) {
  return request({
    url: '/SalesChance/GetAutoSalesChanceLogList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function DeleteSalesChanceProduct (data) {
  return request({
    url: '/SalesChance/DeleteSalesChanceProduct',
    method: 'post',
    data: data
  })
}
export function SubmitSalesChance (data) {
  return request({
    url: '/SalesChance/SubmitSalesChance',
    method: 'post',
    data: data
  })
}
src/api/customermanagement/contacts.js
New file
@@ -0,0 +1,62 @@
import request from '@/utils/request'
export function GetContacterList (data) {
  return request({
    url: '/Contacter/GetContacterList?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
     (data.BrachUserId
       ? '&BrachUserId=' + data.BrachUserId : '') +
    '&Name=' + data.Name +
    (data.ProvinceCode
      ? '&ProvinceCode=' + data.ProvinceCode : '') +
      (data.SelectOwnedType
        ? '&SelectOwnedType=' + data.SelectOwnedType : ''),
    method: 'get'
  })
}
export function AddContacter (data) {
  return request({
    url: '/Contacter/AddContacter',
    method: 'post',
    data: data
  })
}
export function UpdateContacter (data) {
  return request({
    url: '/Contacter/UpdateContacter',
    method: 'post',
    data: data
  })
}
export function DeleteContacter (data) {
  return request({
    url: '/Contacter/DeleteContacter',
    method: 'post',
    data: data
  })
}
export function GetPersonalContacterList (data) {
  return request({
    url: '/Contacter/GetPersonalContacterList?CustomerId=' + data.CustomerId + '&Name=' + data.Name + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetContacterDetail (data) {
  return request({
    url: '/Contacter/GetContacterDetail?Id=' + data.Id,
    method: 'get'
  })
}
export function GetContacterDocumentFileList (data) {
  return request({
    url: '/Contacter/GetContacterDocumentFileList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetContacterOperationLogList (data) {
  return request({
    url: '/Contacter/GetContacterOperationLogList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
src/api/customermanagement/contract.js
New file
@@ -0,0 +1,62 @@
import request from '@/utils/request'
export function AddAgreement (data) {
  return request({
    url: '/Agreement/AddAgreement',
    method: 'post',
    data: data
  })
}
export function UpdateAgreement (data) {
  return request({
    url: '/Agreement/UpdateAgreement',
    method: 'post',
    data: data
  })
}
export function GetAgreementList (data) {
  return request({
    url: '/Agreement/GetAgreementList?SelectOwnedType=' + data.SelectOwnedType + '&AuditStatus=' + data.AuditStatus +
     (data.BrachUserId
       ? '&BrachUserId=' + data.BrachUserId : '') +
    '&PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SealStatus=' + data.SealStatus +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime + (data.SealType
      ? '&SealType=' + data.SealType : ''),
    method: 'get'
  })
}
export function DeleteAgreenment (data) {
  return request({
    url: '/Agreement/DeleteAgreenment',
    method: 'post',
    data: data
  })
}
export function GetManagementAgreementList (data) {
  return request({
    url: '/Agreement/GetManagementAgreementList?SelectOwnedType=' + data.SelectOwnedType + '&AuditStatus=' + data.AuditStatus +
    '&PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SealStatus=' + data.SealStatus +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime + (data.DepartmentUserType
      ? '&DepartmentUserType=' + data.DepartmentUserType : '') +
      (data.Id
        ? '&Id=' + data.Id : '') +
        (data.SealType
          ? '&SealType=' + data.SealType : ''),
    method: 'get'
  })
}
export function AgreementToSeal (data) {
  return request({
    url: '/Agreement/AgreementToSeal',
    method: 'post',
    data: data
  })
}
src/api/customermanagement/customerManage.js
New file
@@ -0,0 +1,125 @@
import request from '@/utils/request'
export function GetCustomerPageList (data) {
  return request({
    url: '/Customer/GetCustomerPageList?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize +
    '&SelectOwnedType=' + data.SelectOwnedType +
     (data.BrachUserId
       ? '&BrachUserId=' + data.BrachUserId : '') +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime +
    '&StartFollowTime=' + data.StartFollowTime +
    '&EndFolowTime=' + data.EndFolowTime +
    (data.ProvinceCode ? '&ProvinceCode=' + data.ProvinceCode : '') +
    (data.CustomerBusinessStatus
      ? '&CustomerBusinessStatus=' + data.CustomerBusinessStatus : '') +
    (data.CustomerSource ? '&CustomerSource=' + data.CustomerSource : '') + (data.CustomerType ? '&CustomerType=' + data.CustomerType : '') +
    (data.CostomerCategory ? '&CostomerCategory=' + data.CostomerCategory : '') +
    (data.CustomerIndustry ? '&CustomerIndustry=' + data.CustomerIndustry : '') +
    (data.CompanyType ? '&CompanyType=' + data.CompanyType : ''),
    method: 'get'
  })
}
export function AddCustomer (data) {
  return request({
    url: '/Customer/AddCustomer',
    method: 'post',
    data: data
  })
}
export function UpdateCustomer (data) {
  return request({
    url: '/Customer/UpdateCustomer',
    method: 'post',
    data: data
  })
}
export function DeleteCustomer (data) {
  return request({
    url: '/Customer/DeleteCustomer',
    method: 'post',
    data: data
  })
}
export function GetPersonalCustomerPageList (data) {
  return request({
    url: '/Customer/GetPersonalCustomerPageList?Name=' + data.Name + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerDetail (data) {
  return request({
    url: '/Customer/GetCustomerDetail?Id=' + data.Id,
    method: 'get'
  })
}
export function GetCustomerFollowRecordList (data) {
  return request({
    url: '/Customer/GetCustomerFollowRecordList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function AddFollowRecord (data) {
  return request({
    url: '/FollowRecord/AddCustomerFollowRecord',
    method: 'post',
    data: data
  })
}
export function MakeFollowRecordCompleted (data) {
  return request({
    url: '/FollowRecord/MakeFollowRecordCompleted',
    method: 'post',
    data: data
  })
}
export function GetCustomerContacterList (data) {
  return request({
    url: '/Customer/GetCustomerContacterList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerSalesChanceList (data) {
  return request({
    url: '/Customer/GetCustomerSalesChanceList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerOrderList (data) {
  return request({
    url: '/Customer/GetCustomerOrderList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerAgreenmentList (data) {
  return request({
    url: '/Customer/GetCustomerAgreenmentList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerPaymentRecordList (data) {
  return request({
    url: '/Customer/GetCustomerPaymentRecordList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerPaymentPlanList (data) {
  return request({
    url: '/Customer/GetCustomerPaymentPlanList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerDocumentFileList (data) {
  return request({
    url: '/Customer/GetCustomerDocumentFileList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetCustomerOperationLogList (data) {
  return request({
    url: '/Customer/GetCustomerOperationLogList?Id=' + data.Id + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
src/api/customermanagement/offer.js
New file
@@ -0,0 +1,62 @@
import request from '@/utils/request'
export function AddQuatotationSheet (data) {
  return request({
    url: '/QuotationSheet/AddQuatotationSheet',
    method: 'post',
    data: data
  })
}
export function UpdateQuotationSheet (data) {
  return request({
    url: '/QuotationSheet/UpdateQuotationSheet',
    method: 'post',
    data: data
  })
}
export function GetQuotationSheetList (data) {
  return request({
    url: '/QuotationSheet/GetQuotationSheetList?SelectOwnedType=' + data.SelectOwnedType +
     (data.BrachUserId
       ? '&BrachUserId=' + data.BrachUserId : '') +
    '&AuditStatus=' + data.AuditStatus +
    '&PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SealStatus=' + data.SealStatus +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime,
    method: 'get'
  })
}
export function DeleteQuotationSheet (data) {
  return request({
    url: '/QuotationSheet/DeleteQuotationSheet',
    method: 'post',
    data: data
  })
}
export function GetManagementQuotationSheetList (data) {
  return request({
    url: 'QuotationSheet/GetManagementQuotationSheetList?AuditStatus=' + data.AuditStatus +
    '&PageIndex=' + data.PageIndex +
    '&PageSize=' + data.PageSize +
    '&SealStatus=' + data.SealStatus +
    '&Name=' + data.Name +
    '&CreateStartTime=' + data.CreateStartTime +
    '&CreateEndTime=' + data.CreateEndTime +
    (data.DepartmentUserType
      ? '&DepartmentUserType=' + data.DepartmentUserType : '') +
      (data.Id
        ? '&Id=' + data.Id : ''),
    method: 'get'
  })
}
export function QuotationSheetToSeal (data) {
  return request({
    url: '/QuotationSheet/QuotationSheetToSeal',
    method: 'post',
    data: data
  })
}
src/api/customermanagement/product.js
New file
@@ -0,0 +1,14 @@
import request from '@/utils/request'
export function GetAutoProductTypeList (data) {
  return request({
    url: '/Product/GetAutoProductTypeList',
    method: 'get'
  })
}
export function GetAutoProductListAsync (data) {
  return request({
    url: '/Product/GetAutoProductListAsync?' + (data.TypeName ? data.TypeName + '&' : '') + 'Name=' + data.Name + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
src/api/login.js
New file
@@ -0,0 +1,62 @@
import request from '@/utils/request'
export function requestverify (data) {
  return request({
    url: '/Account/Verify',
    method: 'get'
  })
}
export function CreateVerifyCode (token) {
  return request({
    url: '/Account/CreateVerifyCode?verify=' + token,
    method: 'get',
    responseType: 'arraybuffer'
  })
}
export function requestLogin (data) {
  return request({
    url: '/Account/Login',
    method: 'post',
    data: data
  })
}
export function FindPassword (data) {
  return request({
    url: '/Account/FindPassword',
    method: 'post',
    data: data
  })
}
export function FindPasswordStep2 (data) {
  return request({
    url: '/Account/FindPasswordStep2',
    method: 'post',
    data: data
  })
}
export function FindPasswordStep3 (data) {
  return request({
    url: '/Account/FindPasswordStep3',
    method: 'post',
    data: data
  })
}
export function WxLogin (code) {
  return request({
    url: '/Account/WxLogin?code=' + code,
    method: 'get'
  })
}
export function CheckLogin (token) {
  return request({
    url: '/Account/CheckLogin',
    method: 'post',
    data: token
  })
}
src/api/moduleManage/moduleManage.js
New file
@@ -0,0 +1,35 @@
import request from '@/utils/request'
export function GetSysModuleList (data) {
  return request({
    url: '/Module/GetSysModuleList',
    method: 'get'
  })
}
export function DeleteSysModule (data) {
  return request({
    url: '/Module/DeleteSysModule',
    method: 'post',
    data: data
  })
}
export function AddSysModule (data) {
  return request({
    url: '/Module/AddSysModule',
    method: 'post',
    data: data
  })
}
export function UpdateSysModule (data) {
  return request({
    url: '/Module/UpdateSysModule',
    method: 'post',
    data: data
  })
}
export function GetCurrentUserModules (data) {
  return request({
    url: '/User/GetCurrentUserModules',
    method: 'get'
  })
}
src/api/pwsApi/ewsAnalyze.js
New file
@@ -0,0 +1,11 @@
import request from '@/utils/request'
export function InsightsMetrics (data) {
  return request({
    url: '/AutoDesk/insightsMetrics/query?' +
    (data.CustomerCSN ? '&CustomerCSN=' + data.CustomerCSN : '') +
    (data.ContractNumber ? '&ContractNumber=' + data.ContractNumber : '') +
    (data.Plc ? '&Plc=' + data.Plc : ''),
    method: 'get'
  })
}
src/api/pwsApi/subscriptions.js
New file
@@ -0,0 +1,18 @@
import request from '@/utils/request'
export function ExportSubscriptionsTask (data) {
  return request({
    url: '/AutoDesk/create/export-subscriptions-task',
    method: 'post',
    data: data
  })
}
export function GetSubscriptionsTask (data) {
  return request({
    url: '/AutoDesk/export-subscriptions-task/paged?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize +
    (data.StartTime ? '&StartTime=' + data.StartTime : '') +
    (data.EndTime ? '&EndTime=' + data.EndTime : '') +
    (data.TaskStatus ? '&TaskStatus=' + data.TaskStatus : ''),
    method: 'get'
  })
}
src/api/systemManagement/departmentManage.js
New file
@@ -0,0 +1,63 @@
import request from '@/utils/request'
// export function GetDepartmentList (data) {
//   return request({
//     url: '/Department/GetDepartmentList',
//     method: 'get'
//   })
// }
export function AddDepartment (data) {
  return request({
    url: '/Department/AddDepartment',
    method: 'post',
    data: data
  })
}
export function DeleteDepartment (data) {
  return request({
    url: '/Department/DeleteDepartment',
    method: 'post',
    data: data
  })
}
export function UpdateDepartment (data) {
  return request({
    url: '/Department/UpdateDepartment',
    method: 'post',
    data: data
  })
}
export function GetDepartmentAreaList (data) {
  return request({
    url: '/Department/GetDepartmentAreaList',
    method: 'get'
  })
}
export function GetDepartmentUserChildList (data) {
  return request({
    url: '/Department/GetDepartmentUserChildList',
    method: 'get'
  })
}
export function GetSalesDepartmentUserChildList (data) {
  return request({
    url: '/Department/GetSalesDepartmentUserChildList',
    method: 'get'
  })
}
export function GetCurrentBranches (data) {
  return request({
    url: '/UserManager/GetCurrentBranches',
    method: 'get'
  })
}
export function GetDepartmentList (data) {
  return request({
    url: '/WxWork/GetDepartmentList',
    method: 'get'
  })
}
src/api/systemManagement/employeeManage.js
New file
@@ -0,0 +1,62 @@
import request from '@/utils/request'
export function GetUserInfoPageList (data) {
  return request({
    url: '/UserManager/GetUserInfoPageList?PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize + '&DepartmentId=' + data.DepartmentId + '&PositionId=' + data.PositionId + '&RealName=' + data.RealName + '&MobilePhone=' + data.MobilePhone,
    method: 'get'
  })
}
export function GetUserInfoDepartmentList (data) {
  return request({
    url: '/UserManager/GetUserInfoDepartmentList',
    method: 'get'
  })
}
export function GetUserInfoPositionList (data) {
  return request({
    url: '/UserManager/GetUserInfoPositionList',
    method: 'get'
  })
}
export function AddUserInfo (data) {
  return request({
    url: '/UserManager/AddUserInfo',
    method: 'post',
    data: data
  })
}
export function UpdateUserInfo (data) {
  return request({
    url: '/UserManager/UpdateUserInfo',
    method: 'post',
    data: data
  })
}
export function DeleteUserInfo (data) {
  return request({
    url: '/UserManager/DeleteUserInfo',
    method: 'post',
    data: data
  })
}
export function GetUserInfoList (data) {
  return request({
    url: '/WxWork/GetUserInfoList?DepartmentId=' + data.DepartmentId + '&RealName=' + data.RealName + '&MobilePhone=' + data.MobilePhone + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function UpdateUserPostion (data) {
  return request({
    url: '/UserManager/UpdateUserPostion',
    method: 'post',
    data: data
  })
}
export function BindUserSalesArea (data) {
  return request({
    url: '/UserManager/BindUserSalesArea',
    method: 'post',
    data: data
  })
}
src/api/systemManagement/log.js
New file
@@ -0,0 +1,14 @@
import request from '@/utils/request'
export function GetOperationLogList (data) {
  return request({
    url: '/Log/GetOperationLogList?StartTime=' + data.StartTime + '&EndTime=' + data.EndTime + '&RealName=' + data.RealName + '&BusinessOperationType=' + data.BusinessOperationType + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
export function GetLoginRecordList (data) {
  return request({
    url: '/Log/GetLoginRecordList?StartTime=' + data.StartTime + '&EndTime=' + data.EndTime + '&RealName=' + data.RealName + '&PageIndex=' + data.PageIndex + '&PageSize=' + data.PageSize,
    method: 'get'
  })
}
src/api/systemManagement/officalAuthority.js
New file
@@ -0,0 +1,42 @@
import request from '@/utils/request'
export function GetPositionList (data) {
  return request({
    url: '/Position/GetPositionList',
    method: 'get'
  })
}
export function AddPosition (data) {
  return request({
    url: '/Position/AddPosition',
    method: 'post',
    data: data
  })
}
export function DeletePosition (data) {
  return request({
    url: '/Position/DeletePosition',
    method: 'post',
    data: data
  })
}
export function UpdatePosition (data) {
  return request({
    url: '/Position/UpdatePosition',
    method: 'post',
    data: data
  })
}
export function GetPositionModules (data) {
  return request({
    url: '/PositionModule/GetPositionModules?positionId=' + data.Id,
    method: 'get'
  })
}
export function UpdatePositionModules (data) {
  return request({
    url: '/PositionModule/UpdatePositionModules',
    method: 'post',
    data: data
  })
}
src/assets/401_images/1.gif
src/assets/401_images/401.gif
src/assets/404_images/404.png
src/assets/404_images/404_cloud.png
src/assets/aside/business.png
src/assets/aside/business_active.png
src/assets/aside/check.png
src/assets/aside/company.png
src/assets/aside/company_active.png
src/assets/aside/customer.png
src/assets/aside/customer_active.png
src/assets/aside/delete.png
src/assets/aside/dilivery.png
src/assets/aside/export.png
src/assets/aside/financial.png
src/assets/aside/financial_active.png
src/assets/aside/import.png
src/assets/aside/order.png
src/assets/aside/order_active.png
src/assets/aside/personnel.png
src/assets/aside/personnel_active.png
src/assets/aside/product.png
src/assets/aside/product_active.png
src/assets/aside/system.png
src/assets/aside/system_active.png
src/assets/aside/total.png
src/assets/aside/total_active.png
src/assets/aside/workbench.png
src/assets/aside/workbench_active.png
src/assets/css/normalize.css
New file
@@ -0,0 +1,460 @@
/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
   ========================================================================== */
html,
body,
#app {
    height: 100%;
    margin: 0;
    padding: 0;
}
#app {
    /*min-width: 1366px;*/
}
.el-breadcrumb {
    margin-bottom: 15px;
    font-size: 12px;
}
.el-card {
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15) !important;
}
.el-table {
    margin-top: 15px;
    font-size: 12px;
}
.el-pagination {
    margin-top: 15px;
}
.ql-editor {
    min-height: 300px;
}
.el-scrollbar__wrap {
    overflow-x: hidden;
}
.el-scrollbar .el-scrollbar__wrap {
    overflow-x: hidden;
}
/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */
html {
    line-height: 1.15;
    /* 1 */
    -webkit-text-size-adjust: 100%;
    /* 2 */
}
/* Sections
   ========================================================================== */
/**
 * Remove the margin in all browsers.
 */
body {
    margin: 0;
}
ul,
li {
    padding: 0;
    margin: 0;
    list-style: none;
}
/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */
h1 {
    font-size: 2em;
    margin: 0.67em 0;
}
/* Grouping content
   ========================================================================== */
/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */
hr {
    box-sizing: content-box;
    /* 1 */
    height: 0;
    /* 1 */
    overflow: visible;
    /* 2 */
}
/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
pre {
    font-family: monospace, monospace;
    /* 1 */
    font-size: 1em;
    /* 2 */
}
/* Text-level semantics
   ========================================================================== */
/**
 * Remove the gray background on active links in IE 10.
 */
a {
    background-color: transparent;
    text-decoration: none;
}
/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
 */
abbr[title] {
    border-bottom: none;
    /* 1 */
    text-decoration: underline;
    /* 2 */
    text-decoration: underline dotted;
    /* 2 */
}
/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */
b,
strong {
    font-weight: bolder;
}
/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
code,
kbd,
samp {
    font-family: monospace, monospace;
    /* 1 */
    font-size: 1em;
    /* 2 */
}
/**
 * Add the correct font size in all browsers.
 */
small {
    font-size: 80%;
}
/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */
sub,
sup {
    font-size: 75%;
    line-height: 0;
    position: relative;
    vertical-align: baseline;
}
sub {
    bottom: -0.25em;
}
sup {
    top: -0.5em;
}
/* Embedded content
   ========================================================================== */
/**
 * Remove the border on images inside links in IE 10.
 */
img {
    border-style: none;
}
/* Forms
   ========================================================================== */
/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */
button,
input,
optgroup,
select,
textarea {
    font-family: inherit;
    /* 1 */
    font-size: 100%;
    /* 1 */
    line-height: 1.15;
    /* 1 */
    margin: 0;
    /* 2 */
}
/**
 * Show the overflow in IE.
 * 1. Show the overflow in Edge.
 */
button,
input {
    /* 1 */
    overflow: visible;
}
/**
 * Remove the inheritance of text transform in Edge, Firefox, and IE.
 * 1. Remove the inheritance of text transform in Firefox.
 */
button,
select {
    /* 1 */
    text-transform: none;
}
/**
 * Correct the inability to style clickable types in iOS and Safari.
 */
button,
[type="button"],
[type="reset"],
[type="submit"] {
    -webkit-appearance: button;
}
/**
 * Remove the inner border and padding in Firefox.
 */
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
    border-style: none;
    padding: 0;
}
/**
 * Restore the focus styles unset by the previous rule.
 */
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
    outline: 1px dotted ButtonText;
}
/**
 * Correct the padding in Firefox.
 */
fieldset {
    padding: 0.35em 0.75em 0.625em;
}
/**
 * 1. Correct the text wrapping in Edge and IE.
 * 2. Correct the color inheritance from `fieldset` elements in IE.
 * 3. Remove the padding so developers are not caught out when they zero out
 *    `fieldset` elements in all browsers.
 */
legend {
    box-sizing: border-box;
    /* 1 */
    color: inherit;
    /* 2 */
    display: table;
    /* 1 */
    max-width: 100%;
    /* 1 */
    padding: 0;
    /* 3 */
    white-space: normal;
    /* 1 */
}
/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */
progress {
    vertical-align: baseline;
}
/**
 * Remove the default vertical scrollbar in IE 10+.
 */
textarea {
    overflow: auto;
}
/**
 * 1. Add the correct box sizing in IE 10.
 * 2. Remove the padding in IE 10.
 */
[type="checkbox"],
[type="radio"] {
    box-sizing: border-box;
    /* 1 */
    padding: 0;
    /* 2 */
}
/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
    height: auto;
}
/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */
[type="search"] {
    -webkit-appearance: textfield;
    /* 1 */
    outline-offset: -2px;
    /* 2 */
}
/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */
[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
}
/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */
::-webkit-file-upload-button {
    -webkit-appearance: button;
    /* 1 */
    font: inherit;
    /* 2 */
}
/* Interactive
   ========================================================================== */
/*
 * Add the correct display in Edge, IE 10+, and Firefox.
 */
details {
    display: block;
}
/*
 * Add the correct display in all browsers.
 */
summary {
    display: list-item;
}
/* Misc
   ========================================================================== */
/**
 * Add the correct display in IE 10+.
 */
template {
    display: none;
}
/**
 * Add the correct display in IE 10.
 */
[hidden] {
    display: none;
}
src/assets/fonts/demo.css
New file
@@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
  font-family: "iconfont logo";
  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
  font-family: "iconfont logo";
  font-size: 160px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
  position: relative;
}
.nav-tabs .nav-more {
  position: absolute;
  right: 0;
  bottom: 0;
  height: 42px;
  line-height: 42px;
  color: #666;
}
#tabs {
  border-bottom: 1px solid #eee;
}
#tabs li {
  cursor: pointer;
  width: 100px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  font-size: 16px;
  border-bottom: 2px solid transparent;
  position: relative;
  z-index: 1;
  margin-bottom: -1px;
  color: #666;
}
#tabs .active {
  border-bottom-color: #f00;
  color: #222;
}
.tab-container .content {
  display: none;
}
/* 页面布局 */
.main {
  padding: 30px 100px;
  width: 960px;
  margin: 0 auto;
}
.main .logo {
  color: #333;
  text-align: left;
  margin-bottom: 30px;
  line-height: 1;
  height: 110px;
  margin-top: -50px;
  overflow: hidden;
  *zoom: 1;
}
.main .logo a {
  font-size: 160px;
  color: #333;
}
.helps {
  margin-top: 40px;
}
.helps pre {
  padding: 20px;
  margin: 10px 0;
  border: solid 1px #e7e1cd;
  background-color: #fffdef;
  overflow: auto;
}
.icon_lists {
  width: 100% !important;
  overflow: hidden;
  *zoom: 1;
}
.icon_lists li {
  width: 100px;
  margin-bottom: 10px;
  margin-right: 20px;
  text-align: center;
  list-style: none !important;
  cursor: default;
}
.icon_lists li .code-name {
  line-height: 1.2;
}
.icon_lists .icon {
  display: block;
  height: 100px;
  line-height: 100px;
  font-size: 42px;
  margin: 10px auto;
  color: #333;
  -webkit-transition: font-size 0.25s linear, width 0.25s linear;
  -moz-transition: font-size 0.25s linear, width 0.25s linear;
  transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
  font-size: 100px;
}
.icon_lists .svg-icon {
  /* 通过设置 font-size 来改变图标大小 */
  width: 1em;
  /* 图标和文字相邻时,垂直对齐 */
  vertical-align: -0.15em;
  /* 通过设置 color 来改变 SVG 的颜色/fill */
  fill: currentColor;
  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
      normalize.css 中也包含这行 */
  overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
  color: #666;
}
/* markdown 样式 */
.markdown {
  color: #666;
  font-size: 14px;
  line-height: 1.8;
}
.highlight {
  line-height: 1.5;
}
.markdown img {
  vertical-align: middle;
  max-width: 100%;
}
.markdown h1 {
  color: #404040;
  font-weight: 500;
  line-height: 40px;
  margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
  color: #404040;
  margin: 1.6em 0 0.6em 0;
  font-weight: 500;
  clear: both;
}
.markdown h1 {
  font-size: 28px;
}
.markdown h2 {
  font-size: 22px;
}
.markdown h3 {
  font-size: 16px;
}
.markdown h4 {
  font-size: 14px;
}
.markdown h5 {
  font-size: 12px;
}
.markdown h6 {
  font-size: 12px;
}
.markdown hr {
  height: 1px;
  border: 0;
  background: #e9e9e9;
  margin: 16px 0;
  clear: both;
}
.markdown p {
  margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
  width: 80%;
}
.markdown ul>li {
  list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
  margin-left: 20px;
  padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
  margin: 0.6em 0;
}
.markdown ol>li {
  list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
  margin-left: 20px;
  padding-left: 4px;
}
.markdown code {
  margin: 0 3px;
  padding: 0 5px;
  background: #eee;
  border-radius: 3px;
}
.markdown strong,
.markdown b {
  font-weight: 600;
}
.markdown>table {
  border-collapse: collapse;
  border-spacing: 0px;
  empty-cells: show;
  border: 1px solid #e9e9e9;
  width: 95%;
  margin-bottom: 24px;
}
.markdown>table th {
  white-space: nowrap;
  color: #333;
  font-weight: 600;
}
.markdown>table th,
.markdown>table td {
  border: 1px solid #e9e9e9;
  padding: 8px 16px;
  text-align: left;
}
.markdown>table th {
  background: #F7F7F7;
}
.markdown blockquote {
  font-size: 90%;
  color: #999;
  border-left: 4px solid #e9e9e9;
  padding-left: 0.8em;
  margin: 1em 0;
}
.markdown blockquote p {
  margin: 0;
}
.markdown .anchor {
  opacity: 0;
  transition: opacity 0.3s ease;
  margin-left: 8px;
}
.markdown .waiting {
  color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
  opacity: 1;
  display: inline-block;
}
.markdown>br,
.markdown>p>br {
  clear: both;
}
.hljs {
  display: block;
  background: white;
  padding: 0.5em;
  color: #333333;
  overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
  color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
  color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
  color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
  color: #0086b3;
}
.hljs-section,
.hljs-name {
  color: #63a35c;
}
.hljs-tag {
  color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
  color: #795da3;
}
.hljs-addition {
  color: #55a532;
  background-color: #eaffea;
}
.hljs-deletion {
  color: #bd2c00;
  background-color: #ffecec;
}
.hljs-link {
  text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
 * prism.js default theme for JavaScript, CSS and HTML
 * Based on dabblet (http://dabblet.com)
 * @author Lea Verou
 */
code[class*="language-"],
pre[class*="language-"] {
  color: black;
  background: none;
  text-shadow: 0 1px white;
  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  text-align: left;
  white-space: pre;
  word-spacing: normal;
  word-break: normal;
  word-wrap: normal;
  line-height: 1.5;
  -moz-tab-size: 4;
  -o-tab-size: 4;
  tab-size: 4;
  -webkit-hyphens: none;
  -moz-hyphens: none;
  -ms-hyphens: none;
  hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
  text-shadow: none;
  background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
  text-shadow: none;
  background: #b3d4fc;
}
@media print {
  code[class*="language-"],
  pre[class*="language-"] {
    text-shadow: none;
  }
}
/* Code blocks */
pre[class*="language-"] {
  padding: 1em;
  margin: .5em 0;
  overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
  background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
  padding: .1em;
  border-radius: .3em;
  white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
  color: slategray;
}
.token.punctuation {
  color: #999;
}
.namespace {
  opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
  color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
  color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
  color: #9a6e3a;
  background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
  color: #07a;
}
.token.function,
.token.class-name {
  color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
  color: #e90;
}
.token.important,
.token.bold {
  font-weight: bold;
}
.token.italic {
  font-style: italic;
}
.token.entity {
  cursor: help;
}
src/assets/fonts/demo_index.html
New file
@@ -0,0 +1,329 @@
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>IconFont Demo</title>
  <link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
  <link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
  <link rel="stylesheet" href="demo.css">
  <link rel="stylesheet" href="iconfont.css">
  <script src="iconfont.js"></script>
  <!-- jQuery -->
  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
  <!-- 代码高亮 -->
  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
</head>
<body>
  <div class="main">
    <h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
    <div class="nav-tabs">
      <ul id="tabs" class="dib-box">
        <li class="dib active"><span>Unicode</span></li>
        <li class="dib"><span>Font class</span></li>
        <li class="dib"><span>Symbol</span></li>
      </ul>
    </div>
    <div class="tab-container">
      <div class="content unicode" style="display: block;">
          <ul class="icon_lists dib-box">
            <li class="dib">
              <span class="icon iconfont">&#xea3f;</span>
                <div class="name">show-password </div>
                <div class="code-name">&amp;#xea3f;</div>
              </li>
            <li class="dib">
              <span class="icon iconfont">&#xe830;</span>
                <div class="name">user</div>
                <div class="code-name">&amp;#xe830;</div>
              </li>
            <li class="dib">
              <span class="icon iconfont">&#xa;</span>
                <div class="name">users</div>
                <div class="code-name">&amp;#xa;</div>
              </li>
            <li class="dib">
              <span class="icon iconfont">&#xe8c9;</span>
                <div class="name">225默认头像</div>
                <div class="code-name">&amp;#xe8c9;</div>
              </li>
            <li class="dib">
              <span class="icon iconfont">&#xe902;</span>
                <div class="name">406报表</div>
                <div class="code-name">&amp;#xe902;</div>
              </li>
            <li class="dib">
              <span class="icon iconfont">&#xe734;</span>
                <div class="name">password</div>
                <div class="code-name">&amp;#xe734;</div>
              </li>
            <li class="dib">
              <span class="icon iconfont">&#xe6af;</span>
                <div class="name">lock-fill</div>
                <div class="code-name">&amp;#xe6af;</div>
              </li>
          </ul>
          <div class="article markdown">
          <h2 id="unicode-">Unicode 引用</h2>
          <hr>
          <p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
          <ul>
            <li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
            <li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
            <li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
          </ul>
          <blockquote>
            <p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式</p>
          </blockquote>
          <p>Unicode 使用步骤如下:</p>
          <h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
  font-family: 'iconfont';
  src: url('iconfont.eot');
  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
      url('iconfont.woff2') format('woff2'),
      url('iconfont.woff') format('woff'),
      url('iconfont.ttf') format('truetype'),
      url('iconfont.svg#iconfont') format('svg');
}
</code></pre>
          <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
</code></pre>
          <h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
          <blockquote>
            <p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
          </blockquote>
          </div>
      </div>
      <div class="content font-class">
        <ul class="icon_lists dib-box">
          <li class="dib">
            <span class="icon iconfont icon-showpassword"></span>
            <div class="name">
              show-password
            </div>
            <div class="code-name">.icon-showpassword
            </div>
          </li>
          <li class="dib">
            <span class="icon iconfont icon-user"></span>
            <div class="name">
              user
            </div>
            <div class="code-name">.icon-user
            </div>
          </li>
          <li class="dib">
            <span class="icon iconfont icon-users"></span>
            <div class="name">
              users
            </div>
            <div class="code-name">.icon-users
            </div>
          </li>
          <li class="dib">
            <span class="icon iconfont icon-morentouxiang"></span>
            <div class="name">
              225默认头像
            </div>
            <div class="code-name">.icon-morentouxiang
            </div>
          </li>
          <li class="dib">
            <span class="icon iconfont icon-baobiao"></span>
            <div class="name">
              406报表
            </div>
            <div class="code-name">.icon-baobiao
            </div>
          </li>
          <li class="dib">
            <span class="icon iconfont icon-password"></span>
            <div class="name">
              password
            </div>
            <div class="code-name">.icon-password
            </div>
          </li>
          <li class="dib">
            <span class="icon iconfont icon-lock-fill"></span>
            <div class="name">
              lock-fill
            </div>
            <div class="code-name">.icon-lock-fill
            </div>
          </li>
        </ul>
        <div class="article markdown">
        <h2 id="font-class-">font-class 引用</h2>
        <hr>
        <p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
        <p>与 Unicode 使用方式相比,具有如下特点:</p>
        <ul>
          <li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
          <li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
          <li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
          <li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
        </ul>
        <p>使用步骤如下:</p>
        <h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
        <h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
        <blockquote>
          <p>"
            iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
        </blockquote>
      </div>
      </div>
      <div class="content symbol">
          <ul class="icon_lists dib-box">
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-showpassword"></use>
                </svg>
                <div class="name">show-password </div>
                <div class="code-name">#icon-showpassword</div>
            </li>
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-user"></use>
                </svg>
                <div class="name">user</div>
                <div class="code-name">#icon-user</div>
            </li>
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-users"></use>
                </svg>
                <div class="name">users</div>
                <div class="code-name">#icon-users</div>
            </li>
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-morentouxiang"></use>
                </svg>
                <div class="name">225默认头像</div>
                <div class="code-name">#icon-morentouxiang</div>
            </li>
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-baobiao"></use>
                </svg>
                <div class="name">406报表</div>
                <div class="code-name">#icon-baobiao</div>
            </li>
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-password"></use>
                </svg>
                <div class="name">password</div>
                <div class="code-name">#icon-password</div>
            </li>
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-lock-fill"></use>
                </svg>
                <div class="name">lock-fill</div>
                <div class="code-name">#icon-lock-fill</div>
            </li>
          </ul>
          <div class="article markdown">
          <h2 id="symbol-">Symbol 引用</h2>
          <hr>
          <p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
            这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
          <ul>
            <li>支持多色图标了,不再受单色限制。</li>
            <li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
            <li>兼容性较差,支持 IE9+,及现代浏览器。</li>
            <li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
          </ul>
          <p>使用步骤如下:</p>
          <h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
          <h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
&lt;/style&gt;
</code></pre>
          <h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
  &lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
          </div>
      </div>
    </div>
  </div>
  <script>
  $(document).ready(function () {
      $('.tab-container .content:first').show()
      $('#tabs li').click(function (e) {
        var tabContent = $('.tab-container .content')
        var index = $(this).index()
        if ($(this).hasClass('active')) {
          return
        } else {
          $('#tabs li').removeClass('active')
          $(this).addClass('active')
          tabContent.hide().eq(index).fadeIn()
        }
      })
    })
  </script>
</body>
</html>
src/assets/fonts/iconfont.css
New file
@@ -0,0 +1,341 @@
@font-face {font-family: "wukong";
  src: url('iconfont.eot?t=1565078640369'); /* IE9 */
  src: url('iconfont.eot?t=1565078640369#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAADJoAAsAAAAAXbQAADIWAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCMcAqBmHT3DQE2AiQDgkQLgSQABCAFhFUHiTwbY0tlBGwcAGjbvoKiKImqGkXFppb9/9fk5HCF2uC/hwSOdMVcG2qjwSdWJOwjcCjn4yM+6YLV8EIlccvH1H1dFIjPSiWmaGIevJL6zGG2qESllo89YKIwk4Zxw33pP6JJjXtIUjSJiP347fuu0okMiZTxjNdIPgz+bdv7sLGBqJ52Q7JkzybP166d3geJtAAkoSTyO8YNgCFeN//eyNxAGCEghCVhDSUkhLEDCVNhJ5awFcI0cTBcCOIgaDXuEjr84thE/S2lBqVLRcHSiqMLcXVr4J86MxfFMIAdL+UwzepGsOKdgNT+vt/z/svtkz9JxV065FQSr0SkFe0yadPHoYV25ds5siynBsRl9+30qZI2Px/475fO/LMz3E+5omguli5/Tu3NIp5ARtIyuws28839tgdpv4oKonaCida/UDGLGvEofrcLGR61ucDgBGWZ9dylrlzNd9JPKq3WkLAh4YqgzfQPzG6s1m6PntgQID7MaWkM7d1IspPFA4AXIBgWMJtNDqmbj/2Vv5IcarptsHSYHBA6zuN9FwF/r6quhOhWJLtvZmodFl/WDGPGbMmw4H0AFB9AyAIoygIhngW6gnAhKCtHkC4qKZLCXKsVIOVCSckBKndiqpgqpbapDUsdc3umNeuWy5Y1y7iGJ34nSYIfwKJ6JydJoJPBQGjqhtjUC/znYGpTt83Pf8ZcPWltI3KlX0QcuC5vr2Fsa3b8HECJeWdkCqhxm1OcvU9Vgipmu7cCitdBUwqqAhEmqSlkXSMGLaOrv8plyZbxVXkrfvriv1XgASW8FGxH9fRKXgGOsqyBjX1elM7+/EYG5VAKcyhDySdybfGmSh1jTqmxVMuKsuCHMaTMzDiXBiUqrVHN6PXTh0+fPH0dppoaGyytjAorTvMrnrhIGQ2tWt/Cyfrv7NnGC8/uxEs2bNnxjvpwUj//N3mUOBUubdp16NSlW49effoNGDRk2IhRY8ZNmDRl2oxZc+YtWLRk2YpVa9Zt2LRl245de/YdOHRkw7ETp86cu1TqVcY1IX2u3bhz616134MnNRbTarM7NFNUAOy/daD0F3ueyTIbJYgnWkg2CqQIraQYbaQE7aQMHaQcnaQCXaQS3USDHrIGvUSLPlKNflKLAVKHQVKPIdKAYdKIEbIWo2QdxkgTxkkzJogOk6QFU6QV06QNM6Qds6QDc6QT82Q9Fogei8SAJbIBy2QjVsgmrJLNWCNdWCfd2CA92CS92CJbsE22Yodswy7Zjj2yA/ukDwdkJw5JP47IwCw/u4BjMogTshunZA/OyF6ck324JEMoRYy4IDdQhjxEObKACuQJKpHXqEL+wxV5h2vyHjfEhjt+A9zyG8I9v2FU4zeCR36jeOA3Bk/8Jm4iNFQt4oKqQyJQ9UgUqgGJw6aTYlQTosHRfGv+x3fFy4Wuzwbeb0fJGu9yVTDrBg8sg+kQiiO0e1McjBCEUyWeQkFwHaF7RJ/VUI2FiRqRsrkEdTA8lFXTOStj8xXMvpIrYU+GiNiNMUTLJxFiSyQYoO3sMqU2RfxlJpZBIhkqlJokKhKjnDetFCLRoBCndfYXicb1ihufSegmnbaAE05IwzloMHITRcIIoZDkmIzG3V5MG/OHw8HSSQ8vvOwHr3IsQAQItxQZiBkxA5wE+fSqFxj7Xb+RfL/43LqvdN22MVODcR9ETQ0hE44mxFApPSsskp+njNsIeBVAr7uYzSZR7ifHYM0IiZO3WegxkxVEMBgilGTeb0iyH50U8n6ynUk8RD8ZfjRS6biffPSnzRTbBsi6cKgo4A+B6Tg/i2yqHgQl0mFSGdMrzIEOXOZYmfTkhCU71z3JnmD6grMPzt+LOWhmPE0wU3NCmRmTqACGxLWokjjXWZTMIyT4ImQCBMebR43F7Cr/sDhhdvIekesv8afwYzODrir5PllC/scCBQPiJKM6kttQGX0V0k5aU4HnRL5s1x2mDGLet7hn8/jvZT+7YmaUA8aHPhLE3L5vhgBMGk5njxmkkbi0U4rtgL5/kvXST1onfvDbaC/9SaGTXwar/bNdBGBFiaBJjdkx4Qsitw503qSEwyX8uH3/4stETz7WhmcKtZ8KHQ5oS99HwXWuccMkTOq8fDqpaKNTJFlEoqS4GjdJBZ6AMwQME7bGxuYXEsykW5bqjJfkZ37e3qsFo3ARHDci12Y31HDUCK3hI1BmA5AJaWdnfkRYgXbzGP0wzQk64bw/aIYyL7iuksYpuyCrN7hHbWQ+05Wf1hp2WW/LizM8Kayb+9AdpdjphnKIN+2iNqprry08KngKxTThKTDkUlfOrAEfq5GbNKVwUfg/6yrv5oiNuVAlEDKKnPUFtgLFH3y8vYBo7tznksNejyI44MGgcEXOHag4lK5U/9lcVpFVbphv67r6ZUGNfSezFTVvyoww7ff7DR/+MdkxtEVMVviwBp7jyUjpkt0qfN7PwDrA2KGKYyAe1JuVURgP3xG8Ur4RoiTOCQ4rW8V0EOJ7QbXGMgFjWRYxLi5P+uW+ildXVPCjbWbOKC8DOlAJc9ChC3O0u8G1qzpv7Tkcl9OCAbwaOU0IbKkpDNM4xaQXaC8J0UdJs3XkSiAKs2iOARN9FzHv/CVER6QJUDpNYprxuCw4PKVWoK2+6bA8AhzklomyiV78zr99KeIN5iGMsRR5gU7kjO41zx5dEbYE2pNliN5y5VM1dUdQR8yOY3IVBoIr8SpB53eyM/6ptxZ/JdGkpkvDTJTDZfzyNUOq6I9F5Bc7CBycAhbQHRMsTncpp9p0jR7jYOQnXrRu1uPgeEuFmyRgXF8VW0J3hC41KzILtT/IJAqLyFOqS7XBcwCoYiPtuIFHxMMIVVTvxGD4BqG2sS9945XDk6YE5HtuQ5PzkHCdMkan4kvVUh8PgzSYtiC1OXslBbf34olPhdNDuBxKjyZTxpMyaKJJYngB9tGKphBrbGCUpUk8yoSAcWISBucN5UqVe8NCf44+hp/GuQwXPHXc3Aj0NcqZgt9GLU4aIHExJJN7m+opwQqc8Klj0do/sbb8mXP3c/9+lf0yy9LLNFW/9J87O3fKf8X6f0KD7w/JRjidcPXfUF81WC3fidCxE2O2XGoT3ExJdfZgg8uMWDMlaLsWAjXZc4QazKSAlmvXou1lNh60sgY8xIWgifQcXX24jpz8Z4B6qwDoNp3UN5ukQYhzT23QluXfvaoyzmvNUxkVA/DW5x4IIR1wKuA3mBf8pmUhajN9S66RK4mgaX9rJC1o8CiMtedPJCaT3mtv2mj+Rpod9PuFsyevAxOoumSqNsWgKlbWOH5H8gCMWEI6NpP2R/tYNMfvh6jQ7UsZTZQrXaEK7RHgu32GeXUVJKJq5dDkVCqDbno9PCOYsZt7Ztl7CNMkhKH1eWtdexJ7jH3A0pApTBW7yf2djGj12lWN94zXmf83CW8nWgg87UnkHKHQygTBmnf21ZHmGTMRDne9sa4mq37ZC/03bqy7peyjr5x+CpsDoPj4dsERSSlDaf9M5HfHpT9DHFjAPN9wZZjeyMwglK0m/V7C4Unfume08A25zhufK9fLg06fp0wfNHDolDJOEMwNzmlU5whJ1ESXBU1wjTd6Vz40gfAt1L5PV2uDHFChZVWRaAjflSJLSEds+NO9EhBVAiNQiK/k4BLxsz9jWZmB8jbXLwj3eoLTYep9R6NZ6CXfBdo9lcrI/iEEvsK468AJ9JklSC7NOfMvbKg5dM1Zxnzn9yjhUA6JGcfSNWWqNZeSs42GdFAi2Vc+EoZMxzD5FVAVVGPH3lyaoCtn3qRMFH4b0rW1Ay4hpUTTmEL0ekiiCORYcGXzossyNipXGxmqitwQyoy4fd44nIhinKoV0K4B+mG966cz9g20Na2q2Gi5VhOSNeGov7eaN8JG+ABWGMGosfMbOM+NMdmewwjjNqRd5Fie5NsMVIa21NYa/H7jQfdlFai9/qNk5lBrwurknubqjAG7NmJBTBmg7IhCWdubxxpI9Zx+8t1fMqIq2OIeCUWRghfAI+aoIP2TsB04URA2lQbGSF+gaXIsKcGUD8rlvSYpAoMBESnQuq5RmtIMaWt3gnEKCe7KwRVoF2/lGVVMibIuAu9K1ZTKeQxGXRXZK5XauDKcUboaTDEg1NdKSyVc9tOkm8a3pIk0ROZ2TTWoMdNpTRD0nUSVDMcp4JVEiaB5gZT+G8kTo7W6bzw78tIbcjc/qTaFQDPJ20LhxlCiYP4AdRZR2HI3drwyvkgeHLIOH7F3HSqZRw4/KwkeFAnxRQbevmdX+2fsZ+tX/G6OzC+IDj/v4q0jHKio8MvWSTFSZw4bcAtQ2mnV6KZySbq0i0byN7F1WTEmiKnnAJKMACQSTaCyDStjRItQItQ1MYcI/awGJxIQG0bDmdt+QOrIKAElehNhs0eaiSsV4dgRlcJFi1XNWYRPpNkozJtf6+a3+DtYZM1158PjqlErjzQjMDs7K7Utg8Zhs1Z4KRpLPikQZcbaI5KHS1SNpyxojBh3BFfHjOUQOUgLizk9NiS8N9Xwme0jVvtuH182vqy2XROmvQ6lbyPWmHJRrkBDaiIXnNhhLaWDWOFhYZezWTmaNBu+70589gcR+mA7UdSUEXAUGPqWH73SHKgM+sy/3GuyqLCYu3bssLOAf8oxm8UGh7hwLFhr794QgpMT7UAFe/sHvqNShksu/XOqUpSGyrP6KtVcu4pxSuGy1F1v9pHr/R++dIZa1fNrb934CZTq9zfnxxpz5x7LBNqSm5Ml7kT5Tqm2lhCoa6RjSlR4KxVJDwPtFUL0JQLsNRcFHa1CK9VDSllcDRJpIY0do6a2cEuOtzPqo88+uXTaZT3xS8aXC1swiUwyfQLG5s51/KTPfHjjUkDatOoJ9upmI0G5W64yG7NORsxkWcLJXww5ysGwfeoPhtPUbg2T0tSBHylxwc8Eb6uUDztTxR07Gw7GUwYazmTNETD1tCFGGmk4D9ov3du2axsybQqJFOCg/QBKST173vYE6rR1hlMx0K7V/T+nZULef3n1w30HsfbtJMtmo39Zpm3HdWCq9WRxRl/5VorqYdq5oUzD1lZV1da5Bv5wE4WD7I7yPZ494HQH/NlektqGNJgWpsOeXrT59ehgr7I8ZXUuR6lEhxHbTaQUizWrSX/O94LdV8Sj6Q2BpCeTrFWY0gb1zoEm1Uwww3D61pot3vsOGUKfYuKRMBr+oVOgTM/35G5vYzYlW4NIXSIZGduQFmbj2pK2Y5qy/amttLW1QBDu1YYgIn+Q4ZL0Vzw90uC1+nJaA6cmNd6uulD/baJiPZpRGRpNRJnbsZ1QuoHGOV1Id0T9Qbqtwr1h+JSDKtHWapPXCREDmdrkXaLK8lfB4WQNj3oVPc0gbAWRSeQoJv0L4brrPEpgMiCtIXfVjYQ+YzTVRaYbB87EFyImcZ6qBMpxRDhG3mhyfMywGphX2Ad585QqKpUdM9CTdZhSmAzuIG45xseUIx+VXknTLavnclC8YIeflhuPY6cQqcf9kk+kfh26gVfl076daa4Vgbx542JafbR330xrbMaK0dISNm3mPo2PJSHSM9+a8U1VNxwjklRkjDfXgH2K75SseAULl9omqqCXQOTz5Q6hmIlHnCgE8IFJSw/Rp2Ea6/WgkyMS5+amSJ0N170ZRyxoAIizZDFwofD7x2pzZuSDoMuYQYr1CcRV9tq7R2AdF+0FrOnFOLVLoQhH8dCVeiZQ4oQF0JpASEwDyBlecszCL3NlayhC1NFEXvy23yIOJWN36knwL/V1FfkvyagREBdympO1Z1sff75caZf+NOLqJio5KA7/dCcQ0XNc6DhUUXPVAe/gvb3HN3L/R5r2eyRdebdueDKYyZZ/NKW837Craxj7KS7KtP47Vxqmy5VE9p4wODmZDSYDKY2D7yInV/NGZ7wJxOmvwCccDq6XwjjvIHm4y6O5lfMoF1zrdlc9BouvkrZj82K8JJIVov62RBhIW72kX0O9zMViDlAIvyoPE9B5nV54g7XDu28MdubKCEuQDiFNLOzkq82pMsF+Tc/YrqYOFAgIv7IptUWBelgQLj0S96kK2JDJ7bgs7+0uTItwkR5Iu0RktYNvYwkQFZ+WUIK4lnlofWKchKcyx1pVD+sq21l2AcLagJFBWEqFuDSROAL0AasMNGlxfHde2MX2vOAQulvMnfbSEu1Pba852KNhpTnTMEujhMIrDvmkRkZZGwsbcmPNdAMBY3avlA9bOj+djovCH7B21UpULqPmARvIA83n4KORXZliFk++PFxTOOgXSWDR0O40LcET+U0NBOP5z/+XCo3KwHxciGLJuWhziREeNnPPcMzeJj0qmetCIbxi2wi56Q7jWqMlEp0cmE+dFtDguBLWKkuQcOhYJTW0aKzkf6nsunJRIcpW6NIcikm9P5AF3ynzYuwkkbpkU5hVhsZxWXbFwcSQF2WyqO5mNcmPLOcK4hK/r7+4UDYZM8AK9K5BaIazdkOk+998MflATsVsbcTvTKO+Gr3vsp9+q70fCKRpOdtgduzCNQjavRZbStcbieTS1orqycslg7clk8EqczYlhImWhCQoh5dkUAmX9wVN4lW9cqAWCq/BOr+kUopur+PccTHvkSgTbjIj1sK0tPldMsId9dvp+rbaEIEbCOVgZ10zNtE4mgXKr8C+b2t25p2t4ey1M1g1Ntqxo35Z0oef3i/1y7tH15K1NflfZOPDoiM+318xm7caiHcrGBmQbQqnIK3qlv/inuwSobBfcAVpR2pddbtqWySSdQbIHlikLLTGMns9WYL6IZ8DVdygEGw2drdGeOnpd03+fDzz5cM4a+3TI3OuEhyOyzMakmuUNcAmqDrssK1+dyn8A4FdCk+ND3UgRvSRibpV3/oFMCZSSjLzbxUZmN4Z27ySKcaB0Mnastvvbgo/X2IC6CDxp7tLsKLZj3+FY0aEZshENXcE0I4SNneJLhiF4/SbHguH/rvQxWhARirwet6Jfxu+q2zb+k4/0oJDrZfJnnjmna3//+LeadL/f2vTlv/+8e/A6d/fkXDib/WGflKzsriV9zuhxJ0a5OwG2yDwjuWjhPKbdfmQ0egTylf6iF8gJ5AX4v+E4drmbku0MovasUpcUlJDw7TFAfVX8pDA3xnNDLwV/JlYa3276+2tjPgzxSc7a3r82ZNbxIxmJg4TBcR0NQPHVEuNNQV9sU5vGnTY7Q3RST+FNgYVX1SoOZ7gXpzcOzczKfB5KbTBABVDJRv0pXCjVRZUAhVvMHz+Jb0HxsM9dHPZMjLpxJF7lh4n0JzdHptBmcuJ+iBcNy6oXozH1HsyjdJNBuQTlCVyN8VG4SAkwZudJ+u6YgoOe7OD/0IG76ruwU9DblxxwGGf00f5J+uivK+bnKI+uytA8SEBleHIoPILUmybhQrbPIMeFBRQ/CAxqPAGvMowAgLEQqqEygYZSc7zaxaDKktl4JHn63UFC64EYsZL7ODLb4BUGvQWiwLMiBlTQLQIjmDl8RZngXkca0h8vyb5sOkGevGCbNy502gXZGdsbZn88pT84QejjJa+W0nNxJLE3UoAkgbRteYKjnz1S5fqgJE9XKKvCMb1owtSxn2yQt+FlIUTcY/BmNqIEuTGbCAb3+mbiGKNIh5Je0t7321Y15/pz4lvawbhQADGDJcoekhUU25lTY30j/NTvJYLs2SSbOf5XExrO5JHcs6wbNs2VVCaicr4PcZSJ1xajDZIWMiKz3fxz8l7Dc79PuzqFL/M070wUCKDklanJIwI1qpjFTniRnhVb9EVGS0GWtyVFKWMq//Z5w3AHxHMZyYmYpodv1ckM9zudP5sP9lexDfk4JpCExIJrymMaULFZEdNcOed9Se6qhPwzcQg07xJxm86HVzfSQBRwneFurOB1weP61Lce8roqsFH8nL/pB3pN6l0B0D5TLQqVnKK4tNQg8V9lPYiRb611IqK52VQfj4kM5GSVMMVkedz73afHK8RXK8713xPc7wiqj1JRTJBsvx8txXzi/R50zxehS9yq+tN9cZftYhZtGssYjmZwOZ/Dn39Gj0HWnCo9TJIa/n7kTt3EIT2N0AtK44MGCQGKoPPmC7Ize179Q31ZE5abm7BdCRSY1kR7NkkaX8gGJ7O4vr9LAkumXnHlXZfvQmTe88MoX+4LU2brj1wgJYYIRGcW6wlPjKjL/RQUxDRFDi8dEZfpp/JvJAtppdeQeFiuXlekHLI10tNby4dNpDay+tF4NbWXjuI17KzbxHirXHmQc/Mp2hkTwrtlKfFRvmXtGS/RPoXZUg8JRDqiQKJmbJkb2OC1eQluyWydGAHSNt8M+1tM2j2vu0Rmz25vT0NBCBAcHl4yyW4kAwKKOUrBJtqybxkdeJ690KiRybm17hyBJexnPkpl5suVpcoO1P7VxYehglRhBwIf5MA0Qmc2SZz/X76/vpRCsGIP4A3u0Tfj6b9l9egKP0AnoH/mD6Kj9x8V4X2Mkbpo0Pj/qs3zgQICBqljkALmFy1UczsZSZYz0ohqwVKgFpYsk3/PXIQBnNyXfshg2voKlKyxoQ0ADSzUIImoJLCTBSMxjDbGR6pTaxOoeK0XxYtiOR9lJvf/3MnTzPohMl3yLQ2LnTW6D7mRpLivIkTIBQBMbD14oWPqbTRiPDLP768deGCajVOQmX4pZhMFMrBg/Rxm2mHWoVA3Ss7eg/jGqOHLhKxbldq/Rqzh2lnk6iStdmrYyEd046lg64BnYAbtx+pm8AtltntPPfu43d/lntoVMg+WEB449d7BruUD7V2ED2fjsGYnVXO5jJfdFI57Vdmn0Okq97ert1debvzIiOHnVVOlyIiUjLuRHVGyh2pt3eeAWzianjnTjhD1R3QzivjpCQ7zLOUWZacVMYq9QzLRqHE4uIf3zF7GXFN/dUQaYXgtNG565hwv8XSjzjt+4H7mTowHiORGIAEWEwzWGLGfbrFYJBYQp5ABBTmGATDQeFura2BfJnjQ0ed/Wpk/KCWluD4haDw5nB1uKYeHN07adGRJ8k6i8h5wjPgJ/GGSZ73gRiHj6L/ogAHQPmLjAuRtvvyekvS48tezD99gL30G+8ApT7+zqFDd+LrKQd4v77gHMBnCfd7x/mZAoysQ8sH9e6ozJC9d8XlOPmKMVIpu+ub212MJNwWl3v/hNS7uDRKD3W4bMUlMrpvf93FPkIdC9y+A0DSBfGd18WMAscOwPo7KIeDTqN3hHdG4AFoZFBYe86ir16hGTrXAcCWIeeQs5b0p9jpLRpScNXHRKewn1mAAwRSREMgB2a5Suw9aXBVf181PBQTMtAHVdE8/g5AVfBXPgVwSxOURyP+InycDYmHArKgheuRDjQ4T9dUAKdmqeDGelgJq7RMBeVAyyAVpMzIKZdBBXlAShrkO6At+XmQ1GnPBDb9DCoQoDOgAYdaL4Ny9PJV9L//UISuNkAtWws9MJnuGbo8rgDvCjCao+YA8JahFjphmmO8GGoGafNm0qCiXk8lREkSUAsrgc9uyEoXgR/pt0AiUAkrGe99fSz9E+Jpp+UgBdqjZyQwdR+WgjU1OtofIEfIx4OhBuEb+xoabqX+SiIz7DFmhwCH45gGBon0CKTM9B05cvDgtF53Rzd3dvrToFvrJqO9sb4+hwD0Np8EqKQYJH7/vXCG9qGb9w3AZrVIqyVfmbZcIasy+7x8VD7f6Q3mEbPeB3zPTUggvVcBvWqdEi8JRs3+Kh+VtzI+E9ze9oY74jfCxZ2MfkZOl2/lG/uxJo4a1ITS0gCMkZvEmytmuUZeUiUwAaWlBLVh1NBMiCY0H3lFsppumqxcK+kmySrOListS9zlsEFa8pmS1aoBKY1PHwi+IUAPPbp+nKvjDZ6D2kFmTNPVO4yZ4trSxM0VKVErfgV3rsY0xb9YW+eOK/wrzL1a8OFf2X+tS/4rWeol2UxUULOa6rNIjfiD25AmIJc2PB94xRxmVda6cqJq/EJ5YeBmH78yNSmjmaUxDhj7WdqMFjXpMmSzn1+5hqjQcTQpiXvfP/4YefoM/ZjS06eHTeizp8jHeJ+fPbMLPH26TvtetCh6sbPvvef7u3dfeL5wAyE/3Z6oFK8V3xus+h8IWXv9onv6VFmyqEfUre2ZtlJEFOt0j0WkMv8NjQuVUWZV3N8zcF3rsKbhl/JyZw7DJcKT7Rl2EBc5HijiZ5pZkqIkOTIhSm6/NBrZGB24hI10j5rzerutpCVKGLfcadXDCnmr804jEo24vbrYXNiEKaQabn9HQ8HjCfcU3jIoV8ie5wLmrZVXWf+MDWqViU4ljTzVoM8CcSicxiJfpbP8w+hDCz6qwUYetH+m5vzba/nnSyCHH6EnIcoQLiWt/dxPqPuNFlyt3aXll/wvL7/sYzISSUaTPsMkohG43uS0lPybXe7MDnchq1jbkOxAAR1Z2HVrHn4xuLac/DFZ8nllvr+EeLKTH3otjPuoluR3MpFYGlqz6NXc4eS9Nlj/+8/GP257t6EpqPvjCzrVuhJqvfH7W3q91T2xOlfM/BOo8rEMew8U3yL2FeTUWlYjS6nxLCDocf/iKPoqT6WmkfUBE80Iowk0rq33K7jwqm4MmkcOyR7/A7ZV1rtlpYKaOe8lRQSJUEQPDdmOFe1HH3xSQEmMHn4DX1wPQ4hXiNeerAPhKbwDpGrtRezGTClJXI76rs3KEAnXGqLs0Rux7OCCzdRNKyWqH7kZuKwkp4A2T85rPUxiftzvp+rI5xJ8g+if8QrgXGWma5wrV7QmG4N2fJebk/nlvNCegbMvonuEtGNFw8jDq8mURF8D/rtnwVILwmQU/YVV+Ef6Cx2FrAg0IGf0cKpX8jhJtn3jnzeQfSJKM8Zx2RrYC3G6kaNKLk4ns0cHKZJ1iQ9ZriCej3LmqMm+9HsJHji0mJWpd1oifEz8nUz59HdpensR0yDX/NPLAaWeIJQFj//lnum85zsgQAzTNhBwaFl1e+23bDKt/RqH9bsNpa9Zkx6COoDxnqllMn4cXwbk+miD644LytxdXOG9/F4QhJYYrKeMxGCi8ZR1OHiYeYNv1tM1SzEa1CoZllhRTcyShv5TCNeLcSs4seiz2N//A3au/p22euzM76I53A8JS1a1FUigky30Poulj96S3pKaxULvO3XKXsL9omrq4G5qdfNXCsXHzxO3xA0l7ElMHIrbbr/5/pO6jxWKr5qp1YO7q0sSRRKM8m5/xA0ZGNQ2dczLM/Rw+Z/qyFROdjs+jZhWX9YGnuvKSGm4tOz2FE6k+s9wuYBvqxwiGXO37D4zxnfYQCPmkWAn/REGRLPYwqoaj1BtCMDUOFdFzVcf+dRBJjv8BIQ/NjguSSS0CZok5qXqcWP/XPAjhxyHR8Fz/Y2PVS8lMaRZ4v/eYdHBbIsq4R08kCZzh32NmcmZRi7rwM4Ac78a301Q9w8cCN14tddZrpGbjIZlXHlTovK5Er7D3Oca2v7z7rz7bORZYyJPAgHi5nV5cyVPNwoqtlOdlc9gDLIdwcDPrvGlbq9Uj1byNgeFV/3BUWAwySjCijn13BTITlcoMBXbwaZddza6sJ5JCAGt4KB/dmCT7UjZ2WdkDAxMb0D6TVhYygyfnw3u3+enJKSSrZa8R5+JdZUJy7+fDGDysHMlLzLnsKN5JgIvlHeXF8IDMae81mtOpHmHNklBRQblBJLqQe47PLMp0j4oi0xKkPTWJ8CbSGgnCF3FL+LBk0Z6GSVLLmMcERwpDmk/5Kz5CFOr2cRbpTGlRuIbvkGO9PVqouW1DLVqHmPIwTS7+iub3FecExBYH3J2gbzeDVYKYAVSBv6nxOx0ogfR2tKC0shzvDlyGs4uqLBSx37Pai7VEivVzWZl60pKgkloGkmGJJVNpDm7WdPaxLvsP8r7+w/g1CwZPw0cWC4BsSsFQgo+JDVyWdK/fx20JHg+TPXZcRVVi7ITd4s/RLugDv+m1WEZ5j2TP8gerbUJhye8vdKiU+V2FKGdyOWzktjSWO80p68EqUQBmfNVqzj/LVYqqVfJVV+AtlUCY43UUf8obD1SnufBzefT5Pd1j1ddO3PKM7oGI3mbL279kkcUEF1Tv0pzNrFY1kZsiYuI8W1aoNVxqUxUFtk8Wn7PTcpN1rGKuJi/lup5/vNTThRKAHufYzDt/Do8CnETGHkuMXLW+DaHUuCt3QDZSWX2xUwC/lLQ/i8C6xyypfYBJn/u5+kuoYs5zPwEKJ46LdVv5LqJY0FeLhxrT7h5KPuDNol/trb10P95Mru6TA9OxhGv1fDp/xzpUvbYwYIjf2/cuT3NJzO97QPZzpt4e0ialyeF7otS7mMEAvQ+adHn5yVrODBWnLyiR+nrpW3StAH/yvaqZh/f3qyuvBzhysGkFdEtBNyOpwt6xE8wIhoRyPK2HtqNfxD3Sd7O/K7U1abq8/ZVhb3h9JBWL18tGPE0s1b7I0aREfFfzTJ7EpuAXTaLMRZ2cBukf7Q+fuHMTQbubOCNm8NRw5euhb4qmb538Zr5M8ybNys3yhs4LWg9OsYt51xBy921378+/ZvkpIgb2L2cevfHxHLuGFqNtksaxCmccvZvQPCtsETz6TcpviH5H2rDtfDfkW7SWjUCIUH5QQhdQkd02ZN3cjA5gKsWhp8417f713vp6OqxyUHLd5Q53CUPdbyp6p/Qn7vd8g1uVcIHnWS+h4+btjJc6hm/8dQFiyhhH2cyqv7GuUTE60PcKgoSSCUWlJMT1ldkoqfKAr6oPfpFzRe2iZcTKu9FPq1xk24lR5SJEhbEfHGPVw+bz+7hgGHG/HWOzksnuS7uYUPDLd0ado9XL1vDafHSgdNdjNezUVELP0dF31nJPn8u6zKwgstuLinGGMlQ7NDz51sk3TExI+kuxC8EiwmL8fZuwHp6KmhqyHZ/z4r1zJvG43fv2nE6QjoqjcGNTBo6qohWm5ryDv61wTliIFDDBlgt+F4FxDbkLmIT54h0g2pxrG6I9WS24gmQy/aJHIaVrr6sYqguq+lT9JxFpbgA0umgQifs581GNV29uFjJsDJU42pGpUJO+aG7ArWHWsBPxDTfZak91azx2auiHbvByBYUQrpmqJCcyohOpoO4oiIggVPH4YZ9+xqgRsheLtzwHoorKIiDZFBhAYh7wLZP4CdLl2XQfvUiXdtxY7MAboRTbb7eiSk+qqDLxvf+K4dYZsLWlLakj+JgpXgkTqZmLbLUc2+e+kZe9AYKxck8Wb9Ec43YXW1zxdRWKl4Gz0pqyB0IC7y7VthaYsaUmj2WjZVnRSoG6mmQM8+VH7xtl3Q2toX71DvOLRM/FojRYmznyoAEGPqADTzmEWgGXmNjRL0NF94XjrPVR2zOPAONwHsMJDH+I33gHB1jTDtGHkc8XrAPp2pYiFhYmGELt0TsMOc05jSYHROInnYY5j0dlHjDd4ItlwLqNVXPAzN1/hM24I0+CQM7hR315xexYOcDZZ+Z6NiC6P75Dsi47fzw+W1l2xHvkdkFMsuSy0Dm4e4bmrNN89FIe/MSBd9sfAIpamqyINJyBynOKUFmRne8Rzs0vPX8/pPDYFi7SRnd6dwluSUa1FmabE2WeugJlFVTnQUpIP+Ow1kfsDA/BS/nLZP/+dmFu+4/7XbmkEppH4GjH+LAaYP/qsJVxItSaCDgxMG/6Icb/EtqDnwnc/ZyTyR+vGfizOYATavg+n0QIK2LOyAfydddLHts0CwlDal+uZKTKzC2qnWxjnVqhsA11i1Dxi+ej5HawwmuckpPL50hYNAH8dhNVkp1rnBJprkfJHSvJBembCKZLgzg+toO/5l/Y2OX4d/tXDrvS9QrWfbYVS6MzHGVMuO8ktAvuXTutv+Uys+7GxuF3jIMmo1iPhHc6z/fG6dMvkiUHNQikAoJXxUziYWrinN7yhqXvCRY1KujEu7tgSohtUyVsBru6TmEKvGp+Nw6TrFRIsnf7z127I/nPd3nB9YpkGwE97NH8UhBQveqvR8RHfgeDg6+3+917I7LKzYTH1iUjpXTJd8Ggdd/HT92CkeJTA0ZhMhraE/27j729jWYGKh0VFqehBaN5CdsYq+P5ODBd3D83K7IjL9nUTlWTGMXzEx5+/euo1/8XXaaTdshg/JetIdkQtkIPACNSQXfaoPm1M5zEtlUnNz1FcdIH6QbOaGv4vp6VIIuu6W7KoBdw3FsipqVT8lHp+KmgC0GKCCtFlJY3uBE8NZmkwVS7FGG07vNwfeuL0mMy9tJfMf7pTAUM4UrkORqYMzOpGz5++5s7Xzvyt752tl3ypaUmdmBVS+XtU6qLUrnwWSSIP1RhsD3/NcKhdOsU3r5+rxvhuCRIJ2UPOis3KICUfWGlFuotc5mZ+GRHVTrPuv+cBfFOF2bXDttpCRTe+eTBxMDfuVchQpbWwthUSHU2gYVXi3M9volvDaqeqakxbHFZeAy6EiN7rnxMCojasuvInGyZG3YJneBbiotBH0ax1z73PATySH5UflWKOKEQ65j7g4NsOkfZN9TzH116sWExPXtGb7DqqGCDeHeo/5m8hQhG7N471v1is7FJ7W+x33hYdEw7HtC6/fd3JTHpWWzj9L8tFW+j6gVZPlofavTfp/zuLxsbvF77fKTvuwRTyPic7zad+H0VbcrD4UPF2uX12j9xI+39WLf9bJqjB5vmHJGxQfr8hi7RDskCUxXEK4v+X357yX/8DES4XzonnwCyocn5Pdk9jcxt+QPMTfRWblVxlpEt8gtFDYgetqgYWdY37ANPmVT2FOax5cwONOn2EXWJ5THBWtx2GmgxlgzgWQKVYMpdIoDuNxRM2wcvmXlzKHBmuBwOVbrdMcEf6KTaqR23uPf65gG0fUG1ZIkBjg+6cYlp0VCcwT7/q5gJyb22AG7x3ZLODNuaf3R2tvs1+l0qpQUVVxGhryr68jRFY2OTo06GkORoerqfqsp5ePzyJs3SIbOd0Ct9ynJ+l5i4FOVVC4rLPF2ImBcN/JdFRu+Xuedvcw+vlJuX0Zf4LcC9JcXbf+z86cJ/Ok0fxCYaQDOcqPSabCGHuciW0pKujbhQ9ualDwvc4mj1Q72PItok9sgxTgPelKJwXMDSQ+T3AfowdRZanCsMUuLC6YdBZfzNHBJf3W883qOktHqTImjySPHJbcek94yfmVcdhMivpBkNR588N458AvE2D58ofGJb9H32vEZ/7Nztvsfg4/r7fUFLfQzBQSG4YSBQSgAkT8WKaj/+/H9p26nnJYPp5sSj6ak9jRuq1MSBjQf5Kx05MGN2VGBOveYMfjNr/gzYOzJ32OUMYzthzkGmR2KIwbChQPrYHIMMy423b+CW+5RroyoNrroq77C/2mjZGYkHxzZYjLm8hO5hc9+Y80AdL1FFZljEVrUkZWWEasjKyeWLySkpfUH8dmVAY5CfoCaxQ8KVBudmk+ZLWqykax2Mjuph0re+72v0hCEI1/+9PgLMw33m24t1dcqadt/BQOvJsyZacWraL5Ab7O9+97++bft1gEA2MZMIUoAbP+XjUSv1WkzIvCdC4ivs4UBkQAAAGJBSnCHeSZEQDEQy2QUWHhTHXkzFRkwZvQj4jz5U4KoROCvsXAj/KdwSidw1S5EmhwffyOxWG4DggT2OYOsCbx1FcEZD+UggajZgEC4lLdAD9Zo4d90k6dIlWUYvEDyrJp0JDJwzQkk3vjBccRRpjxHDCjcKxXZZBvrWMSGWFgkI5SqRyGGS10gBKj6v2knfFOS7R3CcJDDIZPOI2EzbDYpy/MmQkWQTvixgdPuInWB9WgMsnHrb/bDD/Jkmix26ArRVlyPPCujuQzZ0PSZ8NkDP3ENqVZXw2+ZaFERB5sggqqq5cgupvKRQYhVeU8JnoMmS3qp1s+6CgVIl4ySs3800Rf4a+boqmJa9Fs86f8oNszUqeoE6T7oNkAS4AEMts0QAH8iIaGHJb4ntasgQ8X6rw3sHt7BjbaxHPbysKlfwPZOztm8n1pnqr2tZGKIbGrDuZXm29uuIKXFIIjhoJJWSapgPEuczdahByogAIgyDBwyaffnGGuY4FG3hzkXheGIDbDjg2GAA3xEqKlCRDFVdDAGkMByxGJqxMFE4ANiXpgEWKAKIABCCQAAb9CJgyFABicPhgEVjCGCqdcRxdSpgzGAC2YQi6kvDiaCHPCvSxLwgBTKpUxAhqaq5yo4zj4Gs1I39pzb32jHSOJjeV//IRo4V7v19mzrB2SIbgmd2r2Zr7xwqt5nMjrEyNUgfA1n685suNpsPFXG2nFalDIBGZqqnvmJg+Psc63UjX1Ab38DDz5GErKDl/sfomH14NVuvZVSH4Ss0GnZVp3ave0UX9m6cHLE95VREJnB1UAXu4azdaehD1cbqzevKqwbJaabd7DHdbEdAknhUZXJ1RRKdf2u57s0tWrTrsPnDwRD4Ug0Fk8kU+lMNpcvFEvlSrVWbzRb7U631x8MR+PJdDZfLFfrzXb3jHyyjqfz5Xq7P56v9+f7C/j3IgUp5AZyGtn1Z66D65/iliIcsXJkaFnmVQ70/mzxkBHazl6OHh5PEAsp8akpJuTTI03IJPNpjqAJT65Gw231bs6HCexqeJS5Uo8avBrVV+TTYRG+Cbl9MVJCjOMuTLkau2GzT8k6QZIzithlmLN5E88i1YiXOtYrI+1PfYg4HRVSCCImyg7LOpLrV4ly75KzMAWbFXPuOE4J2Xx80dqM03o5QJTzpO1dappgYbL9skGEQRURyQAv5HsRqJ7WzP1lq8hLd/lkH+bDuHScTcjZpRvVOEFCMMzSssFAYiaY7+ishkQmfGgfbvr5A1MjC2rB6WmIf8YSbzgNo3a0eNFBD/TAjzkjrvdU3LD0NbLrLu59nC4SVKnFeeZYK84SZ8yPkNsVecZIuB/ZPnvQndmMpBgoOvvEqD2J3J721J/1LIIaPRlovlTXoRkjykrrCtLy8nDF932isAuBm13EnZbWHLJlsX3LPNrldN/aqA+7sW7VZqWKhrSrmaS59/rT4WuBEYifKsw/vA8Ozx3xXUPwkLHuWRLNBis6xOFgYdAycru6iHzhFhQMcS4SSQ/rs16C43wQKOxAzvGY7ZCk35CXTAfKFGcNugAAAA==') format('woff2'),
  url('iconfont.woff?t=1565078640369') format('woff'),
  url('iconfont.ttf?t=1565078640369') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  url('iconfont.svg?t=1565078640369#wukong') format('svg'); /* iOS 4.1- */
}
.wukong {
  font-family: "wukong" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.wukong-reminder:before {
  content: "\e653";
}
.wukong-lock:before {
  content: "\e625";
}
.wukong-check:before {
  content: "\e698";
}
.wukong-examine-category-nine:before {
  content: "\e6c2";
}
.wukong-examine-category-eight:before {
  content: "\e6db";
}
.wukong-examine-category-overtime:before {
  content: "\e6e4";
}
.wukong-examine-category-seven:before {
  content: "\e6e5";
}
.wukong-examine-category-ordinary:before {
  content: "\e6f3";
}
.wukong-examine-category-leave:before {
  content: "\e702";
}
.wukong-examine-category-six:before {
  content: "\e70a";
}
.wukong-examine-category-five:before {
  content: "\e70f";
}
.wukong-examine-category-four:before {
  content: "\e71f";
}
.wukong-examine-category-business:before {
  content: "\e739";
}
.wukong-examine-category-borrowing:before {
  content: "\e73b";
}
.wukong-examine-category-billing:before {
  content: "\e744";
}
.wukong-examine-category-two:before {
  content: "\e75f";
}
.wukong-examine-category-three:before {
  content: "\e767";
}
.wukong-examine-category-one:before {
  content: "\e627";
}
.wukong-lightning:before {
  content: "\e65e";
}
.wukong-label:before {
  content: "\e65f";
}
.wukong-sub-task:before {
  content: "\e660";
}
.wukong-file:before {
  content: "\e662";
}
.wukong-user:before {
  content: "\e663";
}
.wukong-relevance:before {
  content: "\e664";
}
.wukong-black-label:before {
  content: "\e665";
}
.wukong-activity-task:before {
  content: "\e667";
}
.wukong-comment-task:before {
  content: "\e668";
}
.wukong-time-task:before {
  content: "\e66b";
}
.wukong-person-task:before {
  content: "\e66c";
}
.wukong-addition-task:before {
  content: "\e66e";
}
.wukong-delete-task:before {
  content: "\e66f";
}
.wukong-edit-task:before {
  content: "\e670";
}
.wukong-address:before {
  content: "\e671";
}
.wukong-book:before {
  content: "\e672";
}
.wukong-business:before {
  content: "\e673";
}
.wukong-certificate:before {
  content: "\e674";
}
.wukong-contract:before {
  content: "\e675";
}
.wukong-customer:before {
  content: "\e676";
}
.wukong-contacts:before {
  content: "\e677";
}
.wukong-department:before {
  content: "\e678";
}
.wukong-systemconfig:before {
  content: "\e679";
}
.wukong-taskSetstatistics:before {
  content: "\e67a";
}
.wukong-task:before {
  content: "\e67b";
}
.wukong-taskCompletestatistics:before {
  content: "\e67c";
}
.wukong-examine:before {
  content: "\e67d";
}
.wukong-funnelstatistics:before {
  content: "\e67e";
}
.wukong-workbench:before {
  content: "\e67f";
}
.wukong-project:before {
  content: "\e680";
}
.wukong-message:before {
  content: "\e681";
}
.wukong-notice:before {
  content: "\e682";
}
.wukong-money:before {
  content: "\e683";
}
.wukong-employeestatistics:before {
  content: "\e684";
}
.wukong-moneystatistics:before {
  content: "\e685";
}
.wukong-product:before {
  content: "\e686";
}
.wukong-example:before {
  content: "\e687";
}
.wukong-tag:before {
  content: "\e688";
}
.wukong-log:before {
  content: "\e689";
}
.wukong-over:before {
  content: "\e68a";
}
.wukong-leads:before {
  content: "\e68b";
}
.wukong-pay:before {
  content: "\e68c";
}
.wukong-schedule:before {
  content: "\e68d";
}
.wukong-statistics:before {
  content: "\e68e";
}
.wukong-seas:before {
  content: "\e68f";
}
.wukong-subproject:before {
  content: "\e690";
}
.wukong-productstatistics:before {
  content: "\e691";
}
.wukong-set:before {
  content: "\e692";
}
.wukong-recycle:before {
  content: "\e693";
}
.wukong-personcenter:before {
  content: "\e694";
}
.wukong-goout:before {
  content: "\e695";
}
.wukong-versions:before {
  content: "\e696";
}
.wukong-business-customer:before {
  content: "\e699";
}
.wukong-dashboard:before {
  content: "\e697";
}
.wukong-BI_Leaderboard:before {
  content: "\e6fc";
}
.wukong-BI_Office:before {
  content: "\e6fd";
}
.wukong-BI_Employee_performance:before {
  content: "\e6fe";
}
.wukong-help_tips:before {
  content: "\e700";
}
.wukong-log-delete:before {
  content: "\e6ff";
}
.wukong-log-reply:before {
  content: "\e701";
}
.wukong-marketing:before {
  content: "\e704";
}
.wukong-icon_reset_account_login:before {
  content: "\e703";
}
.wukong-oa_analysis:before {
  content: "\e705";
}
src/assets/fonts/iconfont.eot
Binary files differ
src/assets/fonts/iconfont.js
New file
@@ -0,0 +1 @@
!function(t){var e,c,o,n,i,s,l,a='<svg><symbol id="icon-showpassword" viewBox="0 0 1024 1024"><path d="M1024 512c0 96-211.2 307.2-512 307.2-294.4 0-512-204.8-512-307.2s217.6-307.2 512-307.2c300.8 0 512 204.8 512 307.2l0 0zM512 262.4c-134.4 0-243.2 108.8-243.2 249.6s108.8 249.6 249.6 249.6c134.4 0 249.6-115.2 249.6-249.6-6.4-140.8-121.6-249.6-256-249.6l0 0zM512 352c-89.6 0-160 70.4-160 160s70.4 160 160 160c89.6 0 160-70.4 160-160s-70.4-160-160-160l0 0z"  ></path></symbol><symbol id="icon-user" viewBox="0 0 1024 1024"><path d="M867.328 790.592c-61.12-41.664-191.68-77.824-211.136-88.96s-38.848-19.456-38.848-55.488c0-36.096 19.776-55.232 47.232-80.64 51.52-47.488 41.6-101.376 74.944-126.4 27.328-20.416 40.96-36.16 45.248-66.752 0.704-4.544 1.152-9.728 1.344-15.488 0.064-2.368 0.576-3.968 0.576-6.656 0-47.232-38.848-47.232-38.848-47.232s0 1.344-13.888-76.352c-13.376-75.136-89.152-155.264-194.368-160.64L539.584 65.472c-2.112 0-3.968 0.192-6.016 0.256C531.84 65.664 530.112 65.472 528.32 65.472L528.32 65.92c-0.512 0-0.96 0.128-1.472 0.192C526.336 66.048 525.888 65.92 525.376 65.92L525.376 65.472c-1.792 0-3.52 0.192-5.248 0.256C518.144 65.664 516.224 65.472 514.112 65.472l0 0.512c-105.28 5.376-180.992 85.504-194.368 160.64C305.856 304.384 305.856 302.976 305.856 302.976s-38.848 0-38.848 47.232c0 2.624 0.512 4.224 0.576 6.656 0.256 5.76 0.704 10.944 1.344 15.488 4.288 30.592 17.92 46.336 45.248 66.752C347.52 464.128 337.6 518.016 389.12 565.504c27.52 25.344 47.232 44.48 47.232 80.64 0 36.032-19.456 44.352-38.848 55.488s-150.016 47.232-211.136 88.96S128 854.464 128 890.496C128 951.616 205.824 960 205.824 960l246.464 0 68.544 0 12.032 0 68.544 0 246.464 0c0 0 77.824-8.384 77.824-69.504C925.696 854.464 928.448 832.256 867.328 790.592z"  ></path></symbol><symbol id="icon-users" viewBox="0 0 1152 1024"><path d="M767.952003 770.575839v-52.7967c70.523592-39.741516 127.992-138.743329 127.992-237.809137C895.944003 320.939941 895.944003 191.988001 703.956003 191.988001S511.968002 320.939941 511.968002 479.970002c0 99.065808 57.468408 198.067621 127.992 237.809137v52.7967c-217.074433 17.726892-383.976001 124.408224-383.976001 253.360165h895.944003c0-128.951941-166.901569-235.633273-383.976001-253.360165z" fill="" ></path><path d="M327.147553 795.278295c55.292544-36.15774 124.088244-63.612024 199.795513-80.378976a362.665333 362.665333 0 0 1-40.509468-59.004312 366.441097 366.441097 0 0 1-46.461096-175.861009c0-86.010624 0-167.285545 30.590088-233.777389 29.694144-64.507968 83.130804-104.505468 159.222048-119.480533C612.889694 50.300856 567.83651 0.063996 447.972002 0.063996c-191.988001 0-191.988001 128.951941-191.988001 287.982001 0 99.065808 57.468408 198.067621 127.992 237.809137v52.7967c-217.074433 17.726892-383.976001 124.408224-383.976001 253.360165h278.958565c14.527092-12.927192 30.590088-25.150428 48.188988-36.669708z" fill="" ></path></symbol><symbol id="icon-morentouxiang" viewBox="0 0 1024 1024"><path d="M512 64C264.8 64 64 264.8 64 512s200.8 448 448 448 448-200.8 448-448S759.2 64 512 64zM384.8 376c4-64 56-115.2 120-119.2 74.4-4 135.2 55.2 135.2 128 0 70.4-57.6 128-128 128-73.6 0-132-62.4-127.2-136.8zM768 746.4c0 12-9.6 21.6-21.6 21.6H278.4c-12 0-21.6-9.6-21.6-21.6v-64c0-84.8 170.4-128 255.2-128 84.8 0 255.2 42.4 255.2 128l0.8 64z"  ></path></symbol><symbol id="icon-baobiao" viewBox="0 0 1024 1024"><path d="M960 672V160c0-17.6-14.4-32-32-32H544V64h-64v64H96c-17.6 0-32 14.4-32 32v512c0 17.6 14.4 32 32 32h384v50.4l-152.8 89.6 32 56 144-84h19.2l144 84 32-56L544 754.4V704h384c17.6 0 32-14.4 32-32zM790.4 256l41.6 48.8-316.8 270.4L352 437.6 233.6 536.8 192.8 488l160-133.6 163.2 137.6L790.4 256z"  ></path></symbol><symbol id="icon-password" viewBox="0 0 1024 1024"><path d="M807.049 391.258c0.946-9.62 1.45-19.37 1.45-29.239 0-163.7-132.706-296.406-296.406-296.406S215.687 198.318 215.687 362.02c0 9.802 0.498 19.486 1.432 29.043-43.925 18.95-74.675 62.638-74.675 113.516v330.363c0 68.25 55.328 123.58 123.58 123.58h491.672c68.25 0 123.578-55.328 123.578-123.58V504.578c0-50.704-30.54-94.267-74.225-113.32zM510.917 165.905c109.134 0 197.604 88.47 197.604 197.603 0 5.895-0.275 11.726-0.782 17.49H314.094a200.097 200.097 0 0 1-0.782-17.49c0.002-109.132 88.472-197.603 197.605-197.603z"  ></path></symbol><symbol id="icon-lock-fill" viewBox="0 0 1024 1024"><path d="M810.666667 426.666667h42.666666a42.666667 42.666667 0 0 1 42.666667 42.666666v426.666667a42.666667 42.666667 0 0 1-42.666667 42.666667H170.666667a42.666667 42.666667 0 0 1-42.666667-42.666667V469.333333a42.666667 42.666667 0 0 1 42.666667-42.666666h42.666666V384a298.666667 298.666667 0 1 1 597.333334 0v42.666667z m-85.333334 0V384A213.333333 213.333333 0 0 0 298.666667 384v42.666667h426.666666z m-256 170.666666v170.666667h85.333334v-170.666667h-85.333334z"  ></path></symbol></svg>',d=(e=document.getElementsByTagName("script"))[e.length-1].getAttribute("data-injectcss");if(d&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(t){console&&console.log(t)}}function h(){s||(s=!0,n())}c=function(){var t,e,c,o,n,i=document.createElement("div");i.innerHTML=a,a=null,(t=i.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",e=t,(c=document.body).firstChild?(o=e,(n=c.firstChild).parentNode.insertBefore(o,n)):c.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(c,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),c()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(n=c,i=t.document,s=!1,(l=function(){try{i.documentElement.doScroll("left")}catch(t){return void setTimeout(l,50)}h()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,h())})}(window);
src/assets/fonts/iconfont.json
New file
@@ -0,0 +1,58 @@
{
  "id": "",
  "name": "",
  "font_family": "iconfont",
  "css_prefix_text": "icon-",
  "description": "",
  "glyphs": [
    {
      "icon_id": "212782",
      "name": "show-password ",
      "font_class": "showpassword",
      "unicode": "ea3f",
      "unicode_decimal": 59967
    },
    {
      "icon_id": "587162",
      "name": "user",
      "font_class": "user",
      "unicode": "e830",
      "unicode_decimal": 59440
    },
    {
      "icon_id": "1199149",
      "name": "users",
      "font_class": "users",
      "unicode": "a",
      "unicode_decimal": 10
    },
    {
      "icon_id": "1727461",
      "name": "225默认头像",
      "font_class": "morentouxiang",
      "unicode": "e8c9",
      "unicode_decimal": 59593
    },
    {
      "icon_id": "1727589",
      "name": "406报表",
      "font_class": "baobiao",
      "unicode": "e902",
      "unicode_decimal": 59650
    },
    {
      "icon_id": "7712708",
      "name": "password",
      "font_class": "password",
      "unicode": "e734",
      "unicode_decimal": 59188
    },
    {
      "icon_id": "16035104",
      "name": "lock-fill",
      "font_class": "lock-fill",
      "unicode": "e6af",
      "unicode_decimal": 59055
    }
  ]
}
src/assets/fonts/iconfont.svg
New file
@@ -0,0 +1,47 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
  <font-face
    font-family="iconfont"
    font-weight="500"
    font-stretch="normal"
    units-per-em="1024"
    ascent="896"
    descent="-128"
  />
    <missing-glyph />
    <glyph glyph-name="showpassword" unicode="&#59967;" d="M1024 300c0-96-211.2-307.2-512-307.2-294.4 0-512 204.8-512 307.2s217.6 307.2 512 307.2c300.8 0 512-204.8 512-307.2l0 0zM512 549.6c-134.4 0-243.2-108.8-243.2-249.6s108.8-249.6 249.6-249.6c134.4 0 249.6 115.2 249.6 249.6-6.4 140.8-121.6 249.6-256 249.6l0 0zM512 460c-89.6 0-160-70.4-160-160s70.4-160 160-160c89.6 0 160 70.4 160 160s-70.4 160-160 160l0 0z"  horiz-adv-x="1024" />
    <glyph glyph-name="user" unicode="&#59440;" d="M867.328 105.408c-61.12 41.664-191.68 77.824-211.136 88.96s-38.848 19.456-38.848 55.488c0 36.096 19.776 55.232 47.232 80.64 51.52 47.488 41.6 101.376 74.944 126.4 27.328 20.416 40.96 36.16 45.248 66.752 0.704 4.544 1.152 9.728 1.344 15.488 0.064 2.368 0.576 3.968 0.576 6.656 0 47.232-38.848 47.232-38.848 47.232s0-1.344-13.888 76.352c-13.376 75.136-89.152 155.264-194.368 160.64L539.584 830.528c-2.112 0-3.968-0.192-6.016-0.256C531.84 830.336 530.112 830.528 528.32 830.528L528.32 830.08c-0.512 0-0.96-0.128-1.472-0.192C526.336 829.952 525.888 830.08 525.376 830.08L525.376 830.528c-1.792 0-3.52-0.192-5.248-0.256C518.144 830.336 516.224 830.528 514.112 830.528l0-0.512c-105.28-5.376-180.992-85.504-194.368-160.64C305.856 591.616 305.856 593.024 305.856 593.024s-38.848 0-38.848-47.232c0-2.624 0.512-4.224 0.576-6.656 0.256-5.76 0.704-10.944 1.344-15.488 4.288-30.592 17.92-46.336 45.248-66.752C347.52 431.872 337.6 377.984 389.12 330.496c27.52-25.344 47.232-44.48 47.232-80.64 0-36.032-19.456-44.352-38.848-55.488s-150.016-47.232-211.136-88.96S128 41.536 128 5.504C128-55.616 205.824-64 205.824-64l246.464 0 68.544 0 12.032 0 68.544 0 246.464 0c0 0 77.824 8.384 77.824 69.504C925.696 41.536 928.448 63.744 867.328 105.408z"  horiz-adv-x="1024" />
    <glyph glyph-name="users" unicode="&#10;" d="M767.952003 125.424161v52.7967c70.523592 39.741516 127.992 138.743329 127.992 237.809137C895.944003 575.060059 895.944003 704.011999 703.956003 704.011999S511.968002 575.060059 511.968002 416.029998c0-99.065808 57.468408-198.067621 127.992-237.809137v-52.7967c-217.074433-17.726892-383.976001-124.408224-383.976001-253.360165h895.944003c0 128.951941-166.901569 235.633273-383.976001 253.360165zM327.147553 100.721705c55.292544 36.15774 124.088244 63.612024 199.795513 80.378976a362.665333 362.665333 0 0 0-40.509468 59.004312 366.441097 366.441097 0 0 0-46.461096 175.861009c0 86.010624 0 167.285545 30.590088 233.777389 29.694144 64.507968 83.130804 104.505468 159.222048 119.480533C612.889694 845.699144 567.83651 895.936004 447.972002 895.936004c-191.988001 0-191.988001-128.951941-191.988001-287.982001 0-99.065808 57.468408-198.067621 127.992-237.809137v-52.7967c-217.074433-17.726892-383.976001-124.408224-383.976001-253.360165h278.958565c14.527092 12.927192 30.590088 25.150428 48.188988 36.669708z"  horiz-adv-x="1152" />
    <glyph glyph-name="morentouxiang" unicode="&#59593;" d="M512 832C264.8 832 64 631.2 64 384s200.8-448 448-448 448 200.8 448 448S759.2 832 512 832zM384.8 520c4 64 56 115.2 120 119.2 74.4 4 135.2-55.2 135.2-128 0-70.4-57.6-128-128-128-73.6 0-132 62.4-127.2 136.8zM768 149.6c0-12-9.6-21.6-21.6-21.6H278.4c-12 0-21.6 9.6-21.6 21.6v64c0 84.8 170.4 128 255.2 128 84.8 0 255.2-42.4 255.2-128l0.8-64z"  horiz-adv-x="1024" />
    <glyph glyph-name="baobiao" unicode="&#59650;" d="M960 224V736c0 17.6-14.4 32-32 32H544V832h-64v-64H96c-17.6 0-32-14.4-32-32v-512c0-17.6 14.4-32 32-32h384v-50.4l-152.8-89.6 32-56 144 84h19.2l144-84 32 56L544 141.6V192h384c17.6 0 32 14.4 32 32zM790.4 640l41.6-48.8-316.8-270.4L352 458.4 233.6 359.2 192.8 408l160 133.6 163.2-137.6L790.4 640z"  horiz-adv-x="1024" />
    <glyph glyph-name="password" unicode="&#59188;" d="M807.049 504.742c0.946 9.62 1.45 19.37 1.45 29.239 0 163.7-132.706 296.406-296.406 296.406S215.687 697.682 215.687 533.98c0-9.802 0.498-19.486 1.432-29.043-43.925-18.95-74.675-62.638-74.675-113.516v-330.363c0-68.25 55.328-123.58 123.58-123.58h491.672c68.25 0 123.578 55.328 123.578 123.58V391.422c0 50.704-30.54 94.267-74.225 113.32zM510.917 730.095c109.134 0 197.604-88.47 197.604-197.603 0-5.895-0.275-11.726-0.782-17.49H314.094a200.097 200.097 0 0 0-0.782 17.49c0.002 109.132 88.472 197.603 197.605 197.603z"  horiz-adv-x="1024" />
    <glyph glyph-name="lock-fill" unicode="&#59055;" d="M810.666667 469.333333h42.666666a42.666667 42.666667 0 0 0 42.666667-42.666666v-426.666667a42.666667 42.666667 0 0 0-42.666667-42.666667H170.666667a42.666667 42.666667 0 0 0-42.666667 42.666667V426.666667a42.666667 42.666667 0 0 0 42.666667 42.666666h42.666666V512a298.666667 298.666667 0 1 0 597.333334 0v-42.666667z m-85.333334 0V512A213.333333 213.333333 0 0 1 298.666667 512v-42.666667h426.666666z m-256-170.666666v-170.666667h85.333334v170.666667h-85.333334z"  horiz-adv-x="1024" />
  </font>
</defs></svg>
src/assets/fonts/iconfont.ttf
Binary files differ
src/assets/fonts/iconfont.woff
Binary files differ
src/assets/fonts/iconfont.woff2
Binary files differ
src/assets/img/accessory.png
src/assets/img/add_examine.png
src/assets/img/add_journal.png
src/assets/img/add_notice.png
src/assets/img/add_schedule.png
src/assets/img/add_task.png
src/assets/img/archive_project.png
src/assets/img/business_detail.png
src/assets/img/business_dot.png
src/assets/img/button_add_black.png
src/assets/img/button_add_white.png
src/assets/img/c_business.png
src/assets/img/c_contact.png
src/assets/img/c_contract.png
src/assets/img/c_curomer.png
src/assets/img/c_filtrate.png
src/assets/img/c_log.png
src/assets/img/c_receivables.png
src/assets/img/cancel_associated.png
src/assets/img/check_cancel.png
src/assets/img/check_create.png
src/assets/img/check_fail.png
src/assets/img/check_revoke.png
src/assets/img/check_suc.png
src/assets/img/check_wait.png
src/assets/img/close.png
src/assets/img/close2x.png
src/assets/img/clue_detail.png
src/assets/img/collapse_gray.png
src/assets/img/collapse_right.png
src/assets/img/collapse_white.png
src/assets/img/comment.png
src/assets/img/contacts_detail.png
src/assets/img/contract_detail.png
src/assets/img/crm_multiuser.png
src/assets/img/customer_detail.png
src/assets/img/deadline.png
src/assets/img/delete_task.png
src/assets/img/empty.png
src/assets/img/examine_head.png
src/assets/img/field_business_manager.png
src/assets/img/field_contacts_manager.png
src/assets/img/field_contract_manager.png
src/assets/img/field_customer_manager.png
src/assets/img/field_leads_manager.png
src/assets/img/field_other_manager.png
src/assets/img/field_product_manager.png
src/assets/img/field_receivables_manager.png
src/assets/img/file_excle.png
src/assets/img/file_img.png
src/assets/img/file_pdf.png
src/assets/img/file_ppt.png
src/assets/img/file_txt.png
src/assets/img/file_unknown.png
src/assets/img/file_video.png
src/assets/img/file_word.png
src/assets/img/file_zip.png
src/assets/img/fold.png
src/assets/img/follow_log.png
src/assets/img/follow_record.png
src/assets/img/goOut.png
src/assets/img/head.png
src/assets/img/jd_business.png
src/assets/img/jianbao.png
src/assets/img/journal_comment.png
src/assets/img/loading.gif
src/assets/img/login/login.png
src/assets/img/login/login_bg.png
src/assets/img/login/logo.png
src/assets/img/logo.jpg
src/assets/img/logo.png
src/assets/img/logo_bg.png
src/assets/img/loudou.png
src/assets/img/mobile.png
src/assets/img/money_detail.png
src/assets/img/more_dot.png
src/assets/img/no_data.png
src/assets/img/no_task.png
src/assets/img/nopermission.png
src/assets/img/person_dot.png
src/assets/img/post.png
src/assets/img/product_detail.png
src/assets/img/project/archive_project.png
src/assets/img/project/head.png
src/assets/img/project/my_task.png
src/assets/img/project/project_add.png
src/assets/img/project/project_filtrate.png
src/assets/img/project/relevance_file.png
src/assets/img/project/schedule.png
src/assets/img/project/send_contacts.png
src/assets/img/project/smiling_face.png
src/assets/img/project/t_set.png
src/assets/img/project/task_accessory.png
src/assets/img/project/task_add.png
src/assets/img/project/task_circle.png
src/assets/img/project/task_close.png
src/assets/img/project/task_download.png
src/assets/img/project/task_ellipsis.png
src/assets/img/project/task_end_time.png
src/assets/img/project/task_priority.png
src/assets/img/project/task_subtask.png
src/assets/img/project/task_tag.png
src/assets/img/qushi.png
src/assets/img/relevance_business.png
src/assets/img/relevance_file.png
src/assets/img/scene_add.png
src/assets/img/scene_set.png
src/assets/img/sea_detail.png
src/assets/img/section_reset_name.png
src/assets/img/selection_add_user.png
src/assets/img/selection_alloc.png
src/assets/img/selection_convert_customer.png
src/assets/img/selection_deal_status.png
src/assets/img/selection_delete.png
src/assets/img/selection_delete_user.png
src/assets/img/selection_disable.png
src/assets/img/selection_edit.png
src/assets/img/selection_export.png
src/assets/img/selection_get.png
src/assets/img/selection_lock.png
src/assets/img/selection_putseas.png
src/assets/img/selection_reset.png
src/assets/img/selection_start.png
src/assets/img/selection_transfer.png
src/assets/img/selection_unlock.png
src/assets/img/send_business.png
src/assets/img/send_contacts.png
src/assets/img/send_file.png
src/assets/img/send_img.png
src/assets/img/setting.png
src/assets/img/smiling_face.png
src/assets/img/sprite/vue-emoji.png
src/assets/img/step_success.png
src/assets/img/step_wait.png
src/assets/img/structure.png
src/assets/img/system/app/call_disable.png
src/assets/img/system/app/call_enable.png
src/assets/img/system/app/crm_disable.png
src/assets/img/system/app/crm_enable.png
src/assets/img/system/app/hrm.png
src/assets/img/system/app/inventory.png
src/assets/img/system/app/oa_disable.png
src/assets/img/system/app/oa_enable.png
src/assets/img/system/app/phone.png
src/assets/img/system/app/project_disable.png
src/assets/img/system/app/project_enable.png
src/assets/img/system/customer_pool_module.png
src/assets/img/system/examine_module.png
src/assets/img/system/leads_module.png
src/assets/img/system/leads_pool_module.png
src/assets/img/system/log_module.png
src/assets/img/system/notice_module.png
src/assets/img/system/schedule_module.png
src/assets/img/system/task_module.png
src/assets/img/t_set.png
src/assets/img/tablefilter.png
src/assets/img/task_accessory.png
src/assets/img/task_add.png
src/assets/img/task_close.png
src/assets/img/task_edit_def.png
src/assets/img/task_ellipsis.png
src/assets/img/unfold.png
src/assets/img/update_files.png
src/assets/img/work_examine.png
src/assets/img/work_log.png
src/assets/img/work_notice.png
src/assets/img/work_schedule.png
src/assets/img/work_statistics.png
src/assets/img/work_task.png
src/assets/img/zhibiao.png
src/components/CreateCom/CrmRelative.vue
New file
@@ -0,0 +1,377 @@
<template>
  <div class="cr-contianer">
      <div class="title" v-show="!isProduct">{{ getTitle() }}
        <img
          class="t-close"
          src="@/assets/img/close.png"
          @click="closeView" >
      </div>
    <div style="height: 100%;position: relative;">
      <div
        v-if="crmType === 'product'"
        class="cr-body-side">
        <el-tree
          ref="tree"
          :data="treeData"
          :expand-on-click-node="false"
          node-key="TypeName"
          :props="defaultProps"
          highlight-current
          @node-click="changeDepClick">
          <flexbox
            slot-scope="{ node, data }"
            class="node-data">
            <el-tooltip :content="data.TypeName" placement="top">
              <div class="node-label">{{ data.TypeName }}</div>
            </el-tooltip>
          </flexbox>
        </el-tree>
        <!--<div
          v-for="(item, index) in leftSides"
          :key="index"
          :class="leftType===item.type? 'side-item-select' : 'side-item-default'"
          class="side-item"
          @click="sideClick(item)">{{ item.name }}</div>-->
      </div>
      <div :style="{ 'padding-left': crmType === 'product' ? '220px' : '0'}">
        <crm-relative-table
          v-for="(item, index) in leftSides"
          v-show="item.type === leftType"
          :isProduct="isProduct"
          :key="index"
          :ref="'crm'+item.type"
          :show="show && item.type === leftType"
          :radio="radio"
          :crm-type="item.type"
          :selected-data="currentSelectedData"
          :action="action"
          @closeView="closeView"
          @changeCheckout="checkCrmTypeInfos"/>
          <!--<div class="handle-bar">
            <el-button @click="closeView">取消</el-button>
            <el-button
              type="primary"
              @click="confirmClick">确定</el-button>
          </div>-->
      </div>
    </div>
  </div>
</template>
<script type="text/javascript">
import { GetAutoProductTypeList } from '@/api/customermanagement/product'
import CrmRelativeTable from './CrmRelativeTable'
import { objDeepCopy } from '@/utils'
export default {
  name: 'CrmRelatieve', // 相关
  components: {
    CrmRelativeTable
  },
  props: {
    /** 多选框 只能选一个 */
    radio: {
      type: Boolean,
      default: true
    },
    isProduct: {
      type: Boolean,
      default: true
    },
    /** 没有值就是全部类型 有值就是当个类型 */
    crmType: {
      type: String,
      default: ''
    },
    /** 需要展示哪些类型 默认关键字数组 */
    showTypes: {
      type: Array,
      default: () => {
        return [
          'customer',
          'contacts',
          'leads',
          'business',
          'contract',
          'product'
        ]
      }
    },
    /** 已选信息 */
    selectedData: {
      type: Object,
      default: () => {
        return {}
      }
    },
    /** true 的时候 发请求 */
    show: {
      type: Boolean,
      default: true
    },
    /**
     * default 默认  condition 固定条件筛选 moduleType 下的
     * relative: 相关 添加
     */
    action: {
      type: Object,
      default: () => {
        return {
          type: 'default',
          data: {}
        }
      }
    }
  },
  data () {
    return {
      leftType: 'customer',
      leftSides: [],
      treeData: [],
      /** 各类型选择的值 */
      currentSelectedData: {},
      defaultProps: {
        children: 'ProductResultList',
        label: 'TypeName'
      }
    }
  },
  computed: {},
  watch: {
    selectedData: function (data) {
      this.currentSelectedData = objDeepCopy(data)
    },
    // 刷新标记
    show (val) {
      if (val) {
        this.currentSelectedData = objDeepCopy(this.selectedData)
      }
    }
  },
  mounted () {
    var leftItems = {
      customer: {
        name: '客户',
        type: 'customer'
      },
      contacts: {
        name: '联系人',
        type: 'contacts'
      },
      leads: {
        name: '线索',
        type: 'leads'
      },
      business: {
        name: '商机',
        type: 'business'
      },
      contract: {
        name: '合同',
        type: 'contract'
      },
      product: {
        name: '产品',
        type: 'product'
      }
    }
    if (this.crmType) {
      this.leftType = this.crmType
      this.leftSides.push(leftItems[this.crmType])
    } else {
      for (let index = 0; index < this.showTypes.length; index++) {
        const element = this.showTypes[index]
        this.leftSides.push(leftItems[element])
      }
    }
    this.currentSelectedData = objDeepCopy(this.selectedData)
    this.getTreeList()
  },
  methods: {
    /**
     * 刷新列表
     */
    refreshList () {
      this.$refs['crm' + this.crmType][0].refreshList()
    },
    getTreeList () {
      GetAutoProductTypeList().then(res => {
        console.log(res)
        if (res.data.ErrorCode === 200) {
          this.treeData = res.data.Result || []
        }
      })
    },
    changeDepClick (data) {
      console.log(data)
      this.$refs['crm' + this.crmType][0].getFieldList(data.ParameterLink)
    },
    sideClick (item) {
      this.leftType = item.type
    },
    clearAll () {
      if (this.crmType) {
        this.$refs['crm' + this.crmType][0].clearAll()
      }
    },
    // 当用户手动勾选全选 Checkbox 时触发的事件
    selectAll () {},
    // 关闭操作
    closeView () {
      this.$emit('close')
    },
    checkCrmTypeInfos (data) {
      this.currentSelectedData[data.type] = data.data
      if (this.crmType) {
        // 以单类型传值
        this.$emit('changeVal', this.currentSelectedData[this.crmType])
      } else {
        this.$emit('changeVal', this.currentSelectedData)
      }
      this.$emit('close')
    },
    // 根据类型获取标题展示名称
    getTitle () {
      if (this.crmType === 'leads') {
        return '关联线索'
      } else if (this.crmType === 'customer') {
        return '关联客户'
      } else if (this.crmType === 'contacts') {
        return '关联联系人'
      } else if (this.crmType === 'business') {
        return '关联商机'
      } else if (this.crmType === 'product') {
        return '关联产品'
      } else if (this.crmType === 'contract') {
        return '关联合同'
      } else {
        return '关联业务'
      }
    }
  }
}
</script>
<style lang="scss" scoped>
.cr-contianer {
  // height: 600px;
  position: relative;
  // padding: 50px 0 50px 0;
}
.title {
  padding: 0 30px;
  font-size: 16px;
  line-height: 50px;
  font-weight: 550;
  color: #333333;
  height: 50px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3;
  // border-bottom: 1px solid #e6e6e6;
  .t-close{
    position: absolute;
    right: 30px;
    top: 12px;
    cursor: pointer;
  }
}
.handle-bar {
  height: 50px;
  // position: absolute;
  // bottom: 0;
  // left: 0;
  // right: 40%;
  z-index: 2;
  display: flex;
  align-items: center;
  align-content: center;
  justify-content: center;
  width: 100%;
  button {
    float: right;
    margin-top: 10px;
    margin-right: 10px;
  }
}
.cr-body-side {
  flex-shrink: 0;
  z-index: 3;
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 220px;
  font-size: 12px;
  background-color: #F8F8F8;
  border-right: 1px solid #e6e6e6;
  height: 650px;
  overflow: auto;
  /deep/ .el-tree{
    background-color: #F8F8F8;
  }
  .side-item {
    height: 35px;
    line-height: 35px;
    padding: 0 20px;
    cursor: pointer;
  }
}
.side-item-default {
  color: #333;
}
.side-item-select {
  color: #409eff;
  background-color: #ecf5ff;
}
.el-dialog /deep/ .el-dialog__headerbtn{
  padding: 10px;
}
// tree
.el-tree /deep/ .el-tree-node__content {
  height: 30px;
   &:hover{
    color: #4D88FF;
    background-color: #EBF1FF;
  }
  .node-data {
    .node-label {
      margin-right: 8px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      width: 150px;
    }
    .node-label-set {
      display: none;
    }
  }
  .node-data:hover .node-label-set {
    display: block;
  }
}
.el-tree /deep/ .el-tree-node.is-current > .el-tree-node__content {
  background-color: #4D88FF;
  color: #fff;
  // border-right: 2px solid #4D88FF;
  .node-label-set {
    display: block;
  }
}
.system-view-nav /deep/ .el-tree-node > .el-tree-node__children {
  overflow: visible;
}
.system-view-nav /deep/ .el-tree > .el-tree-node {
  min-width: 100%;
  display: inline-block !important;
}
</style>
src/components/CreateCom/CrmRelativeCell.vue
New file
@@ -0,0 +1,179 @@
<template>
  <el-popover
    v-model="showPopover"
    :disabled="disabled"
    placement="bottom"
    width="700"
    popper-class="no-padding-popover"
    trigger="click">
    <crm-relative
      v-if="!disabled&&showSelectView"
      ref="crmrelative"
      :crm-type="item.data.formType"
      :action="relationAction"
      @close="showPopover=false"
      @changeCheckout="checkInfos"/>
    <flexbox
      slot="reference"
      :class="[disabled ? 'is_disabled' : 'is_valid']"
      wrap="wrap"
      class="user-container"
      @click.native="contentClick">
      <div
        v-for="(aitem, aindex) in dataValue"
        :key="aindex"
        class="user-item"
        @click.stop="deleteinfo(aindex)">{{ getShowName(aitem) }}
        <i class="delete-icon el-icon-close"/>
      </div>
      <div
        v-if="dataValue.length === 0"
        class="add-item">+添加</div>
    </flexbox>
  </el-popover>
</template>
<script type="text/javascript">
import CrmRelative from './CrmRelative'
import arrayMixin from './arrayMixin'
export default {
  name: 'CrmRelativeCell', // 相关模块CRMCell
  components: {
    CrmRelative
  },
  mixins: [arrayMixin],
  props: {
    relation: {
      // 相关ID
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data () {
    return {
      showPopover: false, // 展示popover
      showSelectView: false, // 内容
      radio: true, // 是否单选
      relationAction: { type: 'default' }
    }
  },
  computed: {
    // 如果有相关ID  展示相关效果 例如客户下的商机和合同
    isRelationShow () {
      return this.item && this.item.data && this.item.data.relation_id
    }
  },
  watch: {
    relation: function (val) {
      if (val.moduleType) {
        this.relationAction = { type: 'condition', data: val }
      } else {
        this.relationAction = { type: 'default' }
      }
    }
  },
  mounted () {
    if (this.relation && this.relation.moduleType) {
      this.relationAction = { type: 'condition', data: this.relation }
    } else {
      this.relationAction = { type: 'default' }
    }
  },
  methods: {
    /** 选中 */
    checkInfos (data) {
      this.dataValue = data.data ? data.data : []
      this.$emit('value-change', {
        index: this.index,
        value: data.data
      })
    },
    /** 删除 */
    deleteinfo (index) {
      if (this.disabled) return
      if (this.radio && this.$refs.crmrelative) {
        // 如果单选告知删除
        this.$refs.crmrelative.clearAll()
      }
      if (this.dataValue.length === 1) {
        this.dataValue = []
      } else {
        this.dataValue.splice(index, 1)
      }
      this.$emit('value-change', {
        index: this.index,
        value: this.dataValue
      })
    },
    contentClick () {
      this.showSelectView = true
    },
    getShowName (data) {
      if (this.item.data.formType === 'receivables') {
        return data.number
      } else if (this.item.data.formType === 'customer') {
        return data.customerName
      } else if (this.item.data.formType === 'business') {
        return data.businessName
      } else if (this.item.data.formType === 'contract') {
        return data.contractNum || data.num
      }
      return data.name
    }
  }
}
</script>
<style lang="less" scoped>
.user-container {
  min-height: 34px;
  position: relative;
  border-radius: 3px;
  font-size: 12px;
  border: 1px solid #ddd;
  color: #333333;
  padding: 5px;
  line-height: 15px;
  .user-item {
    padding: 5px;
    background-color: #e2ebf9;
    border-radius: 3px;
    margin: 3px;
    cursor: pointer;
  }
  .add-item {
    padding: 5px;
    color: #4D88FF;
    cursor: pointer;
  }
  .delete-icon {
    color: #999;
    cursor: pointer;
  }
}
.user-container.is_disabled {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  cursor: not-allowed;
  .user-item {
    background-color: #f0f4f8ea;
    color: #c0c4cc;
    cursor: not-allowed;
  }
  .delete-icon {
    color: #c0c4cc;
    cursor: not-allowed;
  }
  .add-item {
    color: #c0c4cc;
    cursor: not-allowed;
  }
}
.user-container.is_valid:hover {
  border-color: #c0c4cc;
}
</style>
src/components/CreateCom/CrmRelativeTable.vue
New file
@@ -0,0 +1,590 @@
<template>
  <div class="cr-body-content">
    <flexbox class="content-header">
      <!--<Xh-inputSelect v-if="isProduct" :isProduct="isProduct" @getName="getName" :crm-type="crmType" />-->
      <el-input
        placeholder='请输入你要搜索的内容'
        v-model="searchContent"
        @keyup.enter.native="searchInput"
        class="search-container">
      </el-input>
      <el-button class="searchBtn" type="primary" @click="searchInput">搜索</el-button>
      <!--<el-button
        class="create-button"
        type="primary"
        @click="isCreate=true">新建</el-button> -->
    </flexbox>
    <div class='content-table'>
      <el-table
        v-loading="loading"
        id="crm-table"
        ref="relativeTable"
        :data="list"
        :height="550"
        :cell-style="cellStyle"
        class="n-table--border"
        border
        highlight-current-row
        style="width: 100%"
        @selection-change="handleSelectionChange"
        @row-click="handleRowClick">
        <el-table-column
          show-overflow-tooltip
          type="selection"/>
        <el-table-column
          v-for="(item, index) in fieldList"
          :key="index"
          :prop="item.field"
          :label="item.name"
          :formatter="fieldFormatter"
          show-overflow-tooltip>
          <template
            slot="header"
            slot-scope="scope">
            <div class="table-head-name">
              {{ scope.column.label }}
            </div>
          </template>
        </el-table-column>
        <el-table-column/>
      </el-table>
    </div>
    <div class="p-contianer" v-show='total>0'>
      <el-pagination
        :current-page="currentPage"
        :page-sizes="pageSizes"
        :page-size.sync="pageSize"
        :total="total"
        class="p-bar"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"/>
    </div>
    <div class="handle-bar">
      <el-button @click="closeView">取消</el-button>
      <el-button
        type="primary"
        @click="confirmClick">确定</el-button>
    </div>
    <c-r-m-create-view
      v-if="isCreate"
      :crm-type="crmType"
      @save-success="getList"
      @hiden-view="isCreate=false"/>
  </div>
</template>
<script type="text/javascript">
// import crmTypeModel from '@/views/clients/model/crmTypeModel'
import { GetSalesChanceList } from '@/api/customermanagement/business'
import { XhInputSelect } from '@/components/CreateCom'
import { GetAutoProductListAsync } from '@/api/customermanagement/product'
export default {
  name: 'CrmRelativeTable', // 相关模块CRMCell
  components: {
    XhInputSelect,
    CRMCreateView: () =>
      import('@/views/clients/components/CRMCreateView')
  },
  props: {
    show: {
      type: Boolean,
      default: false
    },
    /** 多选框 只能选一个 */
    radio: {
      type: Boolean,
      default: true
    },
    isProduct: {
      type: Boolean,
      default: true
    },
    /** 没有值就是全部类型 有值就是当个类型 */
    crmType: {
      type: String,
      default: ''
    },
    /** 已选信息 */
    selectedData: {
      type: Object,
      default: () => {
        return {}
      }
    },
    /**
     * default 默认  condition 固定条件筛选
     * relative: 相关 添加
     */
    action: {
      type: Object,
      default: () => {
        return {
          type: 'default',
          data: {}
        }
      }
    }
  },
  data () {
    return {
      loading: false, // 加载进度
      searchContent: '', // 输入内容
      isCreate: false, // 控制新建
      scenesList: [], // 场景信息
      sceneInfo: null,
      list: [], // 表数据
      fieldList: [], // 表头数据
      currentPage: 1, // 当前页数
      total: 0,
      pageSize: 10,
      pageSizes: [10, 30, 60, 100],
      otherItems: [],
      selectedItem: [] // 勾选的数据 点击确定 传递给父组件
    }
  },
  computed: {
    // 展示相关效果 去除场景
    isRelationShow () {
      return this.action.type === 'condition'
    }
  },
  watch: {
    crmType: function (newValue, oldValue) {
      if (newValue !== oldValue) {
        this.fieldList = []
        this.getFieldList()
      }
    },
    action: function (val) {
      console.log(this.action, val)
      if (this.action !== val) {
        this.sceneInfo = null
        this.list = [] // 表数据
        this.fieldList = [] // 表头数据
        this.currentPage = 1 // 当前页数
        this.pageSize = 10
        if (!this.isRelationShow) {
          this.getSceneList()
        } else {
          this.getFieldList()
        }
      }
    },
    show: {
      handler (val) {
        if (val && this.fieldList.length === 0) {
          // 相关列表展示时不需要场景 直接获取展示字段
          if (!this.isRelationShow) {
            this.getSceneList()
          } else {
            this.getFieldList()
          }
        }
      },
      deep: true,
      immediate: true
    },
    // 选择
    selectedData: function () {
      // this.checkItemsWithSelectedData()
    }
  },
  mounted () {
  },
  methods: {
    /**
     * 刷新列表
     */
    refreshList () {
      this.currentPage = 1
      this.pageSize = 10
      this.getList()
    },
    getName (data) {
      console.log('this is data of input-select: ', data)
      // this.formInline.user = data.name
      // this.inputSelectData = data
    },
    cellStyle ({ row, column, rowIndex, columnIndex }) {
      return { textAlign: 'left' }
    },
    getSceneList () {
      // this.loading = true
      // crmSceneIndex({
      //   type: crmTypeModel[this.crmType]
      // })
      //   .then(res => {
      //     var defaultScene = res.data.filter(function (item, index) {
      //       return item.isDefault === 1
      //     })
      //     this.scenesList = res.data
      //     if (defaultScene && defaultScene.length > 0) {
      //       this.sceneInfo = defaultScene[0]
      //     }
      //     if (this.scenesList.length === 0) {
      //       this.scenesList.push({ sceneId: '', name: '全部' })
      //       this.sceneInfo = this.scenesList[0]
      //     }
      //     this.getFieldList()
      //   })
      //   .catch(() => {
      //     this.loading = false
      //   })
    },
    /** 获取字段 */
    getFieldList (data) {
      if (this.fieldList && this.fieldList.length === 0) {
        this.fieldList = this.getDefaultField()
      }
      // 获取好字段开始请求数据
      this.getList(data)
    },
    /** 获取列表请求 */
    getDefaultField () {
      console.log(this.crmType)
      if (this.crmType === 'leads') {
        return [
          { name: '线索名称', field: 'name', formType: 'leads' },
          { name: '下次联系时间', field: 'nextTime', formType: 'datetime' },
          { name: '最后跟进时间', field: 'updateTime', formType: 'datetime' },
          { name: '创建时间 ', field: 'createTime', formType: 'datetime' }
        ]
      } else if (this.crmType === 'customer') {
        return [
          { name: '客户名称', field: 'CustomerName', formType: 'customer' },
          { name: '下次联系时间', field: 'nextTime', formType: 'datetime' },
          { name: '最后跟进时间', field: 'updateTime', formType: 'datetime' },
          { name: '创建时间 ', field: 'createTime', formType: 'datetime' }
        ]
      } else if (this.crmType === 'contacts') {
        return [
          { name: '姓名', field: 'name', formType: 'contacts' },
          { name: '手机', field: 'mobile', formType: 'mobile' },
          { name: '电话', field: 'telephone', formType: 'text' },
          { name: '是否关键决策人', field: '是否关键决策人', formType: 'text' },
          { name: '职务', field: 'post', formType: 'text' }
        ]
      } else if (this.crmType === 'business') {
        return [
          { field: 'ChanceName', name: '商机名称', formType: 'text' },
          { field: 'CustomerName', name: '客户名称', formType: 'text' },
          { field: 'ContacterName', name: '联系人', formType: 'text' },
          { field: 'SalesChanceStage', name: '销售阶段', formType: 'text' },
          { field: 'ExpectedDate', name: '预期成交日期', formType: 'text' },
          { field: 'ExpectedAmount', name: '商机金额/元', formType: 'text' },
          { field: 'OwerName', name: '销售负责人', formType: 'text' }
        ]
      } else if (this.crmType === 'contract') {
        return [
          { name: '合同编号', field: 'num', formType: 'text' },
          {
            name: '合同名称',
            field: this.isRelationShow ? 'contractName' : 'name',
            formType: 'text'
          },
          { name: '客户名称', field: 'customerName', formType: 'text' },
          { name: '合同金额', field: 'money', formType: 'text' },
          { name: '开始日期', field: 'startTime', formType: 'text' },
          { name: '结束日期', field: 'endTime', formType: 'text' }
        ]
      } else if (this.crmType === 'product') {
        return [
          { name: '产品线', field: 'ProductLine', formType: 'text' },
          { name: '产品类型', field: 'ProductType', formType: 'text' },
          { name: 'SKU值', field: 'SKU', formType: 'text' },
          { name: '产品名称', field: 'ProductName', formType: 'text' },
          { name: '产品描述', field: 'ProductDesc', formType: 'text' },
          { name: '产品更新时间', field: 'LastUpdateTime', formType: 'text' },
          { name: '产品是否在线', field: 'Status', formType: 'text' },
          { name: '市场参考价(¥)', field: 'ETP', formType: 'text' },
          { name: '建议经销商转售价(¥)', field: 'RTP', formType: 'text' }
        ]
      }
    },
    /** 获取列表数据 */
    getList (data) {
      console.log(data)
      this.loading = true
      let crmIndexRequest
      crmIndexRequest = this.getIndexRequest()
      // const params = { search: this.searchContent }
      let params
      // 注入场景
      if (this.sceneInfo) {
        params.sceneId = this.sceneInfo.sceneId
      }
      // 注入关联ID
      if (this.isRelationShow) {
        // this.action.data.moduleType 下的 this.crmType 的列表
        if (this.action.data.moduleType) {
          crmIndexRequest = {
            customer: {
              business: GetSalesChanceList
              // contacts: crmCustomerQueryContacts,
              // contract: crmCustomerQueryContract
            },
            business: {
              business: GetSalesChanceList
              // contacts: crmCustomerQueryContacts,
              // contract: crmCustomerQueryContract
            }
          }[this.action.data.moduleType][this.crmType]
          params = {
            'PageIndex': 1,
            'PageSize': 20,
            'SelectOwnedType': 0,
            'Name': this.searchContent,
            'SalesChanceType': '',
            'CreateStartTime': '',
            'CreateEndTime': ''
          }
          // params[this.action.data.moduleType + 'Id'] = this.action.data[
          //   this.action.data.moduleType + 'Id'
          // ]
          if (this.action.data.params) {
            for (const field in this.action.data.params) {
              params[field] = this.action.data.params[field]
            }
          }
        }
      } else {
        params = {
          PageIndex: this.currentPage,
          PageSize: this.pageSize,
          TypeName: data || '',
          Name: this.searchContent
        }
      }
      crmIndexRequest(params)
        .then(res => {
          this.list = res.data.Result.List || []
          console.log(this.list)
          /**
           *  如果已选择的有数据
           */
          // if (this.selectedData[this.crmType]) {
          //   this.checkItemsWithSelectedData()
          // } else {
          //   this.list = res.data.Result.List
          // }
          // this.total = Math.ceil(res.data.totalRow / 10)
          this.total = res.data.Result.Count
          this.loading = false
          this.$forceUpdate()
        })
        .catch(() => {
          this.loading = false
        })
    },
    // 标记选择数据
    checkItemsWithSelectedData () {
      const selectedArray = this.selectedData[this.crmType].map(item => {
        item.has = false
        return item
      })
      const selectedRows = []
      this.otherItems = []
      this.list.forEach((item, index) => {
        selectedArray.forEach((selectedItem, selectedIndex) => {
          if (item[this.crmType + 'Id'] === selectedItem[this.crmType + 'Id']) {
            selectedItem.has = true
            selectedRows.push(item)
          }
        })
      })
      selectedArray.forEach((selectedItem, selectedIndex) => {
        if (!selectedItem.has) {
          this.otherItems.push(selectedItem)
        }
      })
      this.$nextTick(() => {
        this.$refs.relativeTable.clearSelection()
        selectedRows.forEach(row => {
          this.$refs.relativeTable.toggleRowSelection(row, true)
        })
      })
    },
    /** 获取列表请求 */
    getIndexRequest () {
      // if (this.crmType === 'leads') {
      //   return crmLeadsIndex
      // } else if (this.crmType === 'customer') {
      //   return crmCustomerIndex
      // } else if (this.crmType === 'contacts') {
      //   return crmContactsIndex
      // } else if (this.crmType === 'business') {
      //   return crmBusinessIndex
      // } else if (this.crmType === 'contract') {
      //   return crmContractIndex
      // } else
      if (this.crmType === 'product') {
        return GetAutoProductListAsync
      }
    },
    // 场景选择
    handleTypeDrop (command) {
      this.sceneInfo = command
      this.getList()
    },
    /** 列表操作 */
    // 当某一行被点击时会触发该事件
    handleRowClick (row, column, event) {},
    fieldFormatter (row, column) {
      if (column.property === 'Status') {
        switch (row[column.property]) {
          case true:
            row[column.property] = '是'
            break
          case false:
            row[column.property] = '否'
            break
        }
      }
      return row[column.property] || '--'
    },
    // 当选择项发生变化时会触发该事件
    handleSelectionChange (val) {
      if (this.radio) {
        // this.$refs.relativeTable.clearSelection();
        val.forEach((row, index) => {
          if (index === val.length - 1) return
          this.$refs.relativeTable.toggleRowSelection(row, false)
        })
        if (val.length === 0) {
          this.selectedItem = []
        } else {
          this.selectedItem = val.length === 1 ? val : [val[val.length - 1]]
        }
      } else {
        this.selectedItem = this.otherItems.concat(val)
      }
    },
    closeView () {
      this.$emit('closeView')
    },
    // 确定选择
    confirmClick () {
      console.log(this.crmType)
      this.$emit('changeCheckout', {
        data: this.selectedItem,
        type: this.crmType
      })
    },
    clearAll () {
      this.$refs.relativeTable.clearSelection()
    },
    // 当用户手动勾选全选 Checkbox 时触发的事件
    selectAll () {},
    // 进行搜索操作
    searchInput () {
      this.currentPage = 1
      this.pageSize = 10
      this.getFieldList()
      // this.getList()
    },
    handleSizeChange (newSize) {
      this.pageSize = newSize
      this.getList()
    },
    handleCurrentChange (newPage) {
      this.currentPage = newPage
      this.getList()
    }
  }
}
</script>
<style lang="scss" scoped>
@import '../../views/clients/styles/table.scss';
.cr-body-content {
  position: relative;
  background-color: white;
}
.content-header {
  position: relative;
  padding: 10px 30px;
  .search-container {
    width: 224px;
  }
  .search-container /deep/ .el-input__inner{
    height: 32px;
  }
  .search-container /deep/ .el-input-group__append{
    background-color: #4D88FF;
    border-radius: 0px 3px 3px 0px;
    color: #fff;
    border: 1px solid #4D88FF;
  }
  .create-button {
    position: absolute;
    right: 30px;
    top: 15px;
    width: 97px;
    height: 32px;
    background: #FF8800;
    border-radius: 3px;
    border: 1px solid #FF8800;
  }
}
.content-table{
  padding: 0 30px;
  margin-bottom: 20px;
}
//表尾 上一页按钮
.table-footer {
  padding: 0px 30px;
}
.el-table /deep/ thead th {
  font-weight: 400;
  font-size: 12px;
}
.el-table /deep/ tbody tr td {
  font-size: 12px;
}
.el-table /deep/ thead th,
thead td {
  padding: 0;
  border-right: 1px solid #F7FAFF;
}
// .el-table /deep/ thead .el-checkbox {
//   display: none;
// }
body .el-table th.gutter {
  display: table-cell !important;
}
.el-table /deep/ .el-table__body-wrapper {
  height: calc(100% - 48px) !important;
}
.searchBtn{
  width: 58px;
  height: 32px;
  margin-left: 24px;
}
.handle-bar {
  height: 50px;
  z-index: 2;
  display: flex;
  align-items: center;
  align-content: center;
  justify-content: center;
  width: 100%;
  button {
    float: right;
    margin-top: 10px;
    margin-right: 10px;
  }
}
</style>
src/components/CreateCom/XhBusinessStatus.vue
New file
@@ -0,0 +1,67 @@
<template>
  <el-select
    v-model="dataValue"
    :disabled="disabled"
    style="width: 100%;"
    placeholder="请选择"
    @change="valueChange">
    <el-option
      v-for="item in options"
      :key="item.typeId"
      :label="item.name"
      :value="item.typeId"/>
  </el-select>
</template>
<script type="text/javascript">
import stringMixin from './stringMixin'
// import { crmBusinessStatusList } from '@/api/clients/business'
export default {
  name: 'XhBusinessStatus', // 商机状态
  components: {},
  mixins: [stringMixin],
  props: {},
  data () {
    return {
      options: []
    }
  },
  computed: {},
  mounted () {
    this.getBusinessStatusList()
  },
  methods: {
    /** 获取商机状态组 */
    getBusinessStatusList () {
      // crmBusinessStatusList({})
      //   .then(res => {
      //     this.options = res.data
      //     if (this.dataValue) {
      //       for (const item of this.options) {
      //         if (item.typeId === this.dataValue) {
      //           this.$emit('value-change', {
      //             index: this.index,
      //             value: this.dataValue,
      //             data: this.options,
      //             type: 'init' // 初始化下不更改阶段值
      //           })
      //         }
      //       }
      //     }
      //   })
      //   .catch(() => {})
    },
    // 输入的值
    valueChange (val) {
      /** 商机组顺便回调筛选数据 */
      this.$emit('value-change', {
        index: this.index,
        value: val,
        data: this.options
      })
    }
  }
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhCustomerAddress.vue
New file
@@ -0,0 +1,397 @@
<template>
  <flexbox align="stretch">
    <el-row>
      <el-col
        :span="span">
        <!--@focus="getProvinces" @focus="getCities"@focus="getAreas"-->
        <el-select
          ref="proSel"
          class='selecInput'
          size="small"
          v-model="provinceCode"
          @change="changeProvince"
          placeholder="请选择省份"
          :disabled='disabled'
          filterable>
          <el-option
            v-for="item in provinceList"
            :key="item.ProvinceID"
            :label="item.ProvinceName"
            :value="item.ProvinceID">
          </el-option>
        </el-select>
      </el-col>
      <el-col
        :span="span"
        v-if="!hideCity">
        <el-select
          ref="citySel"
          class='selecInput'
          size="small"
          v-model="cityCode"
          @change="changeCity"
          placeholder="请选择市"
          :disabled='disabled'
          filterable>
          <el-option
            v-for="item in cityList"
            :key="item.CityID"
            :label="item.CityName"
            :value="item.CityID">
          </el-option>
        </el-select>
      </el-col>
      <el-col
        :span="span"
        v-if="!hideCity && !hideArea">
        <el-select
          class='selecInput'
          size="small"
          v-model="areaCode"
          @change="changeArea"
          placeholder="请选择区/县"
          :disabled='disabled'
          filterable>
          <el-option
            v-for="item in areaList"
            :key="item.AreaId"
            :label="item.AreaName"
            :value="item.AreaId">
          </el-option>
        </el-select>
      </el-col>
    </el-row>
  </flexbox>
</template>
<script type="text/javascript">
import {GetProvincesList, GetCityList, GetAreaList} from '@/api/common'
export default {
  name: 'XhCustomerAddress', // 新建 客户位置
  components: {
  },
  props: {
    disabled: { // 禁
      type: Boolean,
      default: false
    },
    hideCity: { // 隐藏市
      type: Boolean,
      default: false
    },
    hideArea: { // 隐藏区/县
      type: Boolean,
      default: false
    },
    province: {
      type: String,
      default: ''
    },
    city: {
      type: String,
      default: ''
    },
    area: {
      type: String,
      default: ''
    },
    addressCode: null // 地址编码
  },
  data () {
    return {
      provinceList: [], // 省份列表
      cityList: [], // 城市列表
      areaList: [], // 区/县列表
      provinceCode: '', // 省份编码
      cityCode: '', // 城市编码
      areaCode: '', // 区/县编码
      cityFlag: false, // 避免重复请求的标志
      provinceFlag: false,
      areaFlag: false
    }
  },
  computed: {
    span () {
      if (this.hideCity) {
        return 24
      }
      if (this.hideArea) {
        return 12
      }
      return 8
    }
  },
  watch: {
    addressCode: {
      deep: true,
      immediate: true,
      handler (newVal) {
        if (newVal) {
          this.addressCodeToList(newVal)
        } else {
          this.$nextTick(() => {
            this.reset()
          })
        }
      }
    },
    province: {
      deep: true,
      immediate: true,
      handler (newVal) {
        if (newVal) {
          console.log(newVal)
          this.editCodeToList(newVal, 'province')
        } else {
          this.$nextTick(() => {
            this.reset()
          })
        }
      }
    },
    city: {
      deep: true,
      immediate: true,
      handler (newVal) {
        if (newVal) {
          this.editCityToList(newVal, 'city')
        } else {
          this.$nextTick(() => {
            this.reset()
          })
        }
      }
    },
    area: {
      deep: true,
      immediate: true,
      handler (newVal) {
        if (newVal) {
          this.editAreaToList(newVal, 'area')
        } else {
          this.$nextTick(() => {
            this.reset()
          })
        }
      }
    }
  },
  created () {
    this.getProList()
  },
  mounted () {
  },
  methods: {
    /**
     * 获取数据
     */
    getProList () {
      GetProvincesList().then(res => {
        this.provinceList = res.data.Result || []
        console.log(this.province)
        if (!this.province) {
          this.provinceCode = res.data.Result && res.data.Result.length > 0 ? res.data.Result[0].ProvinceID : ''
          let selected = this.idFilter(this.provinceCode, this.provinceList, 'province')
          this.$emit('province', selected.ProvinceName)
        }
        this.getCityList(this.provinceCode)
      })
    },
    getCityList (val) {
      let params = {
        provinceId: val
      }
      GetCityList(params).then(res => {
        this.cityList = res.data.Result || []
        // this.cityCode = res.data.Result && res.data.Result.length > 0 ? res.data.Result[0].CityID : ''
        if (this.city) {
          console.log('11111111', this.city)
          let selectedCity = this.nameFilter(this.city, this.cityList, 'city')
          this.cityCode = selectedCity ? selectedCity.CityID : ''
        } else {
          this.cityCode = res.data.Result && res.data.Result.length > 0 ? res.data.Result[0].CityID : ''
          let selected = this.idFilter(this.cityCode, this.cityList, 'city')
          this.$emit('city', selected.CityName)
        }
      })
    },
    getAreaList (val) {
      let params = {
        cityId: val
      }
      GetAreaList(params).then(res => {
        this.areaList = res.data.Result || []
        this.areaCode = res.data.Result && res.data.Result.length > 0 ? res.data.Result[0].AreaID : ''
      })
    },
    idFilter (e, list, name) {
      if (name === 'province') {
        return list.find((item) => {
          return item.ProvinceID === e
        })
      }
      if (name === 'city') {
        return list.find((item) => {
          return item.CityID === e
        })
      }
      if (name === 'area') {
        return list.find((item) => {
          return item.AreaID === e
        })
      }
    },
    nameFilter (e, list, name) {
      if (name === 'province') {
        return list.find((item) => {
          return item.ProvinceName === e
        })
      }
      if (name === 'city') {
        return list.find((item) => {
          return item.CityName === e
        })
      }
      if (name === 'area') {
        return list.find((item) => {
          return item.AreaName === e
        })
      }
    },
    // 根据国家编码获取省份列表
    getProvinces () {
      if (this.provinceFlag) {
        return
      }
      this.getProList()
      this.provinceFlag = true
    },
    // 省份修改,拉取对应城市列表
    changeProvince (val) {
      this.getCityList(this.provinceCode)
      this.cityFlag = true
      this.cityCode = ''
      this.areaCode = ''
      let selected = this.idFilter(val, this.provinceList, 'province')
      this.$emit('province', selected.ProvinceName)
    },
    // 根据省份编码获取城市列表
    getCities () {
      if (this.cityFlag) {
        return
      }
      if (this.provinceCode) {
        this.getCityList(this.provinceCode)
        this.cityFlag = true
      }
    },
    // 城市修改,拉取对应区域列表
    changeCity (val) {
      this.getAreaList(this.cityCode)
      this.areaFlag = true
      this.areaCode = ''
      let selected = this.idFilter(val, this.cityList, 'city')
      this.$emit('city', selected.CityName)
      // let selected = this.idFilter(this.cityCode, this.cityList, 'city')
      // this.$emit('city', selected ? selected.CityName : '')
    },
    // 根据城市编码获取区域列表
    getAreas () {
      if (this.areaFlag) {
        return
      }
      if (this.cityCode) {
        this.getAreaList(this.cityCode)
      }
    },
    // 区域修改
    changeArea (val) {
      let selected = this.idFilter(val, this.areaList, 'area')
      this.$emit('area', selected.AreaName)
    },
    // 重置省市区/县编码
    reset () {
      this.provinceCode = ''
      this.cityCode = ''
      this.areaCode = ''
    },
    editCodeToList (code, name) {
      if (!code) return false
      if (name === 'province') {
        let selectedPro = this.nameFilter(code, this.provinceList, name)
        this.provinceCode = selectedPro ? selectedPro.ProvinceID : ''
        this.getCityList(this.provinceCode)
      }
    },
    editCityToList (code, name) {
      if (!code) return false
      if (name === 'city') {
        if (this.cityList && this.cityList.length > 0) {
          let selectedCity = this.nameFilter(code, this.cityList, name)
          this.cityCode = selectedCity ? selectedCity.CityID : ''
          if (!this.hideArea) {
            this.getAreaList(this.cityCode)
          }
        }
      }
    },
    editAreaToList (code, name) {
      if (!code) return false
      if (name === 'area') {
        if (this.areaList && this.areaList.length > 0) {
          let selectedArea = this.nameFilter(code, this.areaList, name)
          this.areaCode = selectedArea ? selectedArea.AreaID : ''
        }
      }
    },
    // 地址编码转换成省市区列表
    addressCodeToList (addressCode) {
      if (!addressCode) return false
      this.$http({
        method: 'get',
        url: this.API.addressCode + '/' + addressCode
      })
        .then(res => {
          let data = res.data.body
          if (!data) return
          if (data.provinceCode) {
            this.provinceCode = data.provinceCode
            this.fetchData(this.cityList, this.API.city, this.provinceCode)
          } else if (data.cityCode) {
            this.cityCode = data.cityCode
            this.fetchData(this.areaList, this.API.area, this.cityCode)
          } else if (data.areaCode) {
            this.areaCode = data.areaCode
          }
        })
        .finally(res => {
        })
    }
  }
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.map {
  height: 150px;
  width: 100%;
  overflow: hidden;
  margin-top: 5px;
}
.area-title {
  font-size: 12px;
  color: #aaa;
  padding-left: 10px;
}
.distpicker-address-wrapper /deep/ select {
  height: 34px;
  font-size: 12px;
  border-radius: 0.1rem;
  padding: .5rem .2rem;
}
.selecInput{
  min-width: 120px;
  margin-left: 10px;
}
</style>
src/components/CreateCom/XhDate.vue
New file
@@ -0,0 +1,29 @@
<template>
  <el-date-picker
    v-model="dataValue"
    :disabled="disabled"
    style="width: 100%;"
    type="date"
    value-format="yyyy-MM-dd"
    placeholder="选择日期"
    @change="valueChange"/>
</template>
<script type="text/javascript">
import stringMixin from './stringMixin'
export default {
  name: 'XhInput', // 新建 date
  components: {},
  mixins: [stringMixin],
  props: {},
  data () {
    return {}
  },
  computed: {},
  watch: {},
  mounted () {},
  methods: {}
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhDateTime.vue
New file
@@ -0,0 +1,43 @@
<template>
  <el-date-picker
    v-model="dataValue"
    :disabled="disabled"
    style="width: 100%;"
    type="datetime"
    value-format="yyyy-MM-dd HH:mm:ss"
    placeholder="选择日期"
    @change="valueChange"/>
</template>
<script type="text/javascript">
import stringMixin from './stringMixin'
import { getDateFromTimestamp } from '@/utils'
import moment from 'moment'
export default {
  name: 'XhInput', // 新建 datetime
  components: {},
  mixins: [stringMixin],
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data () {
    return {}
  },
  computed: {},
  watch: {},
  mounted () {
    if (this.value && this.value.toString().length === 10) {
      // 编辑的时候 值是时间戳
      this.dataValue = moment(getDateFromTimestamp(this.value)).format(
        'YYYY-MM-DD HH:mm:ss'
      )
    }
  },
  methods: {}
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhFiles.vue
New file
@@ -0,0 +1,203 @@
<template>
  <div
    :class="[disabled ? 'is_disabled' : 'is_valid']"
    class="xh-files-cont">
    <flexbox
      :class="[disabled ? 'is_disabled' : 'is_valid']"
      class="f-header"
      @click.native="selectImage">
      <img
        v-if="!disabled"
        class="f-logo"
        src="@/assets/img/relevance_file.png" >
      <div class="f-name">附件</div>
      <input
        :id="'xhImageInput' + index||'0'"
        type="file"
        class="bar-iput"
        accept="*.*"
        multiple
        @change="xhUploadFile" >
    </flexbox>
    <div class="f-body">
      <flexbox
        v-for="(item, index) in dataValue"
        :key="index"
        class="f-item">
        <img
          class="f-img"
          src="@/assets/img/relevance_file.png" >
        <div class="f-name">{{ item.name.length > 25 ? (item.name.substring(0, 25) + '...'): item.name+'('+item.size+')' }}</div>
        <div
          class="close-button"
          @click="deleteFile(item, index)">×</div>
      </flexbox>
    </div>
  </div>
</template>
<script type="text/javascript">
import arrayMixin from './arrayMixin'
// import { crmFileSave, crmFileDelete } from '@/api/common'
// import { fileSize } from '@/utils/index'
export default {
  name: 'XhFiles', // 新建 file  以数组的形式上传
  components: {},
  mixins: [arrayMixin],
  props: {},
  data () {
    return {
      batchId: '' // 批次ID
    }
  },
  computed: {},
  watch: {},
  mounted () {},
  methods: {
    selectImage () {
      if (!this.disabled) {
        document.getElementById('xhImageInput' + this.index || '0').click()
      }
    },
    /** 图片选择出发 */
    xhUploadFile (event) {
      var files = event.target.files
      var firstFile = files[0]
      this.sendFileRequest(firstFile, () => {
        for (let index = 1; index < files.length; index++) {
          const file = files[index]
          this.sendFileRequest(file)
        }
        event.target.value = ''
      })
    },
    // 发送请求
    sendFileRequest (file, result) {
      var params = { file: file }
      if (this.batchId) {
        params.batchId = this.batchId
      }
      // crmFileSave(params)
      //   .then(res => {
      //     if (this.batchId === '') {
      //       this.batchId = res.batchId
      //     }
      //     res.size = fileSize(res.size)
      //     this.dataValue.push(res)
      //     this.$emit('value-change', {
      //       index: this.index,
      //       value: this.dataValue
      //     })
      //     if (result) {
      //       result()
      //     }
      //   })
      //   .catch(() => {})
    },
    /** 删除图片 */
    deleteFile (item, index) {
      this.$confirm('您确定要删除该文件吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          // crmFileDelete({
          //   id: item.fileId
          // })
          //   .then(res => {
          //     this.dataValue.splice(index, 1)
          //     this.$emit('value-change', {
          //       index: this.index,
          //       value: this.dataValue
          //     })
          //     this.$message.success('操作成功')
          //   })
          //   .catch(() => {})
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消操作'
          })
        })
    }
  }
}
</script>
<style lang="less" scoped>
/** 附件  */
.xh-files-cont {
  position: relative;
  display: inline-block;
  border-radius: 3px;
  width: 100%;
  border: 1px solid #ddd;
  padding: 3.5px 5px;
  margin: 3px;
  line-height: 15px;
}
.xh-files-cont.is_disabled {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  cursor: not-allowed;
  .f-name {
    background-color: #f0f4f8ea;
    color: #c0c4cc;
    cursor: not-allowed;
  }
}
.xh-files-cont.is_valid:hover {
  border-color: #c0c4cc;
}
.f-header {
  cursor: pointer;
  padding: 5px 0 5px;
  .f-logo {
    position: block;
    width: 15px;
    height: 15px;
    margin-right: 8px;
  }
  .f-name {
    color: #4D88FF;
    font-size: 12px;
  }
}
.f-header.is_disabled {
  cursor: not-allowed;
}
.f-body {
  .f-item {
    padding: 3px 0;
    height: 25px;
    .f-img {
      position: block;
      width: 15px;
      height: 15px;
      padding: 0 1px;
      margin-right: 8px;
    }
    .f-name {
      color: #666;
      font-size: 12px;
    }
    .close-button {
      cursor: pointer;
    }
  }
}
.bar-iput {
  position: absolute;
  top: 0;
  left: 0;
  height: 0;
  width: 0;
  opacity: 0;
}
</style>
src/components/CreateCom/XhInput.vue
New file
@@ -0,0 +1,36 @@
<template>
  <el-input
    v-model="dataValue"
    :type="type"
    :disabled="disabled"
    @input="valueChange"/>
</template>
<script type="text/javascript">
import stringMixin from './stringMixin'
export default {
  name: 'XhInput', // 新建 input
  components: {},
  mixins: [stringMixin],
  props: {},
  data () {
    return {}
  },
  computed: {
    type () {
      if (this.item && this.item.form_type === 'password') {
        return this.item.form_type
      } else {
        return 'text'
      }
    }
  },
  watch: {},
  mounted () {
    console.log('123')
  },
  methods: {}
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhInputSelect.vue
New file
@@ -0,0 +1,201 @@
<template>
  <div :class="isProduct?'':'input-container'">
      <el-autocomplete
      ref="elautocomplete"
      v-model="state"
      :class="isProduct?'search-container':''"
      :fetch-suggestions="querySearchAsync"
      :placeholder="isProduct?'输入产品名称':'请输入内容'"
      :trigger-on-focus="false"
      @blur='blurInput'
      @select="handleSelect"
    ></el-autocomplete>
    </div>
</template>
<script type="text/javascript">
import { GetCustomerPageList } from '@/api/customermanagement/customerManage'
import { GetSalesChanceList } from '@/api/customermanagement/business'
import { GetContacterList } from '@/api/customermanagement/contacts'
import { GetAgreementList, GetManagementAgreementList } from '@/api/customermanagement/contract'
import { GetQuotationSheetList, GetManagementQuotationSheetList } from '@/api/customermanagement/offer'
import { GetOtherCustomerPageList, GetOtherSalesChanceList, GetOtherAgreementList } from '@/api/businessIntelligence/index'
export default {
  name: 'XhInputSelect', // 新建 multiple select
  components: {},
  data () {
    return {
      options: [],
      value: [],
      inputVal: '',
      list: [],
      states: [],
      allInfos: [],
      state: '',
      isSelect: false,
      timeout: null
    }
  },
  props: {
    arrayList: { // 下拉列表的数据
      type: Array
    },
    /** 没有值就是全部类型 有值就是当个类型 */
    crmType: {
      type: String,
      default: ''
    },
    isProduct: {
      type: Boolean,
      default: true
    }
  },
  watch: {
    state: {
      handler (val) {
        console.log(val)
        this.$emit('getName', {'name': val})
      },
      deep: true,
      immediate: true
    }
  },
  mounted () {
    console.log(this.isProduct)
  },
  methods: {
    querySearchAsync (queryString, cb) {
      this.getList(queryString)
      clearTimeout(this.timeout)
      this.timeout = setTimeout(() => {
        cb(this.allInfos)
      }, 3000 * Math.random())
    },
    handleSelect (item) {
      this.isSelect = true
      this.$emit('getName', {'name': item.value})
    },
    blurInput () {
      if (!this.isSelect) {
        console.log('blurrrrrrr')
        this.$emit('getName', {'name': this.state})
      }
    },
    resetInput () {
      this.state = ''
    },
    getList (query) {
      if (query !== '') {
        let params = []
        if (this.crmType === 'contract' || this.crmType === 'offers') {
          params = {
            'PageIndex': 1,
            'PageSize': 20,
            'SelectOwnedType': 0,
            'AuditStatus': 0,
            'SealStatus': 0,
            'Name': query,
            'CreateStartTime': '',
            'CreateEndTime': ''
          }
        } else if (this.crmType === 'sealContract' || this.crmType === 'sealOffers') {
          params = {
            'PageIndex': 1,
            'PageSize': 20,
            'DepartmentUserType': 0,
            'SelectOwnedType': 0,
            'AuditStatus': 0,
            'SealStatus': 0,
            'Name': query,
            'CreateStartTime': '',
            'CreateEndTime': ''
          }
        } else {
          params = {
            'PageIndex': 1,
            'PageSize': 20,
            'SelectOwnedType': 0,
            'Name': query,
            'CreateStartTime': '',
            'CreateEndTime': '',
            'StartFollowTime': '',
            'EndFolowTime': ''
          }
        }
        const request = {
          customer: GetCustomerPageList,
          business: GetSalesChanceList,
          contacts: GetContacterList,
          contract: GetAgreementList,
          offers: GetQuotationSheetList,
          sealContract: GetManagementAgreementList,
          sealOffers: GetManagementQuotationSheetList,
          businessCustomer: GetOtherCustomerPageList,
          businessContract: GetOtherAgreementList,
          businessChances: GetOtherSalesChanceList
        }[this.crmType]
        setTimeout(() => {
          if (!this.isProduct) {
            request(params)
              .then(res => {
                console.log(res)
                if (res.data.ErrorCode === 200) {
                  this.options = res.data.Result.List || []
                  this.allInfos = this.options.map((terminal) => {
                    if (this.crmType === 'customer' || this.crmType === 'businessCustomer') {
                      return {
                        value: terminal.CustomerName,
                        name: terminal.CustomerName
                      }
                    } else if (this.crmType === 'business' || this.crmType === 'businessChances') {
                      return {
                        value: terminal.ChanceName,
                        name: terminal.ChanceName
                      }
                    } else if (this.crmType === 'contacts') {
                      return {
                        value: terminal.ChanceName,
                        name: terminal.ChanceName
                      }
                    } else if (this.crmType === 'offers' || this.crmType === 'sealOffers') {
                      return {
                        value: terminal.QuotationName,
                        name: terminal.QuotationName
                      }
                    } else if (this.crmType === 'contract' || this.crmType === 'sealContract' || this.crmType === 'businessContract') {
                      return {
                        value: terminal.AgreeName,
                        name: terminal.AgreeName
                      }
                    }
                  })
                  console.log(this.allInfos)
                } else {
                  this.options = []
                  this.allInfos = []
                  this.$message.error(res.data.Message)
                }
              })
          }
        }, 300)
      } else {
        this.options = []
      }
    }
  }
}
</script>
<style lang="scss" scoped>
.input-container {
    width: 224px;
    height: 32px;
    border-radius: 4px;
    margin-right: 40px
}
.search-container{
  width: 224px;
  height: 32px;
}
.search-container.el-autocomplete /deep/ .el-input__inner{
  height: 32px;
}
</style>
src/components/CreateCom/XhMultipleSelect.vue
New file
@@ -0,0 +1,45 @@
<template>
  <el-select
    v-model="dataValue"
    :disabled="disabled"
    style="width: 100%;"
    multiple
    placeholder="请选择"
    @change="valueChange">
    <el-option
      v-for="item in option"
      :key="item.value"
      :label="item.value"
      :value="item.value"/>
  </el-select>
</template>
<script type="text/javascript">
import arrayMixin from './arrayMixin'
export default {
  name: 'XhMultipleSelect', // 新建 multiple select
  components: {},
  mixins: [arrayMixin],
  props: {},
  data () {
    return {}
  },
  computed: {
    option () {
      var array = []
      if (this.item && this.item.data.setting) {
        for (let index = 0; index < this.item.data.setting.length; index++) {
          const element = this.item.data.setting[index]
          array.push({ value: element })
        }
      }
      return array
    }
  },
  watch: {},
  mounted () {},
  methods: {}
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhProduct.vue
New file
@@ -0,0 +1,391 @@
<template>
  <div class='productWrap'>
    <div class="handel-header">
    <el-dialog title="添加产品" :visible.sync="showPopover" :modal-append-to-body="false" width="80%" top="4vh" class='productTitle'>
      <crm-relative
          v-if="showSelectView"
          ref="crmrelative"
          :isProduct="true"
          :radio="false"
          :show="showPopover"
          :selected-data="selectedData"
          crm-type="product"
          @close="showPopover=false"
          @changeVal="selectInfos"/>
    </el-dialog>
    <el-button
      v-show='!isLcTbl'
      slot="reference"
      @click="showProduct">+ 添加产品</el-button>
    <el-button
      v-show='isLcTbl'
      slot="reference"
      @click="showProduct">+ 添加盗版产品</el-button>
      <!--<el-popover
        v-model="showPopover"
        placement="bottom"
        width="700"
        style="padding: 0 !important;"
        trigger="click">
        <crm-relative
          v-if="showSelectView"
          ref="crmrelative"
          :radio="false"
          :show="showPopover"
          :selected-data="selectedData"
          crm-type="product"
          @close="showPopover=false"
          @changeVal="selectInfos"/>
        <el-button
          v-show='!isLC'
          slot="reference"
          @click="showSelectView=true">+ 添加产品</el-button>
      </el-popover>
      <el-popover
        v-model="showSecondPopover"
        placement="bottom"
        width="200"
        style="padding: 0 !important"
        trigger="click">
        <div style="height: 200px;">
          <div class='el-scrollbar' style="height: 100%">
            <div class='el-select-dropdown__wrap el-scrollbar__wrap' style="margin-bottom: -7px; margin-right: -7px;">
              <ul class="el-scrollbar__view el-select-dropdown__list">
                <li class='el-select-dropdown__item'
                :class="item.value === proValue?'selected':''"
                v-for="item in options"
                :key="item.value"
                @click="getItem(item.value)"
                >{{item.label}}</li>
               <flexbox class="popover-foot">
                  <el-button @click="hidenPopoverView" style='margin-right:16px;'>取 消</el-button>
                  <el-button
                    type="primary"
                    @click="setFakePro">确 定</el-button>
                </flexbox>
              </ul>
            </div>
          </div>
        </div>
        <el-button
          v-show='isLC'
          slot="reference">+ 添加盗版产品</el-button>
      v-if='isTableShow'
      </el-popover>-->
    </div>
    <el-table
      id="crm-table"
      :data="productList"
      :cell-style="cellStyle"
      class="n-table--border"
      border
      highlight-current-row
      style="width: 100%;">
      <el-table-column
        v-for="(item, index) in fieldList"
        :key="'crm'+index"
        :prop="item.field"
        :label="item.name"
        :formatter="fieldFormatter"
        show-overflow-tooltip/>
      <el-table-column/>
      <el-table-column prop="Amount" label="使用数量" :key='1+index'>
       <template slot-scope="scope">
           <el-input size="small" type="number" min='0' v-show="scope.row.show" v-model="scope.row.Amount" placeholder="请输入内容" @keyup.enter.native="getEditData(scope.row)" @keyup.esc.native="cancelEdit(scope.row)"></el-input>
           <span v-show="!scope.row.show">{{scope.row.Amount}}</span>
       </template>
      </el-table-column>
      <el-table-column prop="Department" label="使用部门" v-if="isLcTbl" :key='2+index'>
       <template slot-scope="scope">
           <el-input size="small" v-show="scope.row.show" v-model="scope.row.Department" placeholder="请输入使用部门" @keyup.enter.native="getEditData(scope.row)"></el-input>
           <span v-show="!scope.row.show">{{scope.row.Department}}</span>
       </template>
      </el-table-column>
      <el-table-column prop="Comment" label="说明" v-if="isLcTbl" :key='3+index'>
       <template slot-scope="scope">
           <el-input size="small" v-show="scope.row.show" v-model="scope.row.Comment" placeholder="请输入说明" @keyup.enter.native="getEditData(scope.row)"></el-input>
           <!--@blur="getEditData(scope.row)"-->
           <span v-show="!scope.row.show">{{scope.row.Comment}}</span>
       </template>
      </el-table-column>
      <el-table-column label="操作" width="150">
        <template slot-scope="scope">
          <el-button type="text" v-show="!scope.row.show" @click="scope.row.show=true">编辑 |</el-button>
          <el-button type="text" v-show="scope.row.show" @click="getEditData(scope.row)" style="margin-left:0">保存 |</el-button>
          <el-button type="text" v-show="scope.row.show" @click="cancelEdit(scope.row)" style="margin-left:0">取消</el-button>
          <el-button type="text"  v-show="!scope.row.show" @click="removeItem(scope.$index)" style="margin-left:0">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script type="text/javascript">
import objMixin from './objMixin'
import CrmRelative from '@/components/CreateCom/CrmRelative'
import Lockr from 'lockr'
export default {
  name: 'XhProduct', // 关联产品
  components: {
    CrmRelative
  },
  mixins: [objMixin],
  props: {
    value: {
      type: Array,
      default: () => {
        return []
      }
    },
    crmType: {
      type: String,
      default: ''
    },
    isLC: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      showPopover: false, // 展示产品框
      showSelectView: false, // 内容
      showSecondPopover: false,
      productList: [],
      totalPrice: 0,
      discountRate: 0,
      selectedData: { product: [] },
      options: [{
        value: 'ACAD',
        label: 'ACAD'
      }, {
        value: 'AEC',
        label: 'AEC'
      }, {
        value: 'AEC2',
        label: 'AEC2'
      }, {
        value: 'AMA',
        label: 'AMA'
      }, {
        value: 'AMA2',
        label: 'AMA2'
      }, {
        value: 'CAM',
        label: 'CAM'
      }, {
        value: 'CAM2',
        label: 'CAM2'
      }],
      proValue: '',
      isTableShow: false,
      isLcTbl: false
    }
  },
  computed: {
    fieldList () {
      if (this.isLcTbl) {
        return [
          { name: '产品线', field: 'ProductLine', formType: 'text' }
        ]
      } else {
        return [
          { name: '产品类型', field: 'ProductType', formType: 'text' },
          { name: 'SKU值', field: 'SKU', formType: 'text' }
        ]
      }
    }
  },
  watch: {
    productList: {
      handler (newVal, oldVal) {
        this.selectedData = { product: this.productList || [] }
        return newVal
      },
      deep: true,
      immediate: true
    },
    isLC: {
      handler (newVal, oldVal) {
        this.isLcTbl = newVal
        return newVal
      },
      deep: true,
      immediate: true
    },
    value () {
      // this.productList = this.value
      console.log(this.productList, this.value)
      // this.selectInfos(this.value)
    }
  },
  mounted () {
    this.productList = Lockr.get('productList')
  },
  beforeDestroy () {
    Lockr.set('productList', [])
  },
  methods: {
    cancelEdit (row) {
      row.show = false
    },
    getEditData (row) {
      row.show = false
      let list = JSON.parse(JSON.stringify(this.productList))
      for (let i in list) {
        list[i].Amount = JSON.parse(this.productList[i].Amount)
        delete list[i].show
      }
      this.$emit('value-change', {
        data: this.productList
          ? list
          : [],
        type: 'product'
      })
    },
    getItem (data) {
      this.proValue = data
    },
    showProduct () {
      this.showPopover = true
      this.showSelectView = true
    },
    hidenPopoverView () {
      document.querySelector('#app').click()
      this.showSecondPopover = false
      this.proValue = ''
    },
    fieldFormatter (row, column) {
      return row[column.property] || '--'
    },
    cellStyle ({ row, column, rowIndex, columnIndex }) {
      return { textAlign: 'left' }
    },
    /** 选中 */
    selectInfos (data, flag) {
      if (flag !== undefined) {
        this.isLcTbl = flag
      }
      if (data && data.length > 0) {
        this.isTableShow = true
        let newSelects = []
        data.forEach(element => {
          newSelects.push(this.getShowItem(element))
        })
        this.productList = newSelects
        Lockr.set('productList', newSelects)
        // 数据回填
        let list = JSON.parse(JSON.stringify(this.productList))
        for (let i in list) {
          delete list[i].show
        }
        this.$emit('value-change', {
          data: this.productList
            ? list
            : [],
          type: 'product'
        })
      } else {
        this.isTableShow = false
      }
    },
    getShowItem (data) {
      const item = {}
      if (!this.isLcTbl) {
        item.ProductType = data.ProductType
        item.SKU = data.SKU
        item.Amount = data.Amount ? data.Amount : 1
        item.show = false
      } else {
        item.Amount = data.Amount ? data.Amount : 1
        item.ProductLine = data.ProductLine
        item.Comment = data.Comment
        item.Department = data.Department
        item.show = false
      }
      return item
    },
    // 删除操作
    removeItem (index) {
      this.productList.splice(index, 1)
      let list = JSON.parse(JSON.stringify(this.productList))
      for (let i in list) {
        delete list[i].show
      }
      this.$emit('value-change', {
        data: this.productList
          ? list
          : [],
        type: 'product'
      })
    }
  }
}
</script>
<style lang="scss" scoped>
@import '../../views/clients/styles/table.scss';
.productWrap{
  display: flex;
  flex-direction: column;
}
.handel-header {
  button {
    width: 117px;
    height: 36px;
    border-radius: 4px;
    border: 1px solid #4D88FF;
    margin-bottom: 40px;
    margin-left: 30px;
    color: #4D88FF;
    font-size: 14px;
  }
}
// .handel-header /deep/ .el-button--default{
//   padding: 0 20px;
//   height: 36px;
//   border-radius: 4px;
//   border: 1px solid #4D88FF;
//   font-size: 14px;
//   font-weight: 400;
//   color: #4D88FF;
// }
.el-table /deep/ thead th, thead td {
  padding:3px 0px;
}
.handle-footer {
  position: relative;
  font-size: 12px;
  padding: 5px;
  .discount-title {
    color: #666;
  }
  .total-info {
    position: absolute;
    right: 20px;
    top: 5px;
    .info-yellow {
      color: #fd715a;
    }
  }
}
.el-scrollbar__wrap{
  overflow-x:hidden;
  }
.popover-foot{
  position: relative;
  width: 100%;
  border-top: 1px solid #f1f1f1;
  padding-top: 10px;
  button{
    height: 20px;
    line-height: 1px;
    text-align: center;
    font-size: 12px;
    margin-left: 22px;
  }
}
.productTitle /deep/ .el-dialog__headerbtn .el-dialog__close{
  font-size: 24px;
}
</style>
src/components/CreateCom/XhProuctCate.vue
New file
@@ -0,0 +1,61 @@
<template>
  <el-cascader
    ref="elCascader"
    :options="options"
    :show-all-levels="false"
    :props="defaultProps"
    v-model="dataValue"
    :disabled="disabled"
    style="width: 100%;"
    change-on-select
    @change="valueChange"/>
</template>
<script type="text/javascript">
import arrayMixin from './arrayMixin'
// import { productCategoryIndex } from '@/api/systemManagement/SystemCustomer'
export default {
  name: 'XhProducCate', // 新建 产品分类
  components: {},
  mixins: [arrayMixin],
  props: {},
  data () {
    return {
      options: [],
      defaultProps: {
        children: 'children',
        label: 'label',
        value: 'categoryId'
      }
    }
  },
  computed: {},
  watch: {},
  mounted () {
    this.getProductCategoryIndex()
  },
  methods: {
    /** 获取产品分类数据 */
    getProductCategoryIndex () {
      // productCategoryIndex({
      //   type: 'tree'
      // })
      //   .then(res => {
      //     this.options = res.data
      //   })
      //   .catch(() => {})
    },
    valueChange (val) {
      this.$emit('value-change', {
        index: this.index,
        item: this.item,
        value: val,
        valueContent: this.$refs.elCascader.currentLabels.join(',')
      })
    }
  }
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhReceivablesPlan.vue
New file
@@ -0,0 +1,70 @@
<template>
  <el-select
    v-model="dataValue"
    :disabled="disabled"
    style="width: 100%;"
    placeholder="请选择"
    @change="valueChange(dataValue, option)">
    <el-option
      v-for="(item, index) in option"
      :key="index"
      :label="item.num"
      :value="item.planId"/>
  </el-select>
</template>
<script type="text/javascript">
import stringMixin from './stringMixin'
// import {
//   crmQueryReceivablesPlansByContractId
// } from '@/api/clients/contract'
export default {
  name: 'XhReceivablesPlan', // 回款 下的 回款计划
  components: {},
  mixins: [stringMixin],
  props: {
    relation: {
      // 相关ID
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data () {
    return {
      option: []
    }
  },
  computed: {},
  watch: {
    relation: function (val) {
      if (val.moduleType) {
        this.getPlanList()
      } else {
        this.option = []
      }
    }
  },
  mounted () {
    if (this.relation.moduleType) {
      this.getPlanList()
    }
  },
  methods: {
    getPlanList () {
      this.loading = true
      // crmQueryReceivablesPlansByContractId({ contractId: this.relation.contractId })
      //   .then(res => {
      //     this.loading = false
      //     this.option = res.data
      //   })
      //   .catch(() => {
      //     this.loading = false
      //   })
    }
  }
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhRelativeInput.vue
New file
@@ -0,0 +1,226 @@
<template>
  <el-popover
    class='pop'
    :disabled="item.disabled"
    :offset="250"
    placement="right"
    popper-class="no-padding-popover"
    width="500"
    trigger="click">
    <div class="container">
      <flexbox class="header">
        <div class="name">客户</div>
        <!--<div class="detail"></div>-->
        <img
          class="close"
          src="@/assets/img/task_close.png"
          @click="hidenView" >
      </flexbox>
      <flexbox class="content">
        <div class="cropper-box">
          <span class='searchTitle'>查找内容:</span>
          <el-input class='searchInput' v-model='popSearch' placeholder='请输入客户名称'></el-input>
          <el-button  type="primary" class='searchBtn' @click='getCustomerTable'>立即查找</el-button>
        </div>
      </flexbox>
      <el-table
        v-loading="loading"
        :data="popData"
        :cell-style="popCellStyle"
        :header-cell-style="headerCellStyle"
        height="250"
        style="margin-right:3px;"
        highlight-current-row
        @row-click="handlePopRowClick">
        <el-table-column
          v-for="(item, index) in popFieldList"
          :key="index"
          :prop="item.field"
          :label="item.value"
          align="center"
          header-align="center"
          show-overflow-tooltip/>
      </el-table>
      <div class="p-contianer">
        <el-pagination
          :current-page="currentPopPage"
          :page-sizes="pagePopSizes"
          :page-size.sync="pagePopSize"
          :total="totalPop"
          class="p-bar"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handlePopSizeChange"
          @current-change="handlePopCurrentChange"/>
      </div>
    </div>
    <el-input slot="reference" :disabled='true' v-model='customerChosed' placeholder='请点击选择客户'></el-input>
  </el-popover>
</template>
<script type="text/javascript">
import { GetPersonalCustomerPageList } from '@/api/customermanagement/customerManage'
export default {
  name: 'XhRelativeInput', // 新建 XhRelativeInput
  components: {},
  props: {
    item: {
      type: Object,
      default: () => {
        return {}
      }
    },
    customerId: {
      type: String,
      default: () => {
        return ''
      }
    }
  },
  data () {
    return {
      loading: false,
      popData: [],
      currentPopPage: 1,
      pagePopSize: 15,
      pagePopSizes: [15, 30, 60, 100],
      customerChosed: '',
      popSearch: '',
      totalPop: 0
    }
  },
  computed: {
    popFieldList () {
      if (this.item && this.item.field === 'CustomerId') {
        return [
          { field: 'CustomerNumber', value: '客户编号', width: '20' },
          { field: 'CustomerName', value: '客户名称', width: '20' },
          { field: 'Contacter', value: '联系人', width: '20' },
          { field: 'ContactMobile', value: '联系人方式', width: '30' },
          { field: 'CustomerStatus', value: '客户业务状态', width: '10' },
          { field: 'CustomerSource', value: '客户来源', width: '10' },
          { field: 'CustomerType', value: '客户大类型', width: '10' },
          { field: 'CostomerCategory', value: '客户类别', width: '10' },
          { field: 'Industry', value: '所属行业', width: '12' },
          { field: 'ProvinceCode', value: '省编码', width: '10' },
          { field: 'CityCode', value: '市编码', width: '10' },
          { field: 'SaleOwerId', value: '销售员', width: '10' },
          { field: 'SaleName', value: '销售员姓名', width: '10' },
          { field: 'CreateTime', value: '创建时间', width: '10' },
          { field: 'NextFollowTime', value: '最新跟进时间', width: '10' }
        ]
      } else {
        return []
      }
    }
  },
  watch: {
  },
  mounted () {
    console.log(1111111, this.item)
    if (this.item && this.item.field === 'CustomerId') {
      this.customerChosed = this.item.chosedCusName ? this.item.chosedCusName : ''
      this.getCustomerTable()
    }
  },
  methods: {
    /** 通过回调控制style */
    popCellStyle ({ row, column, rowIndex, columnIndex }) {
      return { fontSize: '12px', textAlign: 'center', cursor: 'pointer' }
    },
    headerCellStyle ({ row, column, rowIndex, columnIndex }) {
      return { fontSize: '12px', textAlign: 'center' }
    },
    handlePopSizeChange (newSize) {
      this.pagePopSizes = newSize
      this.getCustomerTable()
    },
    handlePopCurrentChange (newPage) {
      this.currentPopPage = newPage
      this.getCustomerTable()
    },
    getCustomerTable () {
      let params = {
        Name: this.popSearch,
        PageIndex: this.currentPopPage,
        PageSize: this.pagePopSize
      }
      if (this.item && this.item.field === 'CustomerId') {
        GetPersonalCustomerPageList(params).then(res => {
          if (res.data.ErrorCode === 200 && res.data.Result !== 0) {
            this.popData = res.data.Result.List || []
            this.totalPop = res.data.Result.Count
          } else {
            this.$message.error(res.data.Message)
            this.loading = false
          }
        })
      }
    },
    hidenView () {
      document.querySelector('#app').click()
      this.$emit('close', this.$el, this.data)
    },
    // 当某一行被点击时会触发该事件
    handlePopRowClick (row, column, event) {
      this.$emit('value-change', {index: this.item.field,
        value: row.Id,
        name: row.CustomerName})
      this.customerChosed = row.CustomerName
      console.log(this.customerChosed)
      this.hidenView()
    }
  }
}
</script>
<style lang="scss" scoped>
.container {
  position: relative;
}
.header {
  height: 40px;
  padding: 0 10px;
  flex-shrink: 0;
  .name {
    font-size: 13px;
    padding: 0 10px;
    color: #333;
  }
  .detail {
    font-size: 12px;
    padding: 0 10px;
    color: #aaaaaa;
    border-left: 1px solid #aaaaaa;
  }
  .close {
    position: absolute;
    width: 40px;
    height: 40px;
    top: 0;
    right: 10px;
    padding: 10px;
  }
}
.content{
  .cropper-box{
    display:flex;
    flex-direction: row;
    align-items: center;
    padding: 0 20px;
    .searchTitle{
      font-size: 14px;
      width: 124px;
      color: #333;
    }
    .searchInput{
      margin-right: 20px;
    }
  }
}
.p-contianer .p-bar{
  margin: 5px 0 0 14px;
}
.pop /deep/ .el-input.is-disabled .el-input__inner{
  cursor: pointer;
}
</style>
src/components/CreateCom/XhRelativeInputS.vue
New file
@@ -0,0 +1,214 @@
<template>
  <el-popover
    class='pop'
    :disabled="item.disabled"
    :offset="250"
    placement="right"
    popper-class="no-padding-popover"
    width="500"
    trigger="click">
    <div class="container">
      <flexbox class="header">
        <div class="name">联系人</div>
        <!--<div class="detail"></div>-->
        <img
          class="close"
          src="@/assets/img/task_close.png"
          @click="hidenView" >
      </flexbox>
      <flexbox class="content">
        <div class="cropper-box">
          <span class='searchTitle'>查找内容:</span>
          <el-input class='searchInput' v-model='popSearch' placeholder='请输入联系人名称'></el-input>
          <el-button  type="primary" class='searchBtn' @click='getCustomerTable'>立即查找</el-button>
        </div>
      </flexbox>
      <el-table
        v-loading="loading"
        :data="popData"
        :cell-style="popCellStyle"
        :header-cell-style="headerCellStyle"
        height="250"
        style="margin-right:3px;"
        highlight-current-row
        @row-click="handlePopRowClick">
        <el-table-column
          v-for="(item, index) in popFieldList"
          :key="index"
          :prop="item.field"
          :label="item.value"
          align="center"
          header-align="center"
          show-overflow-tooltip/>
      </el-table>
      <div class="p-contianer">
        <el-pagination
          :current-page="currentPopPage"
          :page-sizes="pagePopSizes"
          :page-size.sync="pagePopSize"
          :total="totalPop"
          class="p-bar"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handlePopSizeChange"
          @current-change="handlePopCurrentChange"/>
      </div>
    </div>
    <el-input slot="reference" :disabled='true' v-model='contacterChosed' placeholder='请点击选择联系人'></el-input>
  </el-popover>
</template>
<script type="text/javascript">
import { GetPersonalContacterList } from '@/api/customermanagement/contacts'
export default {
  name: 'XhRelativeInputS', // 新建 XhRelativeInput
  components: {},
  props: {
    item: {
      type: Object,
      default: () => {
        return {}
      }
    },
    customerId: {
      type: String,
      default: () => {
        return ''
      }
    }
  },
  data () {
    return {
      loading: false,
      popData: [],
      currentPopPage: 1,
      pagePopSize: 15,
      pagePopSizes: [15, 30, 60, 100],
      contacterChosed: '',
      popSearch: '',
      totalPop: 0
    }
  },
  computed: {
    popFieldList () {
      if (this.item && this.item.field === 'ContacterId') {
        return [
          { field: 'ContacterNumber', value: '联系人编号', width: '20' },
          { field: 'CustomerName', value: '联系人名称', width: '20' },
          { field: 'RealName', value: '联系人真实姓名', width: '10' },
          { field: 'Sex', value: '性别', width: '10' },
          { field: 'MobilePhone', value: '联系人方式', width: '30' },
          { field: 'JobPosition', value: '联系人职位', width: '10' },
          { field: 'OwerUserName', value: '负责人', width: '10' }
        ]
      }
    }
  },
  watch: {
  },
  mounted () {
    if (this.item && this.item.field === 'ContacterId') {
      this.contacterChosed = this.item.chosedCusName ? this.item.chosedCusName : ''
      this.getCustomerTable()
    }
  },
  methods: {
    /** 通过回调控制style */
    popCellStyle ({ row, column, rowIndex, columnIndex }) {
      return { fontSize: '12px', textAlign: 'center', cursor: 'pointer' }
    },
    headerCellStyle ({ row, column, rowIndex, columnIndex }) {
      return { fontSize: '12px', textAlign: 'center' }
    },
    handlePopSizeChange (newSize) {
      this.pagePopSizes = newSize
      this.getCustomerTable()
    },
    handlePopCurrentChange (newPage) {
      this.currentPopPage = newPage
      this.getCustomerTable()
    },
    getCustomerTable () {
      let params = {
        Name: this.popSearch,
        PageIndex: this.currentPopPage,
        PageSize: this.pagePopSize,
        CustomerId: this.customerId
      }
      if (this.item && this.item.field === 'ContacterId') {
        GetPersonalContacterList(params).then(res => {
          if (res.data.ErrorCode === 200 && res.data.Result !== 0) {
            this.popData = res.data.Result.List || []
            this.totalPop = res.data.Result.Count
          } else {
            this.$message.error(res.data.Message)
            this.loading = false
          }
        })
      }
    },
    hidenView () {
      document.querySelector('#app').click()
      this.$emit('close', this.$el, this.data)
    },
    // 当某一行被点击时会触发该事件
    handlePopRowClick (row, column, event) {
      this.$emit('value-change', {index: this.item.field,
        value: row.Id})
      this.contacterChosed = row.RealName
      this.hidenView()
    }
  }
}
</script>
<style lang="scss" scoped>
.container {
  position: relative;
}
.header {
  height: 40px;
  padding: 0 10px;
  flex-shrink: 0;
  .name {
    font-size: 13px;
    padding: 0 10px;
    color: #333;
  }
  .detail {
    font-size: 12px;
    padding: 0 10px;
    color: #aaaaaa;
    border-left: 1px solid #aaaaaa;
  }
  .close {
    position: absolute;
    width: 40px;
    height: 40px;
    top: 0;
    right: 10px;
    padding: 10px;
  }
}
.content{
  .cropper-box{
    display:flex;
    flex-direction: row;
    align-items: center;
    padding: 0 20px;
    .searchTitle{
      font-size: 14px;
      width: 124px;
      color: #333;
    }
    .searchInput{
      margin-right: 20px;
    }
  }
}
.p-contianer .p-bar{
  margin: 5px 0 0 14px;
}
.pop /deep/ .el-input.is-disabled .el-input__inner{
  cursor: pointer;
}
</style>
src/components/CreateCom/XhSelect.vue
New file
@@ -0,0 +1,67 @@
<template>
  <el-select
    v-model="dataValue"
    :disabled="disabled"
    style="width: 100%;"
    placeholder="请选择"
    @change="valueChange">
    <el-option
      v-for="(item, index) in option"
      :key="index + 1"
      :label="item.name"
      :value="index + 1"/>
  </el-select>
</template>
<script type="text/javascript">
import stringMixin from './stringMixin'
export default {
  name: 'XhSelect', // 新建 select
  components: {},
  mixins: [stringMixin],
  props: {},
  data () {
    return {
      option: []
    }
  },
  computed: {},
  watch: {
    item: {
      handler (val) {
        if (val && val.data.setting) {
          var settingList = val.data.setting
          if (settingList.length > 0 && typeof settingList[0] === 'string') {
            var array = []
            for (let index = 0; index < settingList.length; index++) {
              const element = settingList[index]
              array.push({ name: element, value: element })
            }
            this.option = array
          } else if (
            settingList.length > 0 &&
            settingList[0].statusId &&
            !settingList[0].value
          ) {
            // 商机阶段
            this.option = settingList.map((item, index, array) => {
              item.value = item.statusId
              return item
            })
          } else {
            this.option = settingList
          }
        } else {
          this.option = []
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted () {},
  methods: {}
}
</script>
<style lang="less" scoped>
</style>
src/components/CreateCom/XhStrucUserCell.vue
New file
@@ -0,0 +1,134 @@
<template>
  <members-dep
    :popover-display="'block'"
    :dep-checked-data="dataStrucs"
    :user-checked-data="dataUsers"
    @popoverSubmit="popoverSubmit">
    <div slot="membersDep">
      <flexbox
        wrap="wrap"
        class="structure-container">
        <div
          v-for="(item, index) in dataUsers"
          :key="'user'+index"
          class="user-item">{{ item.name ? item.name : item.realname }}
        </div>
        <div
          v-for="(item, index) in dataStrucs"
          :key="'struc'+index"
          class="user-item">{{ item.name }}
        </div>
        <div class="add-item">+添加</div>
      </flexbox>
    </div>
  </members-dep>
</template>
<script type="text/javascript">
import membersDep from '@/components/selectEmployee/membersDep'
export default {
  name: 'XhStrucUserCell', // 新建 struc-user-cell
  components: {
    membersDep
  },
  props: {
    // 员工和 部门
    users: {
      type: Array,
      default: () => {
        return []
      }
    },
    strucs: {
      type: Array,
      default: () => {
        return []
      }
    },
    value: {
      type: Object,
      default: () => {
        return {
          users: [],
          strucs: []
        }
      }
    },
    /** 索引值 用于更新数据 */
    index: Number,
    /** 包含数据源 */
    item: Object
  },
  data () {
    return {
      dataUsers: [], // 关联的时候展示name 编辑的时候展示realname
      dataStrucs: []
    }
  },
  computed: {},
  watch: {
    value: function (val) {
      this.dataUsers = val.users
      this.dataStrucs = val.strucs
    },
    users: function (val) {
      this.dataUsers = val
    },
    strucs: function (val) {
      this.dataStrucs = val
    }
  },
  created () {
    if (this.value) {
      this.dataUsers = this.value.users
      this.dataStrucs = this.value.strucs
    }
  },
  methods: {
    popoverSubmit (users, strucs) {
      this.dataUsers = users
      this.dataStrucs = strucs
      this.$emit('value-change', {
        index: this.index,
        value: { users: users, strucs: strucs }
      })
    }
  }
}
</script>
<style lang="less" scoped>
.structure-container {
  min-height: 34px;
  margin: 3px 0;
  position: relative;
  border-radius: 3px;
  font-size: 12px;
  border: 1px solid #ddd;
  color: #333333;
  padding: 0.5px;
  line-height: 15px;
  max-height: 105px;
  overflow-y: auto;
  .user-item {
    padding: 5px;
    background-color: #e2ebf9;
    border-radius: 3px;
    margin: 3px;
    cursor: pointer;
  }
  .add-item {
    padding: 5px;
    color: #4D88FF;
    cursor: pointer;
  }
  .delete-icon {
    color: #999;
    cursor: pointer;
  }
  &:hover {
    border-color: #c0c4cc;
  }
}
</style>
src/components/CreateCom/XhStructure.vue
New file
@@ -0,0 +1,246 @@
<template>
  <div>
    <el-input
      v-model="searchInput"
      placeholder="搜索部门名称"
      size="small"
      suffix-icon="el-icon-search"
      @input="inputchange"/>
    <div
      v-loading="loading"
      class="search-list">
      <el-breadcrumb
        style="padding: 5px 0;"
        separator-class="el-icon-arrow-right">
        <el-breadcrumb-item
          v-for="(item, index) in breadcrumbList"
          :key="index">
          <a
            href="javascript:;"
            @click="breadcrumbBtn(item, index)">{{ item.label }}</a>
        </el-breadcrumb-item>
      </el-breadcrumb>
      <flexbox
        v-for="(item, index) in showlist"
        v-if="item.show"
        :key="index"
        class="stru-list">
        <el-checkbox
          v-model="item.isCheck"
          :disabled="item.disabled"
          class="stru-check"
          @change="checkChange(item, index)"/>
        <div
          class="stru-name"
          @click="enterChildren(item)">{{ item.name }}</div>
        <div
          v-if="item.children"
          class="el-icon-arrow-right stru-enter"/>
      </flexbox>
    </div>
  </div>
</template>
<script type="text/javascript">
// import { depList } from '@/api/common'
export default {
  name: 'XhStructure', // 新建 structure
  components: {},
  props: {
    value: {
      type: Array,
      default: () => {
        return []
      }
    },
    /** 多选框 只能选一个 */
    radio: {
      type: Boolean,
      default: false
    },
    /** 已选信息 */
    selectedData: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data () {
    return {
      breadcrumbList: [], // 面包屑数据
      selectItems: [], // 选择项
      showlist: [], // 展示数据
      loading: false, // 加载动画
      searchInput: ''
    }
  },
  computed: {},
  watch: {},
  mounted () {
    this.selectItems = this.selectedData
    // 部门列表数据
    this.getStructureList()
  },
  methods: {
    // 部门列表数据
    getStructureList () {
      this.loading = true
      // depList({
      //   type: 'tree'
      // })
      //   .then(res => {
      //     this.showlist = this.addIsCheckProp(res.data)
      //     this.breadcrumbList.push({ label: '全部', data: this.showlist })
      //     this.loading = false
      //   })
      //   .catch(() => {
      //     this.loading = false
      //   })
    },
    // 面包屑点击事件
    breadcrumbBtn (item, index) {
      if (this.radio && this.selectItems.length === 1) return
      if (index + 1 <= this.breadcrumbList.length - 1) {
        this.breadcrumbList.splice(index + 1, this.breadcrumbList.length - 1)
      }
      this.showlist = []
      this.showlist = this.handelCheck(item.data)
    },
    // 点击checkbox选中
    checkChange (item, aindex) {
      this.$set(this.showlist, aindex, item)
      var removeIndex = -1
      for (let index = 0; index < this.selectItems.length; index++) {
        const element = this.selectItems[index]
        if (item.id === element.id) {
          removeIndex = index
        }
      }
      if (removeIndex === -1 && item.isCheck) {
        this.selectItems.push(item)
      } else if (removeIndex !== -1) {
        this.selectItems.splice(removeIndex, 1)
      }
      /** 单选逻辑 */
      if (this.radio) {
        if (item.isCheck) {
          this.showlist = this.showlist.map(function (element, index, array) {
            if (element.id === item.id) {
              element.disabled = false
            } else {
              element.disabled = true
            }
            return element
          })
        } else {
          this.showlist = this.showlist.map(function (item, index, array) {
            item.disabled = false
            return item
          })
        }
      }
      this.$emit('changeCheckout', { data: this.selectItems })
    },
    /** 数据重新刷新时 循环标记展示数组 */
    handelCheck (list) {
      var self = this
      list = list.map(function (item, index, array) {
        item.isCheck = self.selectItemsHasItem(item)
        return item
      })
      this.inputchange()
      return list
    },
    selectItemsHasItem (item) {
      if (this.selectItems.length === 0) {
        return false
      }
      var hasItem = false
      for (let index = 0; index < this.selectItems.length; index++) {
        const element = this.selectItems[index]
        if (item.id === element.id) {
          hasItem = true
          break
        }
      }
      return hasItem
    },
    /**  */
    /** 点击进入子数组 */
    enterChildren (item) {
      // 保证单选环境下 没有选中 才可进入children
      if (item.children && !(this.radio && this.selectItems.length === 1)) {
        this.showlist = []
        this.showlist = this.handelCheck(this.addIsCheckProp(item.children))
        this.breadcrumbList.push({ label: item.label, data: this.showlist })
      }
    },
    /** 给默认数据加isCheck属性 */
    addIsCheckProp (list) {
      if (list.length > 0) {
        var item = list[0]
        if (item.hasOwnProperty('isCheck')) {
          return list
        } else {
          return list.map(function (item, index, array) {
            item.disabled = false
            item.isCheck = false
            item.show = true
            return item
          })
        }
      }
      return list
    },
    // 父组件 选中
    parentRemoveCheck (data) {
      this.selectItems = data.data
      var temps = this.showlist
      this.showlist = []
      this.showlist = this.handelCheck(temps)
      /** 单选逻辑 */
      if (this.radio) {
        this.showlist = this.showlist.map(function (item, index, array) {
          item.disabled = false
          return item
        })
      }
    },
    /** 搜索 */
    inputchange (val) {
      this.showlist = this.showlist.map(function (item, index, array) {
        if (item.name.indexOf(val) !== -1) {
          item.show = true
        } else {
          item.show = false
        }
        return item
      })
    }
  }
}
</script>
<style lang="less" scoped>
.search-list {
  padding: 5px;
  height: 248px;
  overflow: auto;
}
.stru-list {
  padding: 5px;
  font-size: 13px;
  .stru-check {
    margin-right: 8px;
  }
  .stru-name {
    flex: 1;
  }
  .stru-enter {
    margin-right: 8px;
  }
}
</style>
src/components/CreateCom/XhStructureCell.vue
New file
@@ -0,0 +1,142 @@
<template>
  <el-popover
    :disabled="disabled"
    placement="bottom"
    width="300"
    trigger="click">
    <xh-structure
      v-if="!disabled && showSelectView"
      ref="structure"
      :radio="radio"
      :selected-data="dataValue"
      @changeCheckout="checkStructure"/>
    <div slot="reference">
      <flexbox
        :class="[disabled ? 'is_disabled' : 'is_valid']"
        wrap="wrap"
        class="structure-container"
        @click.native="focusClick">
        <div
          v-for="(item, index) in dataValue"
          :key="index"
          class="user-item"
          @click.stop="deletestru(item,index)">{{ item.name }}
          <i class="delete-icon el-icon-close"/>
        </div>
        <div class="add-item">+添加部门</div>
      </flexbox>
    </div>
  </el-popover>
</template>
<script type="text/javascript">
import XhStructure from './XhStructure'
import arrayMixin from './arrayMixin'
export default {
  name: 'XhStructureCell', // 新建 structure-cell
  components: {
    XhStructure
  },
  mixins: [arrayMixin],
  props: {
    radio: {
      // 是否单选
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      showPopover: false, // 展示popover
      showSelectView: false // 展示选择内容列表
    }
  },
  computed: {},
  watch: {},
  mounted () {},
  methods: {
    /** 选中 */
    checkStructure (data) {
      this.dataValue = data.data
      this.$emit('value-change', {
        index: this.index,
        value: data.data
      })
    },
    /** 删除 */
    deletestru (item, index) {
      this.dataValue.splice(index, 1)
      this.$refs.structure.parentRemoveCheck({
        data: this.dataValue,
        index: index
      })
      this.$emit('value-change', {
        index: this.index,
        value: this.dataValue
      })
    },
    /** 聚焦动作 */
    focusClick () {
      this.showSelectView = true
      this.$emit('focus')
    }
  }
}
</script>
<style lang="less" scoped>
.structure-container {
  min-height: 34px;
  margin: 3px 0;
  position: relative;
  border-radius: 3px;
  font-size: 12px;
  border: 1px solid #ddd;
  color: #333333;
  padding: 0.5px;
  line-height: 15px;
  max-height: 105px;
  overflow-y: auto;
  .user-item {
    padding: 5px;
    background-color: #e2ebf9;
    border-radius: 3px;
    margin: 3px;
    cursor: pointer;
  }
  .add-item {
    padding: 5px;
    color: #4D88FF;
    cursor: pointer;
  }
  .delete-icon {
    color: #999;
    cursor: pointer;
  }
  &:hover {
    border-color: #c0c4cc;
  }
}
.structure-container.is_disabled {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  cursor: not-allowed;
  .user-item {
    background-color: #f0f4f8ea;
    color: #c0c4cc;
    cursor: not-allowed;
  }
  .delete-icon {
    color: #c0c4cc;
    cursor: not-allowed;
  }
  .add-item {
    color: #c0c4cc;
    cursor: not-allowed;
  }
}
.structure-container.is_valid:hover {
  border-color: #c0c4cc;
}
</style>
src/components/CreateCom/XhTextarea.vue
New file
@@ -0,0 +1,41 @@
<template>
  <el-input
    v-model="dataValue"
    :rows="3"
    :maxlength="200"
    :disabled="disabled"
    type="textarea"
    resize="none"
    show-word-limit
    @input="valueChange"/>
</template>
<script type="text/javascript">
import stringMixin from './stringMixin'
export default {
  name: 'XhTextarea', // 新建 textarea
  components: {},
  mixins: [stringMixin],
  props: {},
  data () {
    return {}
  },
  computed: {},
  watch: {},
  mounted () {},
  methods: {}
}
</script>
<style lang="less" scoped>
/** 调整textarea输入 */
.el-textarea /deep/ .el-textarea__inner {
  padding: 5px 8px;
  border-radius: 3px;
  border: 1px solid #ddd;
  color: #333333;
}
.el-textarea /deep/ .el-textarea__inner:focus {
  outline: 0;
  border-color: #ddd;
}
</style>
src/components/CreateCom/XhUser.vue
New file
@@ -0,0 +1,240 @@
<template>
  <div>
    <el-input
      v-model="searchInput"
      placeholder="搜索成员"
      size="small"
      suffix-icon="el-icon-search"
      @input="inputchange"/>
    <div
      v-loading="loading"
      class="search-list">
      <el-checkbox-group
        v-model="selectItems"
        @change="changeCheckout">
        <el-checkbox
          v-for="(item, i) in list"
          v-if="item.show"
          :key="i"
          :label="item"
          :disabled="item.disabled"
          class="colleagues-list">
          <div
            v-photo="item"
            v-lazy:background-image="$options.filters.filterUserLazyImg(item.img)"
            class="div-photo search-img"/>
          <span>{{ item.realname }}</span>
        </el-checkbox>
      </el-checkbox-group>
    </div>
  </div>
</template>
<script type="text/javascript">
// import { usersList } from '@/api/common'
export default {
  name: 'XhUser', // 新建 user
  components: {},
  props: {
    value: {
      type: String,
      default: ''
    },
    /** 多选框 只能选一个 */
    radio: {
      type: Boolean,
      default: false
    },
    /** 已选信息 */
    selectedData: {
      type: Array,
      default: () => {
        return []
      }
    },
    /** 获取不同的员工展示列表 */
    infoType: {
      type: String,
      default: 'default' // 返回全部  crm_contract crm_receivables oa_examine 合同审核人自选列表
    },
    infoRequest: Function,
    /** 请求辅助参数 */
    infoParams: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data () {
    return {
      list: [],
      selectItems: [], // 选择项
      loading: false, // 加载动画
      searchInput: ''
    }
  },
  computed: {},
  watch: {
    selectedData: function (value) {
      this.checkItems(value)
    }
  },
  mounted () {
    this.getUserList()
  },
  methods: {
    // 获取员工列表
    getUserList () {
      this.loading = true
      this.getRequest()(this.getParams())
        .then(res => {
          var self = this
          this.list = res.data.map(function (item, index, array) {
            item.disabled = false // 要求单选
            item.show = true
            if (self.selectedData.length > 0) {
              let disabled = true
              for (let index = 0; index < self.selectedData.length; index++) {
                const element = self.selectedData[index]
                if (element.userId === item.userId) {
                  disabled = false
                  self.selectItems.push(item)
                }
              }
              if (self.radio) {
                item.disabled = disabled
              }
            }
            return item
          })
          this.loading = false
        })
        .catch(() => {
          this.loading = false
        })
    },
    getRequest () {
      if (this.infoRequest) {
        return this.infoRequest
      } else if (this.infoType === 'default') {
        // return usersList
      } else if (
        this.infoType === 'crm_contract' ||
        this.infoType === 'crm_receivables' ||
        this.infoType === 'oa_examine'
      ) {
        // return usersList
      }
    },
    getParams () {
      const params =
        this.infoParams && Object.keys(this.infoParams.length !== 0)
          ? this.infoParams
          : {}
      if (this.infoType === 'default') {
        params.pageType = 0
        return params
      } else if (
        this.infoType === 'crm_contract' ||
        this.infoType === 'crm_receivables' ||
        this.infoType === 'oa_examine'
      ) {
        params.pageType = 0
        return params
      }
    },
    changeCheckout (items) {
      if (this.radio) {
        if (items.length) {
          var element = items[0]
          this.list = this.list.map(function (item, index, array) {
            if (element.userId === item.userId) {
              item.disabled = false
            } else {
              item.disabled = true
            }
            return item
          })
        } else {
          this.list = this.list.map(function (item, index, array) {
            item.disabled = false
            return item
          })
        }
      }
      this.$emit('changeCheckout', { data: this.selectItems })
    },
    /** 取消勾选 */
    cancelCheckItem (item) {
      var removeIndex = -1
      for (let index = 0; index < this.selectItems.length; index++) {
        const element = this.selectItems[index]
        if (element.userId === item.userId) {
          removeIndex = index
        }
      }
      this.selectItems.splice(removeIndex, 1)
      if (this.radio && this.selectItems.length === 0) {
        this.list = this.list.map(function (item, index, array) {
          item.disabled = false
          return item
        })
      }
    },
    /** 标记勾选 */
    checkItems (items) {
      this.selectItems = []
      if (items.length > 0) {
        for (let bigIndex = 0; bigIndex < this.list.length; bigIndex++) {
          const item = this.list[bigIndex]
          let disabled = true
          for (let index = 0; index < items.length; index++) {
            const element = items[index]
            if (element.userId === item.userId) {
              disabled = false
              this.selectItems.push(item)
            }
          }
          if (this.radio) {
            item.disabled = disabled
          }
        }
      }
    },
    // 搜索
    inputchange (val) {
      this.list = this.list.map(function (item, index, array) {
        if (item.realname.indexOf(val) !== -1) {
          item.show = true
        } else {
          item.show = false
        }
        return item
      })
    }
  }
}
</script>
<style lang="less" scoped>
/* 选择员工 */
.search-img {
  width: 24px;
  height: 24px;
  border-radius: 12px;
  vertical-align: middle;
  margin-right: 8px;
}
.search-list {
  padding: 5px;
  height: 248px;
  overflow: auto;
}
.colleagues-list {
  padding: 5px;
  display: block;
  margin-left: 0;
}
</style>
src/components/CreateCom/XhUserCell.vue
New file
@@ -0,0 +1,162 @@
<template>
  <el-popover
    :disabled="disabled"
    placement="bottom"
    width="300"
    trigger="click">
    <xh-user
      v-if="!disabled&&showSelectView"
      ref="xhuser"
      :info-type="infoType"
      :info-params="infoParams"
      :radio="radio"
      :selected-data="dataValue"
      @changeCheckout="checkUsers"/>
    <div slot="reference">
      <flexbox
        :class="[disabled ? 'is_disabled' : 'is_valid']"
        wrap="wrap"
        class="user-container"
        @click.native="focusClick">
        <div
          v-for="(item, index) in dataValue"
          :key="index"
          class="user-item"
          @click.stop="deleteuser(index)">{{ item.realname }}
          <i class="delete-icon el-icon-close"/>
        </div>
        <div class="add-item">+{{ placeholder }}</div>
      </flexbox>
    </div>
  </el-popover>
</template>
<script type="text/javascript">
import XhUser from './XhUser'
import arrayMixin from './arrayMixin'
export default {
  name: 'XhUserCell', // 新建 user-cell
  components: {
    XhUser
  },
  mixins: [arrayMixin],
  props: {
    radio: {
      // 是否单选
      type: Boolean,
      default: true
    },
    placeholder: {
      type: String,
      default: '添加员工'
    },
    /** 获取不同的员工展示列表 */
    infoType: {
      type: String,
      default: 'default' // 返回全部  crm_contract crm_receivables oa_examine 合同审核人自选列表
    },
    /** 请求辅助参数 */
    infoParams: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data () {
    return {
      showPopover: false, // 展示popover
      showSelectView: false // 展示选择内容列表
    }
  },
  computed: {},
  watch: {},
  mounted () {},
  methods: {
    /** 选中 */
    checkUsers (data) {
      this.dataValue = data.data
      this.$emit('value-change', {
        item: this.item,
        index: this.index,
        value: data.data
      })
    },
    /** 删除 */
    deleteuser (index) {
      if (this.$refs.xhuser) {
        this.$refs.xhuser.cancelCheckItem(this.dataValue[index])
      }
      this.dataValue.splice(index, 1)
      this.$emit('value-change', {
        item: this.item,
        index: this.index,
        value: this.dataValue
      })
    },
    /** 聚焦动作 */
    focusClick () {
      this.showSelectView = true
      this.$emit('focus')
    }
  }
}
</script>
<style lang="less" scoped>
.user-container {
  min-height: 34px;
  margin: 3px 0;
  position: relative;
  border-radius: 3px;
  font-size: 12px;
  border: 1px solid #ddd;
  color: #333333;
  padding: 0.5px;
  line-height: 15px;
  max-height: 105px;
  overflow-y: auto;
  .user-item {
    padding: 5px;
    background-color: #e2ebf9;
    border-radius: 3px;
    margin: 3px;
    cursor: pointer;
  }
  .add-item {
    padding: 5px;
    color: #4D88FF;
    cursor: pointer;
  }
  .delete-icon {
    color: #999;
    cursor: pointer;
  }
  &:hover {
    border-color: #c0c4cc;
  }
}
.user-container.is_disabled {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  cursor: not-allowed;
  .user-item {
    background-color: #f0f4f8ea;
    color: #c0c4cc;
    cursor: not-allowed;
  }
  .delete-icon {
    color: #c0c4cc;
    cursor: not-allowed;
  }
  .add-item {
    color: #c0c4cc;
    cursor: not-allowed;
  }
}
.user-container.is_valid:hover {
  border-color: #c0c4cc;
}
</style>
src/components/CreateCom/arrayMixin.js
New file
@@ -0,0 +1,44 @@
/** 自定义组件 共同逻辑 */
export default {
  data () {
    return {
      dataValue: []
    }
  },
  watch: {
    value: function (val) {
      this.dataValue = val
    }
  },
  props: {
    value: {
      type: Array,
      default: () => {
        return []
      }
    },
    /** 索引值 用于更新数据 */
    index: Number,
    /** 包含数据源 */
    item: Object,
    disabled: {
      type: Boolean,
      default: false
    }
  },
  mounted () {
    this.dataValue = this.value
  },
  methods: {
    // 输入的值
    valueChange (val) {
      this.$emit('value-change', {
        index: this.index,
        value: val
      })
    }
  }
}
src/components/CreateCom/index.js
New file
@@ -0,0 +1,21 @@
export { default as XhInput } from './XhInput'
export { default as XhTextarea } from './XhTextarea'
export { default as XhSelect } from './XhSelect'
export { default as XhMultipleSelect } from './XhMultipleSelect'
export { default as XhDate } from './XhDate'
export { default as XhDateTime } from './XhDateTime'
export { default as XhUser } from './XhUser'
export { default as XhUserCell } from './XhUserCell'
export { default as XhStructureCell } from './XhStructureCell'
export { default as XhFiles } from './XhFiles'
export { default as CrmRelativeCell } from './CrmRelativeCell'
export { default as XhProuctCate } from './XhProuctCate'
export { default as XhProduct } from './XhProduct'
export { default as XhBusinessStatus } from './XhBusinessStatus'
export { default as XhCustomerAddress } from './XhCustomerAddress'
export { default as XhStrucUserCell } from './XhStrucUserCell'
export { default as XhReceivablesPlan } from './XhReceivablesPlan'
export { default as XhRelativeInput } from './XhRelativeInput'
export { default as XhRelativeInputS } from './XhRelativeInputS'
export { default as XhInputSelect } from './XhInputSelect'
src/components/CreateCom/objMixin.js
New file
@@ -0,0 +1,42 @@
/** 自定义组件 共同逻辑 */
export default {
  data () {
    return {
      dataValue: []
    }
  },
  watch: {
  },
  props: {
    // value: {
    //   type: Object,
    //   default: () => {
    //     return {}
    //   }
    // },
    /** 索引值 用于更新数据 */
    index: Number,
    /** 包含数据源 */
    item: Object,
    disabled: {
      type: Boolean,
      default: false
    }
  },
  mounted () {
    /** 如果有值以传入值为主 如果无值 已默认值为主 */
    // this.dataValue = this.value
  },
  methods: {
    // 输入的值
    valueChange (val) {
      this.$emit('value-change', {
        index: this.index,
        value: val
      })
    }
  }
}
src/components/CreateCom/stringMixin.js
New file
@@ -0,0 +1,49 @@
/** 自定义组件 共同逻辑 */
export default {
  data () {
    return {
      dataValue: ''
    }
  },
  watch: {
    value: function (val) {
      this.dataValue = val
    }
  },
  props: {
    value: {
      type: [String, Number],
      default: ''
    },
    /** 索引值 用于更新数据 */
    index: Number,
    /** 包含数据源 */
    item: Object,
    disabled: {
      type: Boolean,
      default: false
    }
  },
  mounted () {
    /** 如果有值以传入值为主 如果无值 已默认值为主 */
    this.dataValue = this.value
  },
  methods: {
    // 输入的值
    valueChange (val, planList = []) {
      const data = {
        index: this.index,
        value: val
      }
      if (planList.length > 0) {
        data.plan = planList.filter(item => {
          return item.planId === this.dataValue
        })[0]
      }
      this.$emit('value-change', data)
    }
  }
}
src/components/CreateSections.vue
New file
@@ -0,0 +1,72 @@
<template>
  <div class="section">
    <div
      v-if="title && title.length > 0"
      class="section-header">
      <div
        :style="{ 'border-left-color': mColor }"
        class="section-mark"/>
      <div class="section-title">{{ title }}</div>
      <slot name="header"/>
    </div>
    <div class="content">
      <slot/>
    </div>
  </div>
</template>
<script type="text/javascript">
export default {
  name: 'CreateSections',
  components: {},
  props: {
    title: {
      type: String,
      default: ''
    },
    mColor: {
      type: String,
      default: '#4D88FF'
    }
  },
  data () {
    return {}
  },
  computed: {},
  mounted () {},
  methods: {}
}
</script>
<style lang="less" scoped>
.section {
  position: relative;
  background-color: white;
  margin-top: 8px;
}
.section:first-child {
  margin-top: 0;
}
.section-mark {
  border-left-width: 2px;
  border-left-style: solid;
  height: 16px;
}
.section-header {
  display: flex;
  align-items: center;
  padding: 5px 15px;
  margin-bottom: 30px;
}
.section-title {
  font-size: 18px;
  color: #333;
  margin-left: 8px;
  flex-shrink: 0;
  font-weight: 550;
}
.content {
  padding: 0 10px;
}
</style>
src/components/CreateView.vue
New file
@@ -0,0 +1,83 @@
<template>
  <transition name="opacity-fade">
    <div
      :style="{ 'background-color': backgroundColor, 'padding': padding+' 0', 'z-index': zIndex }"
      class="c-view">
      <el-card
        v-loading="loading"
        :style="{ 'width': width}"
        :body-style="bodyStyle"
        class="crm-create-card-container">
        <slot name="header"/>
        <slot/>
      </el-card>
    </div>
  </transition>
</template>
<script type="text/javascript">
import { getMaxIndex } from '@/utils/index'
export default {
  name: 'CreateView', // 所有新建效果的view
  components: {},
  props: {
    bodyStyle: {
      type: Object,
      default: () => {
        return {}
      }
    },
    loading: {
      type: Boolean,
      default: false
    },
    // 更改背景颜色颜色
    backgroundColor: {
      type: String,
      default: '#F5F6F9' // rgba(0, 0, 0, 0.6) 黑色半透明
    },
    /** 展示内容的宽 */
    width: {
      type: String,
      default: '1046px'
    },
    /** 展示内容的上下padding */
    padding: {
      type: String,
      default: '40px'
    }
  },
  data () {
    return {
      zIndex: getMaxIndex(),
      loadingObj: null
    }
  },
  computed: {},
  watch: {},
  mounted () {},
  methods: {}
}
</script>
<style lang="less" scoped>
.opacity-fade-enter-active,
.opacity-fade-leave-active {
  transition: all 0.2s;
}
.opacity-fade-enter,
.opacity-fade-leave-to {
  opacity: 0;
}
/** 容器布局 */
.c-view {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
}
.crm-create-card-container {
  margin: 0 auto;
  height: 100%;
}
</style>
src/components/DetailCell.vue
New file
@@ -0,0 +1,84 @@
<template>
  <div class="cell">
    <div class="div-flex">
      <div style="flex:1;">
        <div class="cell-title">{{ title }}</div>
        <div class="cell-detail">{{ detail }}</div>
      </div>
      <div style="flex-shrink:0;">
        <slot name="value"/>
        <div class="cell-time">{{ time }}</div>
      </div>
    </div>
  </div>
</template>
<script type="text/javascript">
export default {
  name: 'DetailsCell', // 标题  详情  时间 常用布局
  components: {},
  props: {
    title: {
      type: String,
      default: ''
    },
    detail: {
      type: String,
      default: ''
    },
    time: {
      type: String,
      default: ''
    }
  },
  data () {
    return {}
  },
  computed: {},
  mounted () {},
  methods: {}
}
</script>
<style lang="less" scoped>
.cell {
  padding: 10px 15px;
  position: relative;
  background-color: white;
}
.cell:before {
  content: ' ';
  position: absolute;
  top: 0;
  right: 0;
  height: 1px;
  border-top: 1px solid #e5e5e5;
  color: #e5e5e5;
  -webkit-transform-origin: 0 0;
  transform-origin: 0 0;
  -webkit-transform: scaleY(0.5);
  transform: scaleY(0.5);
  left: 15px;
  z-index: 2;
}
.cell:first-child:before {
  display: none;
}
.div-flex {
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
}
.cell-title {
  color: #333333;
  font-size: 13px;
}
.cell-detail {
  color: #999999;
  font-size: 12px;
  margin-top: 8px;
}
.cell-time {
  color: #333333;
  font-size: 13px;
}
</style>
src/components/EditImage.vue
New file
@@ -0,0 +1,156 @@
<template>
  <el-dialog
    v-loading="loading"
    :title="title"
    :width="width"
    :append-to-body="true"
    :visible.sync="showDialog"
    @close="hiddenView">
    <flexbox class="content">
      <div class="cropper-box">
        <vueCropper
          ref="cropper"
          :can-move="true"
          :auto-crop="true"
          :fixed="true"
          :fixed-number="fixedNumber"
          :img="cropperImg"
          output-type="png"
          @realTime="realTime"/>
      </div>
      <div class="preview">
        <div class="preview-name">预览</div>
        <img
          :style="{'width': previewWidth, 'height': previewHeight, 'border-radius': previewRadius}"
          :src="previewImg"
          class="preview-img" >
      </div>
    </flexbox>
    <div
      slot="footer"
      class="dialog-footer">
      <el-button
        type="primary"
        @click="submiteImage()">{{ saveButtonTitle }}</el-button>
    </div>
  </el-dialog>
</template>
<script type="text/javascript">
import { VueCropper } from 'vue-cropper'
export default {
  name: 'EditImage', // 处理头像
  components: {
    VueCropper
  },
  props: {
    width: {
      type: String,
      default: '450px'
    },
    title: {
      type: String,
      default: '编辑头像'
    },
    saveButtonTitle: {
      type: String,
      default: '开始上传'
    },
    show: {
      type: Boolean,
      default: false
    },
    fixedNumber: {
      type: Array,
      default: () => {
        return [1, 1]
      }
    },
    previewWidth: {
      type: String,
      default: '70px'
    },
    previewHeight: {
      type: String,
      default: '70px'
    },
    previewRadius: {
      type: String,
      default: '35px'
    },
    file: [File],
    image: String
  },
  data () {
    return {
      loading: false,
      showDialog: false,
      cropperImg: '',
      previewImg: ''
    }
  },
  computed: {},
  watch: {
    show: {
      handler (val) {
        this.showDialog = val
      },
      deep: true,
      immediate: true
    },
    image: function (val) {
      this.cropperImg = val
    }
  },
  mounted () {
    this.cropperImg = this.image
  },
  methods: {
    realTime (data) {
      this.$refs.cropper.getCropData(cropperData => {
        this.previewImg = cropperData
      })
    },
    submiteImage () {
      // 获取截图的blob数据
      this.$refs.cropper.getCropBlob(data => {
        this.$emit('save', {
          blob: data,
          file: this.file,
          image: this.previewImg
        })
        this.hiddenView()
      })
    },
    hiddenView () {
      this.$emit('close')
    }
  }
}
</script>
<style lang="less" scoped>
.cropper-box {
  width: 300px;
  height: 300px;
  margin-right: 15px;
}
.preview {
  position: absolute;
  bottom: 0;
  right: 0;
  .preview-name {
    margin-bottom: 8px;
    font-size: 13px;
    color: #666;
  }
  .preview-img {
    display: block;
  }
}
.content {
  position: relative;
  padding: 0 30px;
}
</style>
src/components/Examine/CheckFlow.vue
New file
@@ -0,0 +1,237 @@
<template>
  <div
    v-loading="loading"
    v-empty="list"
    xs-empty-icon="none"
    xs-empty-text="暂无记录">
    <flexbox class="flow-head">
      <div class="flow-head-name">审批流程</div>
      <img
        class="flow-head-close"
        src="@/assets/img/task_close.png"
        @click="close" >
    </flexbox>
    <div class="flow-body">
      <flexbox
        v-for="(item, index) in list"
        :key="index"
        class="cf-flow-item"
        align="stretch"
        justify="flex-start">
        <img
          :src="item.examineStatus|statusIcon"
          class="cf-flow-item-img" >
        <div>
          <flexbox class="cf-flow-item-head">
            <div class="cf-flow-item-des">{{ item.orderId|stepName }}</div>
            <div>{{ item.examineTime }}</div>
          </flexbox>
          <flexbox class="cf-flow-item-info">
            <div class="cf-flow-item-name">{{ item.realname }}</div>
            <div><span>{{ getStatusName(item.examineStatus) }}</span>了此申请</div>
          </flexbox>
          <div
            v-if="item.remarks"
            class="cf-flow-item-content">{{ item.remarks }}
            <div class="cf-flow-item-content-arrow"/>
          </div>
        </div>
        <div class="cf-flow-item-line"/>
      </flexbox>
    </div>
  </div>
</template>
<script>
// import { crmExamineFlowRecordList } from '@/api/clients/common' // 审批记录
// import { oaExamineFlowRecordList } from '@/api/oamanagement/examine'
import Nzhcn from 'nzh/cn'
export default {
  /** 客户管理 的 合同详情  查看审批流程 */
  name: 'CheckFlow',
  components: {},
  filters: {
    statusIcon: function (status) {
      // 0失败,1通过,2撤回,3创建,4待审核
      // JAVA 0 未审核 1 审核通过 2 审核拒绝 3 审核中 4 已撤回 5 创建 6 待提交
      // if (status === 2) {
      //   return require('@/assets/img/check_fail.png')
      // } else if (status === 1) {
      //   return require('@/assets/img/check_suc.png')
      // } else if (status === 4) {
      //   return require('@/assets/img/check_revoke.png')
      // } else if (status === 3) {
      //   return require('@/assets/img/check_create.png')
      // } else if (status === 0 || status === 6) {
      //   return require('@/assets/img/check_wait.png')
      // } else if (status === 5) {
      //   return require('@/assets/img/check_create.png')
      // }
      return ''
    },
    stepName: function (index) {
      return '第' + Nzhcn.encodeS(index) + '级'
    }
  },
  props: {
    examineType: {
      type: String,
      default: ''
    },
    // 详情信息id
    id: [String, Number]
  },
  data () {
    return {
      loading: false,
      list: []
    }
  },
  computed: {},
  watch: {
    id: function (val) {
      if (val) {
        this.list = []
        this.getDetail()
      }
    }
  },
  mounted () {},
  methods: {
    getDetail () {
      if (this.id) {
        this.loading = true
        const request = {
          // crm_contract: crmExamineFlowRecordList,
          // crm_receivables: crmExamineFlowRecordList,
          // oa_examine: oaExamineFlowRecordList
        }[this.examineType]
        request({
          recordId: this.id
        })
          .then(res => {
            this.loading = false
            this.list = res.data
            // this.$emit('value-change', {
            //   config: res.data.config, // 审批类型
            //   value: [] // 审批信息
            // })
          })
          .catch(() => {
            this.loading = false
          })
      }
    },
    // 获取状态名称
    getStatusName (status) {
      // 0拒绝,1通过,2撤回,3创建,4待审核
      if (status === 0) {
        return '未审核 '
      } else if (status === 1) {
        return '通过'
      } else if (status === 2) {
        return '拒绝'
      } else if (status === 3) {
        return '审核中'
      } else if (status === 4) {
        return '撤回'
      } else if (status === 5) {
        return '创建'
      } else if (status === 6) {
        return '待提交'
      }
      return ''
    },
    close () {
      this.$emit('close')
    }
  }
}
</script>
<style lang="less" scoped>
/** 头部的css */
.flow-head {
  padding: 8px 15px;
  border-bottom: 1px solid #e6e6e6;
  .flow-head-name {
    font-size: 14px;
    color: #333;
    flex: 1;
  }
  .flow-head-name {
    display: block;
    width: 30px;
    height: 30px;
  }
  .flow-head-close {
    cursor: pointer;
    width: 30px;
    height: 30px;
    padding: 8px;
  }
}
.flow-body {
  padding: 15px;
}
/** 每行的css */
.cf-flow-item {
  position: relative;
  padding-bottom: 15px;
  .cf-flow-item-img {
    display: block;
    background-color: white;
    width: 16px;
    height: 16px;
    border-radius: 8px;
    margin-right: 10px;
  }
  .cf-flow-item-head {
    color: #bababa;
    font-size: 12px;
    .cf-flow-item-des {
      margin-right: 10px;
    }
  }
  .cf-flow-item-info {
    margin-top: 8px;
    font-size: 12px;
    color: #979797;
    .cf-flow-item-name {
      color: #333;
      margin-right: 10px;
    }
  }
  .cf-flow-item-line {
    position: absolute;
    z-index: -1;
    width: 1px;
    top: 0px;
    bottom: 0px;
    left: 8px;
    background-color: #e6e6e6;
  }
  .cf-flow-item-content {
    position: relative;
    margin-top: 15px;
    border-radius: 4px;
    background-color: #f7f8fa;
    font-size: 12px;
    color: #929293;
    padding: 8px;
    line-height: 18px;
    .cf-flow-item-content-arrow {
      width: 8px;
      height: 8px;
      background-color: #f7f8fa;
      transform: rotate(45deg);
      position: absolute;
      top: -4px;
      left: 25px;
    }
  }
}
</style>
src/components/Examine/CreateExamineInfo.vue
New file
@@ -0,0 +1,244 @@
<template>
  <div>
    <el-form
      v-if="examineInfo.examineType === 2"
      ref="form"
      :model="form"
      :rules="rules"
      label-position="top"
      class="crm-create-box">
      <el-form-item
        prop="name"
        class="crm-create-item">
        <div
          slot="label"
          style="display: inline-block;">
          <div style="margin:5px 0;font-size:12px;word-wrap:break-word;word-break:break-all;">
            审核人
            <span style="color:#999;"/>
          </div>
        </div>
        <xh-user-cell
          :info-type="types"
          :value="draftUser ? [draftUser] : []"
          @value-change="fieldValueChange"/>
      </el-form-item>
    </el-form>
    <flexbox
      v-else-if="examineInfo.examineType === 1"
      class="fixed-examine"
      wrap="wrap">
      <el-popover
        v-for="(item, index) in examineInfo.examineSteps"
        :key="index"
        :disabled="item.userList.length==0"
        :content="item.userList|contentFilters"
        placement="bottom"
        trigger="hover">
        <div
          slot="reference"
          class="fixed-examine-item">
          <img src="@/assets/img/examine_head.png" >
          <div class="detail">{{ item|detail }}</div>
          <div class="step">{{ (index+1)|step }}</div>
        </div>
      </el-popover>
    </flexbox>
  </div>
</template>
<script type="text/javascript">
// import { crmCreateExamineFlow } from '@/api/clients/common'
// import { oaCreateExamineFlow } from '@/api/oamanagement/examine'
import { XhUserCell } from '@/components/CreateCom'
// import Nzhcn from 'nzh/cn'
export default {
  name: 'CreateExamineInfo',
  components: {
    XhUserCell
  },
  filters: {
    detail: function (data) {
      if (data.stepType === 2) {
        return data.userList.length + '人或签'
      } else if (data.stepType === 3) {
        return data.userList.length + '人会签'
      } else if (data.stepType === 1) {
        return '负责人主管'
      } else if (data.stepType === 4) {
        return '上一级审批人主管'
      }
    },
    step: function (index) {
      // return '第' + Nzhcn.encodeS(index) + '级'
    },
    contentFilters: function (array) {
      return array
        .map(item => {
          return item.realname
        })
        .join('、')
    }
  },
  props: {
    // CRM类型
    types: {
      type: String,
      default: ''
    },
    // 办公审批 传ID
    typesId: {
      type: [String, Number],
      default: ''
    }
  },
  data () {
    return {
      form: {
        name: ''
      },
      rules: {
        name: [{ required: true, message: '审批人不能为空', trigger: 'blur' }]
      },
      // 审核信息 examineType 1 固定审批 2 授权审批
      examineInfo: {},
      draftUser: null
    }
  },
  computed: {},
  mounted () {
    this.getDetail()
  },
  methods: {
    getDetail () {
      // const reqeust = {
      //   oa_examine: oaCreateExamineFlow,
      //   crm_contract: crmCreateExamineFlow,
      //   crm_receivables: crmCreateExamineFlow
      // }[this.types]
      const params = {}
      if (this.types === 'oa_examine') {
        params.categoryId = this.typesId
      } else {
        params.id = this.typesId
        params.categoryType = this.types === 'crm_contract' ? 1 : 2 // 1 合同 2 回款
      }
      // reqeust(params)
      //   .then(res => {
      //     this.examineInfo = res.data
      //     if (res.data.examineType === 2 && res.data.examineUser) {
      //       this.draftUser = {
      //         realname: res.data.examineUserName,
      //         userId: res.data.examineUser
      //       }
      //       this.form.name = res.data.examineUserName
      //       this.$emit('value-change', {
      //         examineType: res.data.examineType, // 审批类型
      //         value: [this.draftUser] // 审批信息
      //       })
      //     } else {
      //       this.form.name = ''
      //       this.draftUser = null
      //       this.$emit('value-change', {
      //         examineType: res.data.examineType, // 审批类型
      //         value: [] // 审批信息
      //       })
      //     }
      //   })
      //   .catch(() => {})
    },
    validateField (result) {
      if (this.examineInfo.examineType === 2) {
        // 授权审批人 需要验证关联人
        this.$refs.form.validate(valid => {
          if (valid) {
            result() // 成功回调
          } else {
            return false
          }
        })
      } else {
        result() // 成功回调
      }
    },
    // 字段的值更新
    fieldValueChange (data) {
      if (data.value.length) {
        this.draftUser = data.value[0]
        this.form.name = this.draftUser.userId
      } else {
        this.draftUser = null
        this.form.name = ''
      }
      this.$emit('value-change', {
        examineType: this.examineInfo.examineType, // 审批类型
        value: data.value // 审批信息
      })
      this.$refs.form.validateField('name')
    }
  }
}
</script>
<style lang="less" scoped>
/** 将其改变为flex布局 */
.crm-create-box {
  display: flex;
  flex-wrap: wrap;
  padding: 0 10px;
}
.crm-create-item {
  flex: 0 0 45%;
  flex-shrink: 0;
  // overflow: hidden;
  padding-bottom: 10px;
}
.el-form-item /deep/ .el-form-item__label {
  line-height: normal;
  font-size: 13px;
  color: #333333;
  position: relative;
  padding-left: 8px;
  padding-bottom: 0;
}
.el-form /deep/ .el-form-item {
  margin-bottom: 0px;
}
.el-form /deep/ .el-form-item.is-required .el-form-item__label:before {
  content: '*';
  color: #f56c6c;
  margin-right: 4px;
  position: absolute;
  left: 0;
  top: 5px;
}
// 固定审批信息
.fixed-examine {
  padding: 0px 10px;
  text-align: center;
  .fixed-examine-item {
    padding: 10px 20px;
    img {
      width: 40px;
      height: 40px;
    }
    .detail {
      color: #777777;
      font-size: 12px;
      padding: 2px 0;
      transform: scale(0.8, 0.8);
    }
    .step {
      color: #333333;
      font-size: 12px;
    }
  }
}
</style>
src/components/Examine/ExamineHandle.vue
New file
@@ -0,0 +1,246 @@
<template>
  <el-dialog
    v-loading="loading"
    :title="title"
    :append-to-body="true"
    :visible.sync="showDialog"
    width="400px"
    @close="hiddenView">
    <div
      v-if="status === 1 && detail.examineType === 2"
      class="handle-type">
      <flexbox class="handle-item">
        <el-radio
          v-model="handleType"
          :label="1"><span/></el-radio>
        <div
          style="font-size: 12px;"
          @click.native="handleType=1">审核结束</div>
      </flexbox>
      <flexbox
        id="selectUser"
        class="handle-item">
        <el-radio
          v-model="handleType"
          :label="2"><span/></el-radio>
        <xh-user-cell
          class="select-user"
          placeholder="选择下一审批人"
          @focus="selectUserFocus"
          @value-change="selectExamineUser"/>
      </flexbox>
    </div>
    <div
      v-if="status === 1 && detail.examineType === 2"
      class="title">意见</div>
    <el-input
      v-model="content"
      :rows="5"
      :maxlength="200"
      :placeholder="placeholder"
      type="textarea"
      resize="none"
      show-word-limit/>
    <div
      slot="footer"
      class="dialog-footer">
      <el-button @click="handleClick('cancel')">取 消</el-button>
      <el-button
        type="primary"
        @click="handleClick('confirm')">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script type="text/javascript">
// import { crmExamineFlowAuditExamine } from '@/api/clients/common'
// import { oaExamineFlowAuditExamine } from '@/api/oamanagement/examine'
import { XhUserCell } from '@/components/CreateCom'
export default {
  name: 'ExamineHandle', // 合同审核操作
  components: {
    XhUserCell
  },
  props: {
    show: {
      type: Boolean,
      default: false
    }, // 审核状态 1 审核通过 2 审核拒绝 4 已撤回
    /** 操作类型  1通过0拒绝2撤回 */ status: {
      type: [String, Number],
      default: 1
    },
    // 详情信息id
    id: [String, Number],
    recordId: [String, Number],
    // 审核信息 config 1 固定 0 自选
    detail: {
      type: Object,
      default: () => {
        return {}
      }
    },
    // crm_contract crm_receivables oa_examine
    examineType: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      loading: false,
      showDialog: false,
      handleType: 1,
      selectUsers: [],
      content: '' // 输入内容
    }
  },
  computed: {
    title () {
      if (this.status === 1) {
        return '审批通过'
      } else if (this.status === 2) {
        return '审批拒绝'
      } else if (this.status === 4) {
        return '撤回审批'
      }
      return ''
    },
    placeholder () {
      // 1 审核通过 2 审核拒绝 4 已撤回
      if (this.status === 1) {
        return '请输入审批意见(选填)'
      } else if (this.status === 2) {
        return '请输入审批意见(必填)'
      } else if (this.status === 4) {
        return '请输入撤回理由(必填)'
      }
      return ''
    }
  },
  watch: {
    show: {
      handler (val) {
        this.showDialog = val
      },
      deep: true,
      immediate: true
    }
  },
  mounted () {},
  methods: {
    submitInfo () {
      if ((this.status === 2 || this.status === 4) && !this.content) {
        this.$message.error(this.placeholder)
      } else {
        if (this.status === 2 || this.status === 1) {
          // 1通过0拒绝2撤回
          this.handlePassAndReject()
        } else if (this.status === 4) {
          this.handleRevoke()
        }
      }
    },
    // 撤回操作
    handleRevoke () {
      this.loading = true
      this.getRequest()({
        id: this.id,
        recordId: this.recordId,
        status: this.status,
        remarks: this.content
      })
        .then(res => {
          this.loading = false
          this.$message.success('操作成功')
          this.$emit('save')
          this.$bus.emit('examine-handle-bus')
          this.$store.dispatch('GetMessageNum')
          this.hiddenView()
        })
        .catch(() => {
          this.loading = false
        })
    },
    getRequest () {
      return {
        // crm_contract: crmExamineFlowAuditExamine,
        // crm_receivables: crmExamineFlowAuditExamine,
        // oa_examine: oaExamineFlowAuditExamine
      }[this.examineType]
    },
    // 通过 拒绝操作
    handlePassAndReject () {
      this.loading = true
      var params = {
        id: this.id,
        recordId: this.recordId,
        status: this.status,
        remarks: this.content
      }
      if (this.status === 1 && this.detail.examineType === 2) {
        if (this.handleType !== 1) {
          params['nextUserId'] = this.selectUsers[0].userId
        }
      }
      this.getRequest()(params)
        .then(res => {
          this.loading = false
          this.$message.success('操作成功')
          this.$emit('save', { type: this.status })
          this.hiddenView()
          this.$bus.emit('examine-handle-bus')
          this.$store.dispatch('GetMessageNum')
        })
        .catch(() => {
          this.loading = false
        })
    },
    handleClick (type) {
      if (type === 'cancel') {
        this.hiddenView()
      } else if (type === 'confirm') {
        this.submitInfo()
      }
    },
    /** 选择了下一审批人 */
    selectUserFocus () {
      this.handleType = 2
    },
    selectExamineUser (data) {
      this.selectUsers = data.value
    },
    hiddenView () {
      this.$emit('close')
    }
  }
}
</script>
<style lang="less" scoped>
.handle-type {
  padding-bottom: 8px;
  .handle-item {
    padding: 8px 0;
    cursor: pointer;
  }
}
.el-dialog__wrapper /deep/ .el-dialog__body {
  padding: 10px 25px 20px;
}
.el-radio-group /deep/ .el-radio + .el-radio {
  margin-left: 0px;
}
.select-user {
  flex: 1;
}
.title {
  font-size: 12px;
  padding-bottom: 8px;
  color: #666;
}
</style>
src/components/Examine/ExamineInfo.vue
New file
@@ -0,0 +1,443 @@
<template>
  <div
    v-loading="loading"
    class="contract-flow-box">
    <flexbox
      direction="row-reverse"
      style="position:relative;">
      <el-popover
        v-model="showFlowPopover"
        placement="bottom"
        width="300"
        trigger="click">
        <check-flow
          ref="checkFlow"
          :id="recordId"
          :examine-type="examineType"
          @close="showFlowPopover=false"/>
        <el-button
          slot="reference"
          class="check-flow-button"
          type="text">查看审批历史</el-button>
      </el-popover>
      <div style="min-height: 40px;">
        <el-button
          v-if="examineInfo.isRecheck==1"
          class="flow-button white"
          @click="examineHandle(4)">撤回审核</el-button>
        <el-button
          v-if="examineInfo.isCheck==1"
          class="flow-button red"
          @click="examineHandle(2)">拒绝</el-button>
        <el-button
          v-if="examineInfo.isCheck==1"
          class="flow-button blue"
          @click="examineHandle(1)">通过</el-button>
      </div>
    </flexbox>
    <flexbox
      v-if="examineInfo.examineType === 2"
      class="check-items">
      <flexbox
        v-for="(item, index) in examineInfo.steps"
        :key="index"
        class="check-item">
        <div>
          <flexbox
            class="check-item-user"
            style="width:auto;">
            <div
              v-photo="item.examinUser"
              v-lazy:background-image="$options.filters.filterUserLazyImg(item.examinUser.img)"
              class="div-photo check-item-img"/>
            <div class="check-item-name">{{ item.examinUser.realname }}</div>
          </flexbox>
          <flexbox class="check-item-info">
            <img
              :src="item.examineStatus|statusIcon"
              class="check-item-img">
            <div class="check-item-name">{{ getStatusName(item.examineStatus) }}</div>
          </flexbox>
        </div>
        <i
          v-if="examineInfo.steps.length -1 !== index"
          class="el-icon-arrow-right check-item-arrow"/>
      </flexbox>
    </flexbox>
    <flexbox
      v-else-if="examineInfo.examineType === 1"
      class="check-items"
      wrap="wrap">
      <el-popover
        v-for="(item, index) in examineInfo.steps"
        :key="index"
        :disabled="!item.userList || item.userList.length==0"
        placement="bottom"
        trigger="hover">
        <div class="popover-detail">
          <flexbox
            v-for="(subItem, subIndex) in item.userList"
            :key="subIndex"
            align="stretch"
            class="popover-detail-item">
            <img
              :src="subItem.examineStatus|statusIcon"
              class="popover-detail-item-img">
            <div>
              <div class="popover-detail-item-time">{{ subItem.examineTime }}</div>
              <flexbox class="popover-detail-item-examine">
                <div class="examine-name">{{ subItem.realname }}</div>
                <div class="examine-info">{{ getStatusName(subItem.examineStatus) }}此申请</div>
              </flexbox>
            </div>
          </flexbox>
        </div>
        <flexbox
          slot="reference"
          class="fixed-examine-item">
          <div class="fixed-examine-info">
            <img src="@/assets/img/examine_head.png" >
            <div class="detail">{{ item|detailName }}</div>
            <flexbox class="check-item-info">
              <img
                :src="item.examineStatus|statusIcon"
                class="check-item-img">
              <div class="check-item-name">{{ getStatusName(item.examineStatus) }}</div>
            </flexbox>
          </div>
          <i
            v-if="examineInfo.steps.length -1 !== index"
            class="el-icon-arrow-right check-item-arrow"/>
        </flexbox>
      </el-popover>
    </flexbox>
    <examine-handle
      :show="showExamineHandle"
      :id="id"
      :record-id="recordId"
      :examine-type="examineType"
      :detail="examineInfo"
      :status="examineHandleInfo.status"
      @close="showExamineHandle = false"
      @save="examineHandleClick"/>
  </div>
</template>
<script type="text/javascript">
// import { crmExamineFlowStepList } from '@/api/clients/common' // 审批步骤
// import { oaExamineFlowStepList } from '@/api/oamanagement/examine'
import Nzhcn from 'nzh/cn'
import ExamineHandle from './ExamineHandle' // 审批操作理由
import CheckFlow from './CheckFlow' // 审批流程
// 审核信息 config 1 固定 0 自选
export default {
  name: 'ExamineInfo', // 合同审核操作
  components: {
    ExamineHandle,
    CheckFlow
  },
  filters: {
    statusIcon: function (status) {
      // 0失败,1通过,2撤回,3创建,4待审核
      // JAVA 0 未审核 1 审核通过 2 审核拒绝 3 审核中 4 已撤回 5 创建 6 待提交
      if (status === 2) {
        return require('@/assets/img/check_fail.png')
      } else if (status === 1) {
        return require('@/assets/img/check_suc.png')
      } else if (status === 4) {
        return require('@/assets/img/check_revoke.png')
      } else if (status === 3) {
        return require('@/assets/img/check_create.png')
      } else if (status === 0 || status === 6) {
        return require('@/assets/img/check_wait.png')
      } else if (status === 5) {
        return require('@/assets/img/check_create.png')
      }
      return ''
    },
    detailName: function (data) {
      if (data.stepType === 2) {
        return data.userList.length + '人或签'
      } else if (data.stepType === 3) {
        return data.userList.length + '人会签'
      } else if (data.stepType === 1) {
        return '负责人主管'
      } else if (data.stepType === 4) {
        return '上一级审批人主管'
      } else if (data.stepType === 5) {
        return '创建人'
      }
    },
    stepName: function (index) {
      return '第' + Nzhcn.encodeS(index) + '级'
    }
  },
  props: {
    examineType: {
      type: String,
      default: ''
    },
    // 详情信息id
    id: [String, Number],
    // 审批流id
    recordId: [String, Number],
    ownerUserId: [String, Number]
  },
  data () {
    return {
      loading: false,
      examineInfo: {}, // 审核信息
      showFlowPopover: false,
      examineHandleInfo: { status: 1 }, // 1 审核通过 2 审核拒绝 4 已撤回
      showExamineHandle: false // 审核操作
    }
  },
  computed: {},
  watch: {
    recordId: {
      handler (val) {
        if (val) {
          this.examineInfo = {}
          this.getFlowStepList()
          if (this.$refs.checkFlow) {
            this.$refs.checkFlow.getDetail()
          }
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted () {},
  methods: {
    getFlowStepList () {
      if (!this.recordId || !this.id) {
        return
      }
      this.loading = true
      // const request = {
      //   crm_contract: crmExamineFlowStepList,
      //   crm_receivables: crmExamineFlowStepList,
      //   oa_examine: oaExamineFlowStepList
      // }[this.examineType]
      // request({
      //   recordId: this.recordId,
      //   ownerUserId: this.ownerUserId
      // })
      //   .then(res => {
      //     this.loading = false
      //     this.examineInfo = res.data
      //     this.$emit('value-change', {
      //       config: res.data.examineType, // 审批类型
      //       value: [] // 审批信息
      //     })
      //   })
      //   .catch(() => {
      //     this.loading = false
      //   })
    },
    // 撤回审核 通过 拒绝
    examineHandle (status) {
      this.examineHandleInfo.status = status
      this.showExamineHandle = true
    },
    // 获取状态名称
    getStatusName (status) {
      if (status === 0) {
        return '未审核'
      } else if (status === 1) {
        return '通过'
      } else if (status === 2) {
        return '拒绝'
      } else if (status === 3) {
        return '审核中'
      } else if (status === 4) {
        return '撤回'
      } else if (status === 5) {
        return '创建'
      } else if (status === 6) {
        return '待提交'
      }
      return ''
    },
    getContentFilters (array) {
      var content = ''
      for (let index = 0; index < array.length; index++) {
        const item = array[index]
        if (index === array.length - 1) {
          content =
            content + item.realname + ':' + this.getStatusName(item.checkType)
        } else {
          content =
            content +
            item.realname +
            ':' +
            this.getStatusName(item.checkType) +
            '、'
        }
      }
      return content
    },
    // 审批操作点击
    examineHandleClick (data) {
      this.getFlowStepList()
      if (this.$refs.checkFlow) {
        this.$refs.checkFlow.getDetail()
      }
      this.$emit('on-handle', data)
    }
  }
}
</script>
<style lang="less" scoped>
.contract-flow-box {
  position: relative;
  min-height: 100px;
}
.flow-button {
  width: 75px;
  height: 30px;
  border-radius: 2px;
  margin: 5px;
  font-size: 13px;
}
.blue {
  background-color: #4D88FF;
  color: white;
  border: none;
}
.red {
  background-color: #ff6767;
  color: white;
  border: none;
}
.white {
  background-color: white;
  color: #777;
}
.check-flow-button {
  font-size: 13px;
  position: absolute;
  left: 0;
  top: 5px;
}
/** 审核流程 */
.check-items {
  overflow-x: auto;
  padding: 10px 0;
}
.check-item {
  width: auto;
  flex-shrink: 0;
  .check-item-user {
    width: auto;
    .check-item-img {
      display: block;
      width: 40px;
      height: 40px;
      border-radius: 20px;
      margin-right: 8px;
    }
    .check-item-name {
      color: #333;
      font-size: 15px;
      font-weight: 500;
    }
  }
  .check-item-info {
    width: auto;
    margin-top: 5px;
    .check-item-img {
      display: block;
      width: 16px;
      height: 16px;
      border-radius: 8px;
      margin-right: 8px;
    }
    .check-item-name {
      color: #aaa;
      font-size: 12px;
    }
  }
  .check-item-arrow {
    color: #ccc;
    margin: 0 16px;
    font-size: 20px;
    font-weight: 600;
  }
}
// 固定审批信息
.fixed-examine-item {
  width: auto;
  flex-shrink: 0;
  .fixed-examine-info {
    padding: 10px 20px;
    text-align: center;
    img {
      width: 40px;
      height: 40px;
    }
    .detail {
      color: #777777;
      font-size: 12px;
      padding: 2px 0;
      transform: scale(0.9, 0.9);
    }
    .check-item-info {
      width: auto;
      margin-top: 5px;
      .check-item-img {
        display: block;
        width: 16px;
        height: 16px;
        border-radius: 8px;
        margin-right: 8px;
      }
      .check-item-name {
        color: #aaa;
        font-size: 12px;
      }
    }
  }
  .check-item-arrow {
    color: #ccc;
    margin: 0 16px;
    font-size: 20px;
    font-weight: 600;
  }
}
.popover-detail {
  padding: 0 5px;
}
.popover-detail-item {
  padding: 5px 0;
  &-img {
    display: block;
    width: 16px;
    height: 16px;
    border-radius: 8px;
    margin-right: 10px;
  }
  &-time {
    color: #bababa;
    font-size: 12px;
  }
  &-examine {
    .examine-name {
      color: #333;
      margin-right: 10px;
    }
    .examine-info {
      color: #666;
    }
  }
}
</style>
src/components/HelloWorld.vue
New file
@@ -0,0 +1,113 @@
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li>
        <a
          href="https://vuejs.org"
          target="_blank"
        >
          Core Docs
        </a>
      </li>
      <li>
        <a
          href="https://forum.vuejs.org"
          target="_blank"
        >
          Forum
        </a>
      </li>
      <li>
        <a
          href="https://chat.vuejs.org"
          target="_blank"
        >
          Community Chat
        </a>
      </li>
      <li>
        <a
          href="https://twitter.com/vuejs"
          target="_blank"
        >
          Twitter
        </a>
      </li>
      <br>
      <li>
        <a
          href="http://vuejs-templates.github.io/webpack/"
          target="_blank"
        >
          Docs for This Template
        </a>
      </li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li>
        <a
          href="http://router.vuejs.org/"
          target="_blank"
        >
          vue-router
        </a>
      </li>
      <li>
        <a
          href="http://vuex.vuejs.org/"
          target="_blank"
        >
          vuex
        </a>
      </li>
      <li>
        <a
          href="http://vue-loader.vuejs.org/"
          target="_blank"
        >
          vue-loader
        </a>
      </li>
      <li>
        <a
          href="https://github.com/vuejs/awesome-vue"
          target="_blank"
        >
          awesome-vue
        </a>
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
src/components/MapView.vue
New file
@@ -0,0 +1,93 @@
<template>
  <div class="map-view">
    <div id="choicemap"/>
    <i
      class="el-icon-close map-close"
      @click="hiddenView"/>
  </div>
</template>
<script type="text/javascript">
import { getMaxIndex } from '@/utils/index'
export default {
  name: 'MapView', // 地图详情
  components: {},
  props: {
    /**
     * title 内容
     * lat lng 经纬度
     */
    title: {
      type: String,
      default: ''
    },
    lat: {
      type: Number,
      default: 0
    },
    lng: {
      type: Number,
      default: 0
    }
  },
  data () {
    return {}
  },
  computed: {},
  mounted () {
    this.$el.style.zIndex = getMaxIndex()
    document.body.appendChild(this.$el)
    let map = new BMap.Map('choicemap', { enableMapClick: false })
    let point = new BMap.Point(this.lng, this.lat)
    map.centerAndZoom(point, 18)
    map.enableScrollWheelZoom()
    let marker = new BMap.Marker(point) // 创建标注
    map.addOverlay(marker) // 将标注添加到地图中
    let infoWindow = new BMap.InfoWindow(this.title) // 创建信息窗口对象
    marker.addEventListener('click', function () {
      map.openInfoWindow(infoWindow, point) // 开启信息窗口
    })
  },
  destroyed () {
    // remove DOM node after destroy
    if (this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el)
    }
  },
  methods: {
    hiddenView () {
      this.$emit('hidden')
    }
  }
}
</script>
<style lang="less" scoped>
.map-view {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-color: #000;
}
.map-close {
  position: absolute;
  right: 10px;
  top: 10px;
  font-size: 28px;
  color: #fff;
  cursor: pointer;
}
#choicemap {
  position: absolute;
  left: 100px;
  top: 100px;
  bottom: 100px;
  right: 100px;
  overflow: hidden;
}
</style>
src/components/SlideView.vue
New file
@@ -0,0 +1,129 @@
<template>
  <transition
    name="slide-fade"
    @after-enter="afterEnter">
      <el-card
        id="slide"
        ref="slide"
        :style="{ 'z-index': zIndex }"
        :body-style="bodyStyle"
        class="slide-detail-card-container">
        <slot/>
      </el-card>
  </transition>
</template>
<script type="text/javascript">
import { getMaxIndex } from '@/utils/index'
export default {
  name: 'SlideView', // 客户管理详情 滑动view
  components: {},
  props: {
    bodyStyle: {
      type: Object,
      default: () => {
        return { padding: 0 }
      }
    },
    /** 监听点击事件 隐藏视图 */
    listenerIDs: {
      type: Array,
      default: () => {
        return []
      }
    },
    /** 阻挡点击事件 隐藏视图 */
    noListenerIDs: {
      type: Array,
      default: () => {
        return []
      }
    },
    noListenerClass: {
      type: Array,
      default: () => {
        return []
      }
    },
    appendToBody: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      zIndex: getMaxIndex()
    }
  },
  computed: {},
  watch: {},
  mounted () {
    if (this.appendToBody) {
      document.body.appendChild(this.$el)
    }
    this.listenerIDs.forEach(element => {
      if (document.getElementById(element)) {
        document
          .getElementById(element)
          .addEventListener('click', this.handleDocumentClick, false)
      }
    })
  },
  beforeDestroy () {
    if (this.appendToBody && this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el)
    }
  },
  methods: {
    handleDocumentClick (e) {
      var hidden = true
      this.noListenerIDs.forEach(element => {
        if (
          document.getElementById(element) &&
          document.getElementById(element).contains(e.target)
        ) {
          hidden = false
        }
      })
      this.noListenerClass.forEach(element => {
        var items = document.getElementsByClassName(element)
        if (items && hidden) {
          for (let index = 0; index < items.length; index++) {
            const element = items[index]
            if (element.contains(e.target)) {
              hidden = false
              break
            }
          }
        }
      })
      if (
        document.getElementById('slide') &&
        document.getElementById('slide').contains(e.target)
      ) {
        hidden = false
      }
      if (hidden) {
        this.$emit('side-close')
      }
    },
    afterEnter () {
      this.$emit('afterEnter')
    }
  }
}
</script>
<style lang="scss" scoped>
// .slide-fade-enter-active,
// .slide-fade-leave-active {
//   will-change: transform;
//   transition: all 0.35s ease;
// }
// .slide-fade-enter,
// .slide-fade-leave-to {
//   transform: translateX(100%);
// }
</style>
src/components/common/SIdentify.vue
New file
@@ -0,0 +1,164 @@
<template>
  <div class="s-canvas">
    <canvas
      id="s-canvas"
      :width="contentWidth"
      :height="contentHeight"
    />
  </div>
</template>
<script>
export default {
  name: 'SIdentify',
  props: {
    identifyCode: {
      type: String,
      default: '1234'
    },
    fontSizeMin: {
      type: Number,
      default: 25
    },
    fontSizeMax: {
      type: Number,
      default: 30
    },
    backgroundColorMin: {
      type: Number,
      default: 255
    },
    backgroundColorMax: {
      type: Number,
      default: 255
    },
    colorMin: {
      type: Number,
      default: 0
    },
    colorMax: {
      type: Number,
      default: 160
    },
    lineColorMin: {
      type: Number,
      default: 100
    },
    lineColorMax: {
      type: Number,
      default: 255
    },
    dotColorMin: {
      type: Number,
      default: 0
    },
    dotColorMax: {
      type: Number,
      default: 255
    },
    contentWidth: {
      type: Number,
      default: 112
    },
    contentHeight: {
      type: Number,
      default: 31
    }
  },
  watch: {
    identifyCode () {
      this.drawPic()
    }
  },
  mounted () {
    this.drawPic()
  },
  methods: {
    // 生成一个随机数
    randomNum (min, max) {
      return Math.floor(Math.random() * (max - min) + min)
    },
    // 生成一个随机的颜色
    randomColor (min, max) {
      const r = this.randomNum(min, max)
      const g = this.randomNum(min, max)
      const b = this.randomNum(min, max)
      return 'rgb(' + r + ',' + g + ',' + b + ')'
    },
    drawPic () {
      const canvas = document.getElementById('s-canvas')
      const ctx = canvas.getContext('2d')
      ctx.textBaseline = 'bottom'
      // 绘制背景
      ctx.fillStyle = this.randomColor(
        this.backgroundColorMin,
        this.backgroundColorMax
      )
      ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)
      // 绘制文字
      for (let i = 0; i < this.identifyCode.length; i++) {
        this.drawText(ctx, this.identifyCode[i], i)
      }
      this.drawLine(ctx)
      this.drawDot(ctx)
    },
    drawText (ctx, txt, i) {
      ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)
      ctx.font =
        this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'
      const x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
      const y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
      var deg = this.randomNum(-45, 45)
      // 修改坐标原点和旋转角度
      ctx.translate(x, y)
      ctx.rotate((deg * Math.PI) / 180)
      ctx.fillText(txt, 0, 0)
      // 恢复坐标原点和旋转角度
      ctx.rotate((-deg * Math.PI) / 180)
      ctx.translate(-x, -y)
    },
    drawLine (ctx) {
      // 绘制干扰线
      for (let i = 0; i < 5; i++) {
        ctx.strokeStyle = this.randomColor(
          this.lineColorMin,
          this.lineColorMax
        )
        ctx.beginPath()
        ctx.moveTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        )
        ctx.lineTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        )
        ctx.stroke()
      }
    },
    drawDot (ctx) {
      // 绘制干扰点
      for (let i = 0; i < 80; i++) {
        ctx.fillStyle = this.randomColor(0, 255)
        ctx.beginPath()
        ctx.arc(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight),
          1,
          0,
          2 * Math.PI
        )
        ctx.fill()
      }
    }
  }
}
</script>
<style scoped>
.s-canvas {
  height: 38px;
}
.s-canvas canvas {
  margin-top: 1px;
  margin-left: 8px;
}
</style>
src/components/emoji.vue
New file
@@ -0,0 +1,130 @@
<template>
  <div class="emoji">
    <ul class="emoji-controller">
      <li
        v-for="(pannel,index) in pannels"
        :key="index"
        :class="{'active': index === activeIndex}"
        @click="changeActive(index)">
        {{ pannel }}
      </li>
    </ul>
    <ul class="emoji-container">
      <li
        v-for="(emojiGroup, index) in emojis"
        v-if="index === activeIndex"
        :key="index"
        style="padding: 0">
        {{ emojiGroup }}--{{ index }}
        <a
          v-for="(emoji, index) in emojiGroup"
          :key="index"
          href="javascript:;"
          @click="selectItem(emoji)">
          <span
            :title="emoji"
            :class="'sprite-' + getPureName(emoji)"
            class="emoji-item"/>
        </a>
      </li>
    </ul>
  </div>
</template>
<script>
import data from '@/utils/emoji-data.js'
export default {
  name: 'Emoji',
  data () {
    return {
      emojiData: data,
      pannels: ['表情', '自然', '物品', '地点', '符号'],
      activeIndex: 0
    }
  },
  computed: {
    emojis () {
      return this.pannels.map(item => {
        return Object.keys(this.emojiData[item])
      })
    }
  },
  created () {
  },
  methods: {
    changeActive (index) {
      this.activeIndex = index
    },
    getPureName (name) {
      return name.replace(/:/g, '')
    },
    selectItem (emoji) {
      this.$emit('select', emoji)
    }
  }
}
</script>
<style lang='scss' scoped>
@import '@/styles/emoji-sprite.scss';
.emoji {
  //   width: 420px;
  //       box-shadow: 0 0 24px rgba(0,0,0,.18);
  // //   height: 186px;
  //   bottom: 30px;
  //   background: #fff;
  //   z-index: 10;
  //   padding: 10px;
  //   margin-right: 10px;
  .emoji-controller {
    height: 36px;
    overflow: hidden;
    margin-bottom: 0;
    li {
      float: left;
      width: 76px;
      font-size: 12px;
      line-height: 36px;
      cursor: pointer;
      text-align: center;
      position: relative;
      &.active::after {
        content: '';
        width: 100%;
        height: 1px;
        background: #0689dd;
        left: 0;
        bottom: 4px;
        position: absolute;
      }
    }
  }
  .emoji-container {
    height: 175px;
    overflow-y: auto;
    overflow-x: hidden;
    position: relative;
    li {
      font-size: 0;
      padding: 5px;
      a {
        float: left;
        overflow: hidden;
        height: 35px;
        transition: all ease-out 0.2s;
        border-radius: 4px;
        &:hover {
          background-color: #d8d8d8;
          border-color: #d8d8d8;
        }
        span {
          width: 25px;
          height: 25px;
          display: inline-block;
          border: 1px solid transparent;
          cursor: pointer;
        }
      }
    }
  }
}
</style>
src/components/flexbox/flexbox-item.vue
New file
@@ -0,0 +1,62 @@
<template>
  <div
    :style="style"
    class="vux-flexbox-item">
    <slot/>
  </div>
</template>
<script>
const prefixList = ['-moz-box-', '-webkit-box-', '']
export default {
  name: 'FlexboxItem',
  props: {
    span: [Number, String],
    order: [Number, String]
  },
  data () {
    return {
      bodyWidth: 0
    }
  },
  computed: {
    style () {
      const styles = {}
      const marginName =
        this.$parent.orient === 'horizontal' ? 'marginLeft' : 'marginTop'
      if (this.$parent.gutter * 1 !== 0) {
        styles[marginName] = `${this.$parent.gutter}px`
      }
      if (this.span) {
        for (let i = 0; i < prefixList.length; i++) {
          styles[`${prefixList[i]}flex`] = `0 0 ${this.buildWidth(this.span) *
            100}%`
        }
      }
      if (typeof this.order !== 'undefined') {
        styles.order = this.order
      }
      return styles
    }
  },
  beforeMount () {
    this.bodyWidth = document.documentElement.offsetWidth
  },
  methods: {
    buildWidth (width) {
      if (typeof width === 'number') {
        if (width < 1) {
          return width
        } else {
          return width / 12
        }
      } else if (typeof width === 'string') {
        return width.replace('px', '') / this.bodyWidth
      }
    }
  }
}
</script>
src/components/flexbox/flexbox.vue
New file
@@ -0,0 +1,81 @@
<template>
  <div
    :class="{
      'vux-flex-col': orient === 'vertical',
      'vux-flex-row': orient === 'horizontal'
    }"
    :style="styles"
    class="vux-flexbox">
    <slot/>
  </div>
</template>
<script>
export default {
  name: 'Flexbox',
  props: {
    gutter: {
      type: Number,
      default: 8
    },
    orient: {
      type: String,
      default: 'horizontal'
    },
    justify: String,
    align: String,
    wrap: String,
    direction: String
  },
  computed: {
    styles () {
      const styles = {
        'justify-content': this.justify,
        '-webkit-justify-content': this.justify,
        'align-items': this.align,
        '-webkit-align-items': this.align,
        'flex-wrap': this.wrap,
        '-webkit-flex-wrap': this.wrap,
        'flex-direction': this.direction,
        '-webkit-flex-direction': this.direction
      }
      return styles
    }
  }
}
</script>
<style lang="less">
.vux-flexbox {
  width: 100%;
  text-align: left;
  display: flex;
  display: -webkit-flex;
  box-align: center;
  align-items: center;
  .vux-flexbox-item {
    flex: 1;
    -webkit-flex: 1;
    min-width: 20px;
    width: 0%;
    &:first-child {
      margin-left: 0 !important;
      margin-top: 0 !important;
    }
  }
}
.vux-flex-row {
  box-direction: row;
  box-orient: horizontal;
  flex-direction: row;
}
.vux-flex-col {
  box-orient: vertical;
  flex-direction: column;
  > .vux-flexbox-item {
    width: 100%;
  }
}
</style>
src/components/flexbox/index.js
New file
@@ -0,0 +1,7 @@
import Flexbox from './flexbox'
import FlexboxItem from './flexbox-item'
export {
  Flexbox,
  FlexboxItem
}
src/components/relatedBusiness.vue
New file
@@ -0,0 +1,240 @@
<template>
  <div
    :style="{'margin-left': marginLeft}"
    class="related-business">
    <!-- 新建- 关联业务 -->
    <el-popover
      v-if="!isTask && alterable"
      v-model="showPopover"
      placement="bottom"
      width="800"
      popper-class="no-padding-popover"
      trigger="click">
      <crm-relative
        v-if="showRelative"
        ref="crmrelative"
        :show="showPopover"
        :radio="false"
        :selected-data="relatedListData"
        :show-types="showTypes"
        @close="crmrelativeClose"
        @changeCheckout="checkInfos"/>
      <p
        v-if="showCRMPermission"
        slot="reference"
        class="add-file"
        @click="showRelative = true">
        <img
          src="@/assets/img/relevance_business.png"
          alt="">
        关联业务
      </p>
    </el-popover>
    <p
      v-if="!alterable"
      :style="{color: alterableColor}"
      class="alterable-p">关联业务</p>
    <div
      v-for="(items, key) in relatedListData"
      :key="key">
      <related-business-cell
        v-for="(item, itemIndex) in items"
        :data="item"
        :cell-index="itemIndex"
        :type="key"
        :key="itemIndex"
        :show-foot="isTask"
        @unbind="delRelevance"
        @detail="checkRelatedDetail(key, item)"/>
    </div>
    <!-- 任务页面显示格式 -->
    <el-popover
      v-if="isTask"
      v-model="showPopover"
      placement="bottom"
      width="800"
      popper-class="no-padding-popover"
      trigger="click">
      <crm-relative
        v-if="showTaskRelative"
        ref="crmrelative"
        :radio="false"
        :show="showPopover"
        :selected-data="relatedListData"
        :show-types="showTypes"
        @close="crmrelativeClose"
        @changeCheckout="checkInfos"/>
      <p
        v-if="showCRMPermission"
        slot="reference"
        class="add-file"
        @click="showTaskRelative = true">
        <img
          src="@/assets/img/relevance_business.png"
          alt="">
        关联业务
      </p>
    </el-popover>
  </div>
</template>
<script>
// 关联业务 - 弹出框
// import { editTaskRelation } from '@/api/oamanagement/task'
import CrmRelative from '@/components/CreateCom/CrmRelative'
import RelatedBusinessCell from '@/views/OAManagement/components/relatedBusinessCell'
import { objDeepCopy } from '@/utils'
import { mapGetters } from 'vuex'
export default {
  components: {
    CrmRelative,
    RelatedBusinessCell
  },
  props: {
    marginLeft: {
      type: String,
      default: '20px'
    },
    // 编辑时传递所有关联数据   关联联系人-contacts 关联客户-customer 商机-business 合同-contract
    allData: {
      type: Object,
      default: () => {
        return {
          contacts: [],
          customer: [],
          business: [],
          contract: []
        }
      }
    },
    // 是否是任务页面
    isTask: {
      type: Boolean,
      default: false
    },
    taskID: Number,
    alterable: {
      type: Boolean,
      default: true
    },
    alterableColor: {
      type: String,
      default: '#999'
    }
  },
  data () {
    return {
      showTypes: ['customer', 'contacts', 'business', 'contract'],
      showPopover: false,
      relevanceAll: {
        customerIds: [],
        contractIds: [],
        contactsIds: [],
        businessIds: []
      },
      // 关联业务信息
      relatedListData: {},
      showRelative: false,
      // 展示任务相关
      showTaskRelative: false
    }
  },
  computed: {
    ...mapGetters(['crm']),
    showCRMPermission () {
      return this.crm
    }
  },
  watch: {
    allData: function () {
      this.relatedListData = this.allData
    }
  },
  mounted () {
    // 编辑时勾选
    this.relatedListData = this.allData
  },
  methods: {
    crmrelativeClose () {
      this.showPopover = false
    },
    checkInfos (val) {
      this.showPopover = false
      this.relatedListData = val.data
      for (const key in val.data) {
        const list = val.data[key]
        this.relevanceAll[key + 'Ids'] = list.map(function (
          item,
          index,
          array
        ) {
          return item[key + 'Id']
        })
      }
      this.$emit('checkInfos', this.relevanceAll)
    },
    // 任务页面取消关联
    delRelevance (field, index, item) {
      this.$confirm('确认取消关联?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        customClass: 'is-particulars'
      })
        .then(() => {
          const params = { taskId: this.taskID }
          const tempRelatedListData = objDeepCopy(this.relatedListData)
          tempRelatedListData[field].splice(index, 1)
          for (let index = 0; index < this.showTypes.length; index++) {
            const typeItem = this.showTypes[index]
            const typeArray = tempRelatedListData[typeItem] || []
            params[typeItem + 'Ids'] = typeArray
              .map(aItem => {
                return aItem[typeItem + 'Id']
              })
              .join(',')
          }
          // editTaskRelation(params)
          //   .then(res => {
          //     this.relatedListData[field].splice(index, 1)
          //     this.relatedListData = objDeepCopy(this.relatedListData)
          //     this.$message.success('关联取消成功')
          //   })
          //   .catch(() => {})
        })
        .catch(() => {
          this.$message.info('已取消操作')
        })
    },
    checkRelatedDetail (field, val) {
      val.key = val[field + 'Id']
      this.$emit('checkRelatedDetail', field, val)
    }
  }
}
</script>
<style scoped lang="less">
.related-business {
  color: #777;
  font-size: 12px;
  margin: 10px 0;
  .alterable-p {
    padding-bottom: 10px;
    font-size: 13px;
  }
  .add-file {
    margin: 10px 0;
    font-size: 13px;
    color: #4D88FF;
    cursor: pointer;
    display: inline-block;
    img {
      vertical-align: middle;
      width: 15px;
      margin-right: 5px;
    }
  }
}
</style>
src/components/reminder.vue
New file
@@ -0,0 +1,60 @@
<template>
  <flexbox class="reminder-wrapper">
    <flexbox
      align="stretch"
      class="reminder-body">
      <i class="wukong wukong-reminder reminder-icon"/>
      <div
        :style="{'font-size': fontSize + 'px'}"
        class="reminder-content">
        {{ content }}
      </div>
    </flexbox>
  </flexbox>
</template>
<script type="text/javascript">
// 警示信息
export default {
  name: 'Reminder',
  components: {},
  props: {
    content: {
      type: String,
      default: '内容'
    },
    fontSize: {
      type: String,
      default: '13'
    }
  },
  data () {
    return {}
  },
  computed: {},
  mounted () {},
  destroyed () {},
  methods: {}
}
</script>
<style lang="less" scoped>
.reminder-wrapper {
  .reminder-body {
    width: auto;
    padding: 8px 15px;
    border-radius: 4px;
    background-color: #fff4e7;
    .reminder-icon {
      color: #ff7922;
      flex-shrink: 0;
      margin-right: 8px;
    }
    .reminder-content {
      color: #9c9c9b;
      line-height: 17px;
    }
  }
}
</style>
src/components/selectEmployee/membersDep.vue
New file
@@ -0,0 +1,622 @@
<template>
  <el-popover
    ref="popover"
    :placement="placement"
    :width="popoverWidth"
    v-model="popoverVisible"
    popper-class="project-com-popover"
    trigger="click">
    <div v-if="popoverContentShow">
      <div class="title-icon">
        <span>{{ title }}</span>
        <span
          class="el-icon-close rt"
          @click="popoverVisible = false"/>
      </div>
      <div class="popover-content-box">
        <div class="select-input">
          <!-- 搜索员工列表 -->
          <el-tabs
            v-model="activeTabName"
            :stretch="true"
            @tab-click="tabClick">
            <el-tab-pane
              v-loading="userLoading"
              v-if="!closeUser"
              label="员工"
              name="user">
              <el-input
                v-model="searchUserInput"
                placeholder="搜索员工"
                size="mini"
                prefix-icon="el-icon-search"
                @input="userSearchChange"/>
              <div class="search-list">
                <div
                  v-for="(user, index) in userList"
                  v-if="!user.hidden"
                  :key="index"
                  class="colleagues-list">
                  <el-checkbox
                    v-model="user.isCheck"
                    @change="userCheckboxChange(user, index)">
                    <div
                      v-photo="user"
                      v-lazy:background-image="$options.filters.filterUserLazyImg(user.img)"
                      class="div-photo search-img header-circle"/>
                    <span>{{ user.realname }}</span>
                  </el-checkbox>
                </div>
              </div>
            </el-tab-pane>
            <el-tab-pane
              v-loading="depLoading"
              v-if="!closeDep"
              label="部门"
              name="dep">
              <el-input
                v-model="searchDepInput"
                placeholder="搜索部门"
                size="mini"
                style="margin-bottom:10px;"
                prefix-icon="el-icon-search"
                @input="depSearchChange"/>
              <div class="search-list">
                <el-breadcrumb separator-class="el-icon-arrow-right">
                  <el-breadcrumb-item
                    v-for="(item, index) in breadcrumbList"
                    :key="index">
                    <a
                      href="javascript:;"
                      @click="breadcrumbBtn(item, index)">{{ item.label }}</a>
                  </el-breadcrumb-item>
                </el-breadcrumb>
                <div
                  v-for="(depItem, index) in depShowList"
                  v-if="!depItem.hidden"
                  :key="index"
                  class="checkout-box">
                  <el-checkbox
                    v-model="depItem.isCheck"
                    @change="depCheckboxChange(depItem, index)"/>
                  <div @click="enterDepChildren(depItem)">
                    <span>{{ depItem.name }}</span>
                    <span
                      v-if="depItem.children"
                      class="el-icon-arrow-right"/>
                  </div>
                </div>
              </div>
            </el-tab-pane>
          </el-tabs>
        </div>
        <div class="checked-content">
          <div class="checked-top">
            <span class="title">已选择</span>
            <span
              v-if="!closeUser"
              class="title">员工 ({{ userSelectCount }})</span>
            <span
              v-if="!closeDep"
              class="title">部门 ({{ depSelectCount }})</span>
            <el-button
              type="text"
              class="rt"
              @click="emptyClick">清空</el-button>
          </div>
          <div class="border-content">
            <div
              v-for="(item, index) in checkedUserDepList"
              :key="index"
              class="checked-list">
              <div
                v-photo="item"
                v-lazy:background-image="$options.filters.filterUserLazyImg(item.img)"
                v-if="item.type === 'user'"
                class="div-photo"/>
              <span v-if="item.type === 'user'"> {{ item.realname }} </span>
              <span v-else> {{ item.name }} </span>
              <span
                class="rt el-icon-close"
                @click="selectDelect(item, index)"/>
            </div>
          </div>
        </div>
      </div>
      <div class="popover-footer">
        <el-button
          type="primary"
          @click="popoverSubmit">确 定</el-button>
        <el-button @click="popoverVisible = false">取 消</el-button>
      </div>
    </div>
    <div
      slot="reference"
      :style="{'display':contentBlock ? 'block' : 'inline-block'}"
      @click="showContentClick">
      <slot name="membersDep"/>
    </div>
  </el-popover>
</template>
<script>
// import { usersList, depList } from '@/api/common'
export default {
  props: {
    // 弹出框宽度
    popoverWidth: {
      type: String,
      default: '600'
    },
    // 标题
    title: {
      type: String,
      default: '选择成员'
    },
    // 显示位置
    placement: {
      type: String,
      default: 'bottom-start'
    },
    // 内容框类型
    contentBlock: {
      type: Boolean,
      default: true
    },
    // 编辑时 -- 用户默认勾选的数据
    userCheckedData: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 编辑时 -- 部门默认勾选的数据
    depCheckedData: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 是否关闭某个类的选择
    closeUser: {
      type: Boolean,
      default: false
    },
    closeDep: {
      type: Boolean,
      default: false
    },
    userRequest: Function,
    userParams: Object
  },
  data () {
    return {
      activeTabName: 'user',
      // 筛选
      searchUserInput: '',
      searchDepInput: '',
      popoverVisible: false,
      // 内容展示
      popoverContentShow: false,
      // 加载动画
      userLoading: false,
      depLoading: false,
      // 所有用户
      userList: [],
      // 展示客户
      depShowList: [],
      // 面包屑数据
      breadcrumbList: [],
      // 选中的数据 -- 员工和部门一个数组用于页面展示
      checkedUserDepList: []
    }
  },
  computed: {
    userSelectCount () {
      return this.checkedUserDepList.filter(item => {
        return item.type === 'user'
      }).length
    },
    depSelectCount () {
      return this.checkedUserDepList.filter(item => {
        return item.type === 'dep'
      }).length
    }
  },
  watch: {
    userCheckedData: function () {
      this.updateCheckInfoByWatch()
    },
    depCheckedData: function () {
      this.updateCheckInfoByWatch()
    },
    popoverVisible: function (val) {
      if (val) {
        this.updateCheckInfoByWatch()
      }
    }
  },
  methods: {
    initInfo () {
      // 用户列表
      this.checkedUserDepList = this.userCheckedData
        .map(item => {
          item.type = 'user'
          return item
        })
        .concat(
          this.depCheckedData.map(item => {
            item.type = 'dep'
            return item
          })
        )
      if (!this.closeUser) {
        this.getUserList()
      } else if (!this.closeDep) {
        this.activeTabName = 'dep'
        this.getDepList()
      }
    },
    tabClick () {
      if (this.activeTabName === 'dep') {
        if (this.depShowList.length === 0) {
          this.getDepList()
        }
      }
    },
    userSearchChange (val) {
      this.userList = this.userList.map(item => {
        if (item.realname.indexOf(val) !== -1) {
          item.hidden = false
        } else {
          item.hidden = true
        }
        return item
      })
    },
    depSearchChange (val) {
      this.depShowList = this.depShowList.map(item => {
        if (item.name.indexOf(val) !== -1) {
          item.hidden = false
        } else {
          item.hidden = true
        }
        return item
      })
    },
    /**
     * 部门信息
     */
    // 部门列表数据
    getDepList () {
      this.depLoading = true
      // depList({ type: 'tree' })
      //   .then(res => {
      //     this.depShowList = res.data.map((item, index, array) => {
      //       item.type = 'dep'
      //       item.isCheck = this.getItemCheckInfo(item, 'dep')
      //       return item
      //     })
      //     this.breadcrumbList.push({ label: '全部', data: this.depShowList })
      //     this.depLoading = false
      //   })
      //   .catch(() => {
      //     this.depLoading = false
      //   })
    },
    // 部门下一级
    enterDepChildren (depItem) {
      if (depItem.children) {
        this.depShowList = []
        this.depShowList = depItem.children.map((item, index, array) => {
          item.type = 'dep'
          if (item.name.indexOf(this.searchDepInput) !== -1) {
            item.hidden = false
          } else {
            item.hidden = true
          }
          item.isCheck = this.getItemCheckInfo(item, 'dep')
          return item
        })
        this.breadcrumbList.push({
          label: depItem.label,
          data: this.depShowList
        })
      }
    },
    // 面包屑点击事件
    breadcrumbBtn (item, index) {
      if (index + 1 <= this.breadcrumbList.length - 1) {
        this.breadcrumbList.splice(index + 1, this.breadcrumbList.length - 1)
      }
      this.depShowList = []
      this.depShowList = item.data.map((item, index, array) => {
        if (item.name.indexOf(this.searchDepInput) !== -1) {
          item.hidden = false
        } else {
          item.hidden = true
        }
        item.isCheck = this.getItemCheckInfo(item, 'dep')
        return item
      })
    },
    // 部门勾选
    depCheckboxChange (item, aindex) {
      this.$set(this.depShowList, aindex, item)
      this.updateCheckedUserDepListByCheck(item, 'dep')
    },
    /**
     * 员工操作
     */
    getUserList () {
      this.userLoading = true
      // let request = usersList
      // let params = {}
      if (this.userRequest) {
        // request = this.userRequest
        // params = this.userParams || {}
      } else {
        // params = { pageType: 0 }
      }
      // request(params)
      //   .then(res => {
      //     this.userList = res.data.map(item => {
      //       item.type = 'user'
      //       item.isCheck = this.getItemCheckInfo(item, 'user')
      //       return item
      //     })
      //     this.userLoading = false
      //   })
      //   .catch(() => {
      //     this.userLoading = false
      //   })
    },
    // 员工勾选
    userCheckboxChange (item, aindex) {
      this.$set(this.userList, aindex, item)
      this.updateCheckedUserDepListByCheck(item, 'user')
    },
    // check 操作后的 存储数据刷新
    updateCheckedUserDepListByCheck (item, type) {
      var removeIndex = -1
      for (let index = 0; index < this.checkedUserDepList.length; index++) {
        const element = this.checkedUserDepList[index]
        if (element.type === 'user' && item.userId === element.userId) {
          removeIndex = index
        } else if (element.type === 'dep' && item.id === element.id) {
          removeIndex = index
        }
      }
      if (removeIndex === -1) {
        this.checkedUserDepList.push(item)
      } else if (removeIndex !== -1) {
        this.checkedUserDepList.splice(removeIndex, 1)
      }
    },
    // 获取事项标记信息
    getItemCheckInfo (item, type) {
      if (this.checkedUserDepList.length === 0) {
        return false
      }
      var hasItem = false
      for (let index = 0; index < this.checkedUserDepList.length; index++) {
        const element = this.checkedUserDepList[index]
        if (element.type === 'user' && item.userId === element.userId) {
          hasItem = true
          break
        } else if (element.type === 'dep' && item.id === element.id) {
          hasItem = true
          break
        }
      }
      return hasItem
    },
    /**
     * 删除 清空 等操作
     */
    // 删除一个选择员工或部门
    selectDelect (selectItem, index) {
      this.checkedUserDepList.splice(index, 1)
      if (selectItem.type === 'dep') {
        this.depShowList = this.depShowList.map((item, index, array) => {
          item.isCheck = this.getItemCheckInfo(item, 'dep')
          return item
        })
      } else {
        this.userList = this.userList.map((item, index, array) => {
          item.isCheck = this.getItemCheckInfo(item, 'user')
          return item
        })
      }
    },
    // 提交按钮
    popoverSubmit () {
      this.popoverVisible = false
      this.$emit(
        'popoverSubmit',
        this.checkedUserDepList.filter(item => {
          return item.type === 'user'
        }),
        this.checkedUserDepList.filter(item => {
          return item.type === 'dep'
        })
      )
    },
    // 清空按钮
    emptyClick () {
      this.checkedUserDepList = []
      for (let index = 0; index < this.userList.length; index++) {
        this.userList[index].isCheck = false
      }
      for (let index = 0; index < this.depShowList.length; index++) {
        this.depShowList[index].isCheck = false
      }
    },
    // 内容可见
    showContentClick () {
      if (!this.popoverContentShow) {
        this.popoverContentShow = true
        this.initInfo()
      }
    },
    // 监听父类改变更新check
    updateCheckInfoByWatch () {
      this.checkedUserDepList = this.userCheckedData
        .map(item => {
          item.type = 'user'
          return item
        })
        .concat(
          this.depCheckedData.map(item => {
            item.type = 'dep'
            return item
          })
        )
      this.userList = this.userList.map(item => {
        item.isCheck = this.getItemCheckInfo(item, 'user')
        return item
      })
      this.depShowList = this.depShowList.map((item, index, array) => {
        item.isCheck = this.getItemCheckInfo(item, 'dep')
        return item
      })
    }
  }
}
</script>
<style scoped lang="scss">
@import '@/styles/mixin.scss';
.popover-content-box {
  display: flex;
  .select-input {
    flex: 1;
    margin-right: 30px;
    .select-input > .el-input {
      margin: 10px 0;
    }
  }
  .select-input /deep/ .el-tabs {
    .el-tabs__active-bar {
      display: none;
    }
    .el-tabs__nav-wrap::after {
      height: 0;
    }
    .el-tabs__content {
      border: 1px solid #e6e6e6;
      height: 300px;
      .el-checkbox {
        margin-left: 0;
        margin-right: 10px;
      }
    }
    .el-breadcrumb {
      margin-bottom: 15px;
    }
    .checkout-box {
      display: flex;
      margin-bottom: 10px;
    }
    .checkout-box > div {
      flex: 1;
      .el-icon-arrow-right {
        float: right;
      }
      span {
        cursor: pointer;
      }
    }
    .el-tab-pane {
      padding: 10px;
      height: 100%;
    }
    .el-tab-pane > .el-input {
      width: 90%;
      margin: auto 5%;
      .el-input__inner {
        border-radius: 15px;
      }
    }
  }
  .checked-content {
    flex: 1;
    .checked-top {
      height: 40px;
      line-height: 40px;
      margin-bottom: 15px;
      .title {
        color: #999999;
      }
    }
    .border-content {
      border: 1px solid #e6e6e6;
      height: 300px;
      overflow: auto;
      padding: 20px 0;
      @include scrollBar;
      .checked-list {
        height: 30px;
        line-height: 30px;
        padding: 0 20px;
        cursor: pointer;
        .el-icon-close {
          opacity: 0;
          margin-top: 8px;
          margin-right: 0;
        }
        .div-photo {
          width: 24px;
          height: 24px;
          border-radius: 12px;
          vertical-align: middle;
          margin-right: 8px;
        }
      }
      .checked-list:hover {
        -webkit-box-shadow: 0 0 8px 2px #eee;
        box-shadow: 0 0 8px 2px #eee;
        .el-icon-close {
          opacity: 1;
        }
      }
    }
  }
}
.title-icon {
  padding: 10px 20px 15px;
  border-bottom: 1px solid #e6e6e6;
  margin-bottom: 10px;
  font-size: 16px;
  .el-icon-close {
    font-size: 20px;
    color: #ccc;
    margin-right: 0;
  }
}
.popover-footer {
  float: right;
  margin: 20px 0 0;
}
/* 选择员工 */
.search-img {
  width: 24px;
  height: 24px;
  border-radius: 12px;
  vertical-align: middle;
  margin-right: 8px;
}
.search-list {
  margin: 5px;
  height: 248px;
  overflow: auto;
  margin-right: -10px;
  padding-right: 10px;
  @include scrollBar;
}
.colleagues-list {
  padding: 5px;
}
</style>
src/components/timeTypeSelect/index.vue
New file
@@ -0,0 +1,184 @@
<template>
  <el-popover
    v-model="showTypePopover"
    placement="bottom"
    width="200"
    popper-class="no-padding-popover"
    trigger="click">
    <div class="type-popper">
      <div class="type-content">
        <div
          v-for="(item, index) in typeOptions"
          :key="index"
          :class="{ 'selected' : selectType.value === item.value && !showCustomContent}"
          class="type-content-item"
          @click="typeSelectClick(item)">
          <div class="mark"/>{{ item.label }}
        </div>
        <div
          :class="{ 'selected' : showCustomContent}"
          class="type-content-item"
          @click="showCustomContent = true">
          <div class="mark"/>自定义
        </div>
      </div>
      <div
        v-if="showCustomContent"
        class="type-content-custom">
        <el-date-picker
          v-model="startTime"
          type="date"
          value-format="yyyy-MM-dd"
          placeholder="选择日期"/>
        <el-date-picker
          v-model="endTime"
          type="date"
          value-format="yyyy-MM-dd"
          placeholder="选择日期"/>
        <el-button @click="customSureClick">确定</el-button>
      </div>
    </div>
    <el-input
      slot="reference"
      v-model="typeShowValue"
      :readonly="true"
      placeholder="请选择选择"
      class="type-select">
      <i
        slot="suffix"
        :class="['el-input__icon', 'el-icon-' + iconClass]"/>
    </el-input>
  </el-popover>
</template>
<script type="text/javascript">
export default {
  name: 'TimeTypeSelect',
  props: {
    defaultType: Object
  },
  data() {
    return {
      selectType: { label: '本年', value: 'year' },
      showTypePopover: false,
      showCustomContent: false, // 展示自定义时间内容
      sureCustomContent: false, // 确定
      startTime: '',
      endTime: '',
      typeOptions: [
        { label: '今天', value: 'today' },
        { label: '昨天', value: 'yesterday' },
        { label: '本周', value: 'week' },
        { label: '上周', value: 'lastWeek' },
        { label: '本月', value: 'month' },
        { label: '上月', value: 'lastMonth' },
        { label: '本季度', value: 'quarter' },
        { label: '上季度', value: 'lastQuarter' },
        { label: '本年', value: 'year' },
        { label: '去年', value: 'lastYear' }
      ]
    }
  }, // 时间类型选择
  computed: {
    iconClass() {
      return this.showTypePopover ? 'arrow-up' : 'arrow-down'
    },
    typeShowValue() {
      if (this.sureCustomContent) {
        if (this.startTime || this.endTime) {
          return (this.startTime || '') + '-' + (this.endTime || '')
        }
        return ''
      } else {
        return this.selectType.label
      }
    }
  },
  mounted() {
    if (this.defaultType) {
      this.selectType = this.defaultType
    } else {
      this.$emit('change', { type: 'default', value: this.selectType.value })
    }
  },
  methods: {
    // 类型选择
    typeSelectClick(item) {
      this.showTypePopover = false
      this.sureCustomContent = false
      this.showCustomContent = false
      this.selectType = item
      this.$emit('change', { type: 'default', value: this.selectType.value })
    },
    // 选择自定义时间 确定
    customSureClick() {
      if (this.startTime && this.endTime) {
        this.sureCustomContent = true
        this.showTypePopover = false
        this.$emit('change', {
          type: 'custom',
          startTime: this.startTime,
          endTime: this.endTime
        })
      }
    }
  }
}
</script>
<style lang="less" scoped>
.type-select {
  width: 200px;
  margin-right: 15px;
}
// 时间选择
.type-popper {
  .type-content {
    height: 250px;
    overflow-y: auto;
    .type-content-item {
      height: 34px;
      line-height: 34px;
      padding: 0 20px;
      color: #606266;
      position: relative;
      cursor: pointer;
      .mark {
        display: inline-block;
        width: 8px;
        height: 8px;
        border-radius: 4px;
        margin-right: 5px;
        background-color: transparent;
      }
    }
    .selected {
      color: #409eff;
      font-weight: 700;
      .mark {
        background-color: #409eff;
      }
    }
    .type-content-item:hover {
      background-color: #f5f7fa;
    }
  }
  .type-content-custom {
    padding: 5px 20px 10px;
    position: relative;
    overflow: hidden;
    .el-date-editor {
      width: 100%;
      margin-bottom: 8px;
    }
    button {
      float: right;
    }
  }
}
</style>
src/components/vuePictureViewer/img/pre_close.png
src/components/vuePictureViewer/img/pre_down.png
src/components/vuePictureViewer/img/pre_left.png
src/components/vuePictureViewer/img/pre_max.png
src/components/vuePictureViewer/img/pre_min.png
src/components/vuePictureViewer/img/pre_right.png
src/components/vuePictureViewer/img/pre_rotate.png
src/components/vuePictureViewer/index.vue
New file
@@ -0,0 +1,753 @@
<template>
  <div
    id="vue-picture-viewer"
    :style="maskContainer">
    <!-- 头部 -->
    <flexbox class="perview-header">
      <div class="left">{{ imgIndex + 1 }} / {{ imgLength }}</div>
      <div class="center">{{ bigImgName.slice(0,bigImgName.indexOf('.')) }}</div>
      <img
        class="close"
        src="./img/pre_close.png"
        @click="closeViewer" >
    </flexbox>
    <!-- 图片容器 -->
    <div
      ref="imgContainer"
      :style="imgContainer"
      class="imgContainer">
      <img
        v-if="bigShowType.isImage"
        ref="bigImg"
        :src="bigImgUrl"
        :style="bigImgStyle"
        alt="">
      <flexbox
        v-if="!bigShowType.isImage"
        class="file-show">
        <div class="file-icon">
          <img :src="bigShowType.icon" >
        </div>
        <div class="file-handle">
          <!-- <el-button type="primary"
                     @click.native="fileHandle('online')">在线预览</el-button> -->
          <el-button
            type="primary"
            plain
            @click.native="fileHandle('download')">下载</el-button>
        </div>
      </flexbox>
      <!-- tips -->
      <transition name="fade">
        <div
          v-show="showTips"
          class="tips">{{ tipsText }}</div>
      </transition>
    </div>
    <div class="fixedHandle">
      <!-- 操作按钮 -->
      <flexbox
        v-if="bigShowType.isImage"
        class="handleContainer">
        <img
          src="./img/pre_max.png"
          @click="enlarge" >
        <img
          src="./img/pre_min.png"
          @click="reduce" >
        <img
          style="padding: 4.5px;"
          src="./img/pre_rotate.png"
          @click="rotate" >
        <img
          src="./img/pre_down.png"
          @click="downloadImg(bigImgUrl, bigImgName)" >
      </flexbox>
      <!-- 缩略图容器 -->
      <div
        v-if="imgLength > 1"
        class="thumbnailContainer">
        <ul>
          <li
            v-for="(item, index) in imgData"
            ref="thumbnailItem"
            :key="index"
            @click="switchImgUrl(index, $event)">
            <img
              v-if="isShowImage(item.url)"
              :src="item.url"
              alt="">
            <img
              v-if="!isShowImage(item.url)"
              :src="getFileTypeIconWithSuffix(item.url)"
              alt="">
          </li>
        </ul>
      </div>
    </div>
    <!-- 左边箭头 -->
    <div
      class="leftArrowCon"
      @click="handlePrev"
      @mouseenter="enterLeft"
      @mouseout="outLeft">
      <img
        v-show="leftArrowShow"
        class="leftArrow"
        src="./img/pre_left.png"
        @click="enlarge" >
    </div>
    <!-- 右边箭头 -->
    <div
      class="rightArrowCon"
      @click="handleNext"
      @mouseenter="enterRight"
      @mouseout="outRight">
      <img
        v-show="rightArrowShow"
        class="rightArrow"
        src="./img/pre_right.png" >
    </div>
  </div>
</template>
<script>
import { getMaxIndex, downloadImage } from '@/utils'
export default {
  name: 'VuePictureViewer',
  props: {
    imgData: {
      type: Array,
      default: () => {
        return []
      }
    },
    background: {
      type: String,
      default: 'rgba(0,0,0,0.4)'
    },
    // 选择的索引
    selectIndex: {
      type: Number,
      default: -1
    }
  },
  data() {
    return {
      // 默认不显示左右切换箭头
      leftArrowShow: false,
      rightArrowShow: false,
      // 图片容器数据
      rotateDeg: 0,
      bigImgUrl: '',
      bigShowType: { isImage: true, icon: '' }, // 不是图片的时候 展示 icon
      bigImgName: '',
      imgLength: 0,
      imgIndex: 0,
      showTips: false,
      tipsText: '',
      bigImgConWidth: '',
      bigImgConHeight: '',
      maskContainer: {
        width: '100%',
        height: '100%',
        background: this.background,
        position: 'fixed',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0
      },
      imgContainer: {
        width: 'auto',
        height: 'auto',
        position: 'absolute',
        top: '50%',
        left: '50%',
        'z-index': 100,
        transform: 'translate(-50%, -50%)'
      },
      bigImgStyle: {
        display: 'block',
        width: '80px',
        height: '80px',
        position: 'absolute',
        top: 50 + '%',
        left: 50 + '%',
        marginLeft: '',
        marginTop: '',
        userSelect: 'none'
      }
    }
  },
  mounted() {
    document
      .getElementById('vue-picture-viewer')
      .addEventListener('click', e => {
        e.stopPropagation()
      })
    this.imgLength = this.imgData.length
    this.imgIndex = this.selectIndex
    this.$nextTick(() => {
      this.bigImgUrl = this.imgData[this.imgIndex].url
      this.getShowTypeInfo(this.bigImgUrl)
      this.bigImgName = this.imgData[this.imgIndex].name
      if (this.imgLength > 1) {
        // 大于1的时候才会展示缩略图
        var item = this.$refs.thumbnailItem
        item[this.imgIndex].className = 'borderActive'
      }
    })
    var self = this
    this.$refs.bigImg.onload = () => {
      self.init()
    }
    this.maskContainer['z-index'] = getMaxIndex()
  },
  beforeDestroy() {
    if (document.getElementById('vue-picture-viewer')) {
      document
        .getElementById('vue-picture-viewer')
        .removeEventListener('click', e => {
          e.stopPropagation()
        })
    }
  },
  methods: {
    // init
    init() {
      const screenW =
        document.documentElement.offsetWidth || document.body.offsetWidth
      const screenH =
        document.documentElement.scrollHeight || document.body.scrollHeight
      this.$nextTick(function() {
        const ratio = [0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9]
        for (const item of ratio) {
          if (
            this.$refs.bigImg.naturalWidth * item < screenW &&
            this.$refs.bigImg.naturalHeight * item < screenH - 200
          ) {
            this.bigImgConWidth = this.$refs.bigImg.naturalWidth * item
            this.bigImgConHeight = this.$refs.bigImg.naturalHeight * item
            this.imgContainer.width = this.bigImgConWidth + 'px'
            this.imgContainer.height = this.bigImgConHeight + 'px'
            this.bigImgStyle.width = this.bigImgConWidth + 'px'
            this.bigImgStyle.height = this.bigImgConHeight + 'px'
            this.bigImgStyle.marginLeft = -(this.bigImgConWidth / 2) + 'px'
            this.bigImgStyle.marginTop = -(this.bigImgConHeight / 2) + 'px'
          }
        }
      })
    },
    // rotate init
    rotateInit() {
      const screenH =
        document.documentElement.scrollHeight || document.body.scrollHeight
      const ratio = [0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9]
      for (const item of ratio) {
        if (this.$refs.bigImg.naturalWidth * item < screenH - 160) {
          this.bigImgConWidth = this.$refs.bigImg.naturalWidth * item
          this.bigImgConHeight = this.$refs.bigImg.naturalHeight * item
          this.imgContainer.width = this.bigImgConWidth + 'px'
          this.imgContainer.height = this.bigImgConHeight + 'px'
          this.bigImgStyle.width = this.bigImgConWidth + 'px'
          this.bigImgStyle.height = this.bigImgConHeight + 'px'
          this.bigImgStyle.marginLeft = -(this.bigImgConWidth / 2) + 'px'
          this.bigImgStyle.marginTop = -(this.bigImgConHeight / 2) + 'px'
        }
      }
    },
    // 放大
    enlarge() {
      this.$nextTick(function() {
        const screenW =
          document.documentElement.offsetWidth || document.body.offsetWidth
        const screenH =
          document.documentElement.scrollHeight || document.body.scrollHeight
        if (
          (this.$refs.bigImg.offsetWidth >= this.$refs.bigImg.offsetHeight &&
            this.$refs.bigImg.offsetHeight * 2 < screenH * 2) ||
          (this.$refs.bigImg.offsetHeight >= this.$refs.bigImg.offsetWidth &&
            this.$refs.bigImg.offsetWidth * 2 < screenW * 2)
        ) {
          this.$refs.bigImg.style.width =
            this.$refs.bigImg.offsetWidth * 1.3 + 'px'
          this.$refs.bigImg.style.height =
            this.$refs.bigImg.offsetHeight * 1.3 + 'px'
          this.$refs.bigImg.style.left = '50%'
          this.$refs.bigImg.style.top = '50%'
          this.bigImgStyle.marginLeft =
            -this.$refs.bigImg.offsetWidth / 2 + 'px'
          this.bigImgStyle.marginTop =
            -this.$refs.bigImg.offsetHeight / 2 + 'px'
        }
      })
    },
    // 缩小
    reduce() {
      if (this.$refs.bigImg.offsetWidth > 80) {
        /**
           * clientWidth = width + padding
             offsetWidth = width + padding + border  */
        this.$refs.bigImg.style.width =
          this.$refs.bigImg.offsetWidth * 0.7 + 'px'
        this.$refs.bigImg.style.height =
          this.$refs.bigImg.offsetHeight * 0.7 + 'px'
        this.$refs.bigImg.style.left = '50%'
        this.$refs.bigImg.style.top = '50%'
        this.bigImgStyle.marginLeft = -this.$refs.bigImg.offsetWidth / 2 + 'px'
        this.bigImgStyle.marginTop = -this.$refs.bigImg.offsetHeight / 2 + 'px'
      }
    },
    // 旋转
    rotate() {
      if (this.rotateDeg === 0) {
        this.$refs.bigImg.style.transform = 'rotate(90deg)'
        this.rotateInit()
        this.rotateDeg++
      } else if (this.rotateDeg === 1) {
        this.$refs.bigImg.style.transform = 'rotate(180deg)'
        this.init()
        this.rotateDeg++
      } else if (this.rotateDeg === 2) {
        this.$refs.bigImg.style.transform = 'rotate(270deg)'
        this.rotateInit()
        this.rotateDeg++
      } else if (this.rotateDeg === 3) {
        this.$refs.bigImg.style.transform = 'rotate(360deg)'
        this.init()
        this.rotateDeg = 0
      }
    },
    // 点击缩略图切换图片
    switchImgUrl(num, e) {
      var item = this.$refs.thumbnailItem
      item.forEach(function(i) {
        i.className = ''
      })
      this.imgIndex = num
      this.bigImgUrl = this.imgData[num].url
      this.getShowTypeInfo(this.bigImgUrl)
      this.bigImgName = this.imgData[num].name
      e.currentTarget.className = 'borderActive'
      if (this.bigShowType.isImage) {
        this.init()
      }
    },
    // 切换到上一张
    handlePrev() {
      if (this.imgIndex <= 0) {
        this.tips('已经是第一张了!')
        this.imgIndex = 0
      } else {
        if (this.$refs.bigImg) {
          this.$refs.bigImg.style.transform = 'rotate(0deg)'
          this.rotateDeg = 0
        }
        this.imgIndex--
        this.bigImgUrl = this.imgData[this.imgIndex].url
        this.getShowTypeInfo(this.bigImgUrl)
        this.bigImgName = this.imgData[this.imgIndex].name
        var item = this.$refs.thumbnailItem
        item.forEach(function(i) {
          i.className = ''
        })
        item[this.imgIndex].className = 'borderActive'
        if (this.bigShowType.isImage) {
          this.init()
        }
      }
    },
    // 切换到下一张
    handleNext() {
      if (this.imgIndex + 1 >= this.imgData.length) {
        this.tips('已经是最后一张了!')
      } else {
        if (this.$refs.bigImg) {
          this.$refs.bigImg.style.transform = 'rotate(0deg)'
          this.rotateDeg = 0
        }
        this.imgIndex++
        this.bigImgUrl = this.imgData[this.imgIndex].url
        this.getShowTypeInfo(this.bigImgUrl)
        this.bigImgName = this.imgData[this.imgIndex].name
        var item = this.$refs.thumbnailItem
        item.forEach(function(i) {
          i.className = ''
        })
        item[this.imgIndex].className = 'borderActive'
        if (this.bigShowType.isImage) {
          this.init()
        }
      }
    },
    // 提示框
    tips(msg) {
      this.showTips = true
      this.tipsText = msg
      const _this = this
      setTimeout(function() {
        _this.showTips = false
      }, 10000)
    },
    // 下载图片
    downloadImg(data, filename) {
      downloadImage(data, filename)
    },
    // 鼠标左移
    enterLeft() {
      this.leftArrowShow = true
    },
    outLeft() {
      this.leftArrowShow = false
    },
    // 鼠标右移
    enterRight() {
      this.rightArrowShow = true
    },
    outRight() {
      this.rightArrowShow = false
    },
    // 关闭查看器
    closeViewer() {
      this.$emit('close-viewer')
    },
    /** 附件逻辑 */
    fileHandle(type) {
      var a = document.createElement('a')
      a.href = this.bigImgUrl
      a.download = this.bigImgName ? this.bigImgName : '文件'
      a.target = '_black'
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
    },
    getShowTypeInfo(url) {
      const temps = url ? url.split('.') : []
      var ext = ''
      if (temps.length > 0) {
        ext = temps[temps.length - 1]
      } else {
        ext = ''
      }
      var icon = ''
      var isImage = true
      if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
        isImage = true
        icon = require('@/assets/img/file_img.png')
      } else if (this.arrayContain(['mp4', 'mp3', 'avi'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['xlsx', 'xls', 'XLSX', 'XLS'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['doc', 'docx', 'DOC', 'DOCX'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_word.png')
      } else if (this.arrayContain(['rar', 'zip'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_zip.png')
      } else if (ext === 'pdf') {
        isImage = false
        icon = require('@/assets/img/file_pdf.png')
      } else if (ext === 'ppt' || ext === 'pptx') {
        isImage = false
        icon = require('@/assets/img/file_ppt.png')
      } else if (this.arrayContain(['txt', 'text'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_txt.png')
      } else {
        isImage = false
        icon = require('@/assets/img/file_unknown.png')
      }
      this.bigShowType = { isImage: isImage, icon: icon }
    },
    getFileTypeIconWithSuffix(url) {
      const temps = url ? url.split('.') : []
      var ext = ''
      if (temps.length > 0) {
        ext = temps[temps.length - 1]
      } else {
        ext = ''
      }
      if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
        return require('@/assets/img/file_img.png')
      } else if (this.arrayContain(['mp4', 'mp3', 'avi'], ext)) {
        return require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['xlsx', 'xls', 'XLSX', 'XLS'], ext)) {
        return require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['doc', 'docx', 'DOC', 'DOCX'], ext)) {
        return require('@/assets/img/file_word.png')
      } else if (this.arrayContain(['rar', 'zip'], ext)) {
        return require('@/assets/img/file_zip.png')
      } else if (ext === 'pdf') {
        return require('@/assets/img/file_pdf.png')
      } else if (ext === 'ppt' || ext === 'pptx') {
        return require('@/assets/img/file_ppt.png')
      } else if (this.arrayContain(['txt', 'text'], ext)) {
        return require('@/assets/img/file_txt.png')
      }
      return require('@/assets/img/file_unknown.png')
    },
    isShowImage(url) {
      const temps = url ? url.split('.') : []
      var ext = ''
      if (temps.length > 0) {
        ext = temps[temps.length - 1]
      } else {
        ext = ''
      }
      if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
        return true
      }
      return false
    },
    arrayContain(array, string) {
      return array.some(item => {
        return item === string
      })
    }
  }
}
</script>
<style lang="less" scoped>
.perview-header {
  width: 100%;
  height: 40px;
  background: rgba(0, 0, 0, 0.6);
  color: rgba(255, 255, 255, 0.8);
  line-height: 40px;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 101;
  padding: 10px;
  .left {
    flex-shrink: 0;
    font-size: 14px;
  }
  .center {
    text-align: center;
    flex: 1;
    padding: 0 20px;
  }
  .close {
    display: block;
    padding: 8px;
    width: 40px;
    height: 40px;
    cursor: pointer;
  }
}
.leftArrowCon {
  width: 30%;
  height: calc(100% - 40px);
  background: transparent;
  position: absolute;
  top: 40px;
  left: 0;
  z-index: 98;
  cursor: pointer;
}
.rightArrowCon {
  width: 30%;
  height: calc(100% - 40px);
  background: transparent;
  position: absolute;
  top: 40px;
  right: 0;
  z-index: 99;
  cursor: pointer;
}
.leftArrow {
  position: absolute;
  top: 50%;
  left: 30px;
  margin-top: -60px;
  transition: all 0.5s;
  width: 50px;
  height: 50px;
  pointer-events: none;
}
.rightArrow {
  position: absolute;
  top: 50%;
  right: 30px;
  margin-top: -60px;
  width: 50px;
  height: 50px;
  transition: all 0.5s;
  pointer-events: none;
}
.imgContainer .tips {
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  text-align: center;
  line-height: 40px;
  position: absolute;
  left: 50%;
  top: 50%;
  min-width: 150px;
  margin-left: -60px;
  margin-top: -20px;
  border-radius: 6px;
  padding: 4px 4px;
  font-size: 14px;
}
.fixedHandle {
  width: 800px;
  height: 140px;
  position: fixed;
  left: 50%;
  bottom: 0;
  margin-left: -400px;
  overflow: hidden;
  z-index: 100;
}
.handleContainer {
  width: 210px;
  height: 40px;
  background: rgba(0, 0, 0, 0.6);
  line-height: 40px;
  border-radius: 20px;
  position: absolute;
  left: 50%;
  bottom: 100px;
  padding: 0 14px;
  margin-left: -100px;
  img {
    display: block;
    width: 40px;
    height: 40px;
    padding: 8px;
    margin: 0 2px;
    cursor: pointer;
  }
}
.handleItem {
  width: 28px;
  height: 28px;
  color: white;
}
ul {
  padding: 0;
  margin: 0;
}
ul li {
  list-style: none;
  display: inline-block;
  width: 30px;
  height: 30px;
  margin-left: 20px;
  cursor: pointer;
}
.thumbnailContainer {
  max-width: 800px;
  background: rgba(255, 255, 255, 0.7);
  position: absolute;
  left: 50%;
  bottom: 0;
  border-top-left-radius: 5px;
  border-top-right-radius: 5px;
  transform: translate(-50%, 0%);
  overflow-x: auto;
  overflow-y: hidden;
}
.thumbnailContainer ul {
  padding-top: 10px;
  padding-bottom: 10px;
  text-align: center;
  white-space: nowrap;
}
.thumbnailContainer ul li {
  display: inline-block;
  width: 38px;
  height: 38px;
  box-sizing: content-box;
  margin-left: 10px;
  user-select: none;
}
.thumbnailContainer ul li:last-child {
  margin-right: 10px;
}
.thumbnailContainer ul li img {
  display: inline-block;
  width: 38px;
  height: 38px;
  border-radius: 3px;
  box-sizing: content-box;
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 1s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
/* 添加border */
.borderActive {
  box-shadow: 0px 4px 7px 0px rgb(241, 140, 112);
}
/* 修改原生的滚动条 */
::-webkit-scrollbar {
  /* 血槽宽度 */
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-thumb {
  /* 拖动条 */
  background: rgba(0, 0, 0, 0.3);
  border-radius: 6px;
}
::-webkit-scrollbar-track {
  /* 背景槽 */
  background: #ddd;
  border-radius: 6px;
}
/** 文件展示*/
.file-show {
  position: absolute;
  top: 60%;
  left: 50%;
  width: 450px;
  height: 260px;
  margin-top: -150px;
  margin-left: -225px;
  background-color: white;
  border-radius: 3px;
  padding: 0 80px;
  .file-icon {
    flex: 1;
    img {
      display: block;
      width: 100px;
    }
  }
  .file-handle {
    button {
      display: block;
      width: 120px;
      margin-left: 0;
      margin-right: 0;
      height: 34px;
    }
    button:first-child {
      margin-bottom: 20px;
    }
  }
}
</style>
src/directives/empty/empty.scss
New file
@@ -0,0 +1,7 @@
.xs-empty-parent--relative {
  position: relative !important
}
.xs-empty-parent--hidden {
  overflow: hidden !important
}
src/directives/empty/empty.vue
New file
@@ -0,0 +1,97 @@
<template>
  <div
    v-show="visible"
    :style="{ backgroundColor: background || '' }"
    :class="[customClass]"
    class="empty-mask">
    <div class="empty-content">
      <img
        v-if="iconUrl"
        :src="iconUrl"
        class="empty-icon" >
      <p
        v-if="showText"
        class="empty-text">{{ showText }}</p>
    </div>
  </div>
</template>
<script>
export default {
  data () {
    return {
      text: null,
      background: null,
      visible: false,
      icon: null,
      customClass: ''
    }
  },
  computed: {
    iconUrl: function () {
      /** 内置几个类型  当时none的时候  不展示 */
      if (this.icon) {
        if (this.icon === 'none') {
          return ''
        } else if (this.icon === 'nopermission') {
          return require('@/assets/img/nopermission.png')
        } else {
          return require('@/assets/img/empty.png')
        }
      } else {
        return require('@/assets/img/empty.png')
      }
    },
    showText: function () {
      /** 内置几个类型  当时none的时候  不展示 */
      if (this.text) {
        return this.text
      } else {
        return '没有找到数据'
      }
    }
  },
  methods: {
    setText (text) {
      if (text) {
        this.text = text
      }
    },
    setIcon (icon) {
      this.icon = icon
    }
  }
}
</script>
<style lang="scss" scoped>
.empty-mask {
  position: absolute;
  z-index: 2000;
  background-color: rgba(255, 255, 255, 0.98);
  margin: 0;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.empty-content {
  top: 50%;
  width: 100%;
  text-align: center;
  position: absolute;
}
.empty-text {
  margin: 3px 0;
  color: #aaa;
  font-size: 13px;
}
.empty-icon {
  display: block;
  width: 150px;
  margin: 0 auto 20px auto;
}
</style>
src/directives/empty/index.js
New file
@@ -0,0 +1,102 @@
/* eslint-disable no-mixed-operators */
import Vue from 'vue'
import Empty from './empty.vue'
import {
  addClass,
  removeClass,
  getStyle
} from 'element-ui/src/utils/dom'
const Mask = Vue.extend(Empty)
/**
 * xs-empty-text
 * 在绑定了v-empty指令的元素上添加xs-empty-text属性,其值会被渲染为加载文案,并显示在加载图标的下方
 * xs-empty-icon
 * 定义了几个类型  none 就是不展示icon 其他或者无值 就是一种效果
 * xs-empty-background
 * 背景色
 * xs-empty-custom-class
 * 类选择器样式 多个以空格分开
 */
const loadingDirective = {}
loadingDirective.install = Vue => {
  if (Vue.prototype.$isServer) return
  const toggleEmpty = (el, binding) => {
    /** 如果是数组 判断数组长度  否则 判断是否存在 当做Boolean */
    if ((Object.prototype.toString.call(binding.value) === '[object Array]' && binding.value.length === 0) ||
      (Object.prototype.toString.call(binding.value) !== '[object Array]' && binding.value)) {
      Vue.nextTick(() => {
        el.originalPosition = getStyle(el, 'position')
        insertDom(el, el, binding)
      })
    } else { // 移除效果
      el.domVisible = false
      removeClass(el, 'xs-empty-parent--relative')
      removeClass(el, 'xs-empty-parent--hidden')
      el.instance.visible = false
    }
  }
  const insertDom = (parent, el, binding) => {
    if (!el.domVisible && getStyle(el, 'display') !== 'none' && getStyle(el, 'visibility') !== 'hidden') {
      Object.keys(el.maskStyle).forEach(property => {
        el.mask.style[property] = el.maskStyle[property]
      })
      if (el.originalPosition !== 'absolute' && el.originalPosition !== 'fixed') {
        addClass(parent, 'xs-empty-parent--relative')
      }
      el.domVisible = true
      parent.appendChild(el.mask)
      Vue.nextTick(() => {
        el.instance.visible = true
      })
      el.domInserted = true
    }
  }
  Vue.directive('empty', {
    bind: function (el, binding, vnode) {
      const textExr = el.getAttribute('xs-empty-text')
      const iconExr = el.getAttribute('xs-empty-icon')
      const backgroundExr = el.getAttribute('xs-empty-background')
      const customClassExr = el.getAttribute('xs-empty-custom-class')
      const vm = vnode.context
      const mask = new Mask({
        el: document.createElement('div'),
        data: {
          text: vm && vm[textExr] || textExr,
          icon: vm && vm[iconExr] || iconExr,
          background: vm && vm[backgroundExr] || backgroundExr,
          customClass: vm && vm[customClassExr] || customClassExr
        }
      })
      el.instance = mask
      el.mask = mask.$el
      el.maskStyle = {}
      binding.value && toggleEmpty(el, binding)
    },
    update: function (el, binding) {
      el.instance.setText(el.getAttribute('xs-empty-text'))
      el.instance.setIcon(el.getAttribute('xs-empty-icon'))
      if (binding.oldValue !== binding.value) {
        toggleEmpty(el, binding)
      }
    },
    unbind: function (el, binding) {
      if (el.domInserted) {
        el.mask &&
          el.mask.parentNode &&
          el.mask.parentNode.removeChild(el.mask)
        toggleEmpty(el, {
          value: false,
          modifiers: binding.modifiers
        })
      }
    }
  })
}
export default loadingDirective
src/directives/focus.js
New file
@@ -0,0 +1,7 @@
const focus = {
  update (el) {
    el.querySelector('input').focus()
  }
}
export default focus
src/directives/index.js
New file
@@ -0,0 +1,24 @@
const clickoutside = {
  bind (el, binding, vnode) {
    function documentHandler (e) {
      // 这里判断点击的元素是否是本身,是本身,则返回
      if (el.contains(e.target)) {
        return false
      }
      // 判断指令中是否绑定了函数
      if (binding.expression) {
        binding.value(e)
      }
    }
    // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
    el.__vueClickOutside__ = documentHandler
    document.addEventListener('click', documentHandler)
  },
  unbind (el, binding) {
    // 解除事件监听
    document.removeEventListener('click', el.__vueClickOutside__)
    delete el.__vueClickOutside__
  }
}
export default clickoutside
src/directives/photo/index.js
New file
@@ -0,0 +1,91 @@
/* eslint-disable no-mixed-operators */
import Vue from 'vue'
import Photo from './photo.vue'
import {
  addClass,
  removeClass,
  getStyle
} from 'element-ui/src/utils/dom'
const Mask = Vue.extend(Photo)
const loadingDirective = {}
loadingDirective.install = Vue => {
  if (Vue.prototype.$isServer) return
  const togglePhoto = (el, binding) => {
    /** 如果是数组 判断数组长度  否则 判断是否存在 当做Boolean */
    if (binding.value && !binding.value.img) {
      Vue.nextTick(() => {
        el.originalPosition = getStyle(el, 'position')
        insertDom(el, el, binding)
      })
    } else { // 移除效果
      el.domVisible = false
      removeClass(el, 'xs-photo-parent--relative')
      removeClass(el, 'xs-photo-parent--hidden')
      el.instance.visible = false
    }
  }
  const insertDom = (parent, el, binding) => {
    if (!el.domVisible && getStyle(el, 'display') !== 'none' && getStyle(el, 'visibility') !== 'hidden') {
      Object.keys(el.maskStyle).forEach(property => {
        el.mask.style[property] = el.maskStyle[property]
      })
      if (el.originalPosition !== 'absolute' && el.originalPosition !== 'fixed') {
        addClass(parent, 'xs-photo-parent--relative')
      }
      el.domVisible = true
      parent.appendChild(el.mask)
      Vue.nextTick(() => {
        el.instance.visible = true
      })
      el.domInserted = true
    }
  }
  Vue.directive('photo', {
    bind: function (el, binding, vnode) {
      const vm = vnode.context
      let text = ''
      if (binding.value && !binding.value.img) {
        text = binding.value.realname && binding.value.realname.length > 2 ? binding.value.realname.substring(binding.value.realname.length - 2, binding.value.realname.length) : binding.value.realname
      }
      const mask = new Mask({
        el: document.createElement('div'),
        data: {
          text: vm && vm[text] || text
        }
      })
      el.instance = mask
      el.mask = mask.$el
      el.maskStyle = {}
      text && togglePhoto(el, binding)
    },
    update: function (el, binding) {
      let text = ''
      if (binding.value && !binding.value.img) {
        text = binding.value.realname && binding.value.realname.length > 2 ? binding.value.realname.substring(binding.value.realname.length - 2, binding.value.realname.length) : binding.value.realname
      }
      el.instance.setText(text)
      if (binding.oldValue !== binding.value) {
        togglePhoto(el, binding)
      }
    },
    unbind: function (el, binding) {
      if (el.domInserted) {
        el.mask &&
          el.mask.parentNode &&
          el.mask.parentNode.removeChild(el.mask)
        togglePhoto(el, {
          value: false,
          modifiers: binding.modifiers
        })
      }
    }
  })
}
export default loadingDirective
src/directives/photo/photo.scss
New file
@@ -0,0 +1,7 @@
.xs-photo-parent--relative {
  position: relative !important
}
.xs-photo-parent--hidden {
  overflow: hidden !important
}
src/directives/photo/photo.vue
New file
@@ -0,0 +1,79 @@
<template>
  <div
    v-show="visible"
    class="photo-wrap">
    <flexbox
      :style="{'font-size' : fontSize+'px'}"
      class="photo-content"
      justify="center"
      align="center">
      <div v-if="text">{{ text }}</div>
    </flexbox>
  </div>
</template>
<script>
export default {
  data () {
    return {
      text: null,
      visible: false,
      fontSize: 12
    }
  },
  computed: {},
  watch: {
    visible: function (params) {
      this.$nextTick(() => {
        if (this.$el.getBoundingClientRect().height > 0) {
          let fontSize = this.$el.getBoundingClientRect().height * 0.38
          if (fontSize > 40) {
            fontSize = 40
          }
          this.fontSize = fontSize
        } else {
          this.fontSize = 12
        }
      })
    }
  },
  mounted () {},
  methods: {
    setText (text) {
      if (text) {
        this.text = text
      }
    },
    setIcon (icon) {
      this.icon = icon
    }
  }
}
</script>
<style lang="scss" scoped>
.photo-wrap {
  position: absolute;
  z-index: 1;
  // background-color: white;
  margin: 0;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  .photo-content {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background-color: #2486e4;
    color: white;
    div {
      width: 100%;
      text-align: center;
      transform: scale(0.9, 0.9);
      max-height: 50px;
      overflow: hidden;
    }
  }
}
</style>
src/directives/scrollx/index.js
New file
@@ -0,0 +1,135 @@
// 盒子滚动条拖拽
import { on, off } from '@/utils/dom'
import Vue from 'vue'
import { debounce } from 'throttle-debounce'
let targetDrag = { // 托拽
  isDown: false,
  coord: {
    x: 0,
    y: 0
  }
}
let dom = null
let ignoreClass = [] // 忽略的类名
const scrollMousedown = event => {
  dom.style.cursor = 'pointer'
  targetDrag.isDown = true
  targetDrag.coord.x = event.pageX
  targetDrag.coord.y = event.pageY
}
const scrollMouseup = event => {
  dom.style.cursor = 'default'
  targetDrag.isDown = false
  targetDrag.coord.x = 0
  targetDrag.coord.y = 0
}
const scrollMousemove = event => {
  const movX = targetDrag.coord.x - event.pageX
  targetDrag.coord.x = event.pageX
  if (checkDomIsIgnore(event)) {
    dom.style.cursor = 'default'
    targetDrag.isDown = false
  } else if (targetDrag.isDown) {
    dom.scrollLeft = dom.scrollLeft + movX
  }
}
const scrollMouseout = event => {
  dom.style.cursor = 'default'
  targetDrag.isDown = false
}
const scrollMousewheel = event => {
  if (checkIsIgnore(event)) {
    dom.style.cursor = 'default'
    targetDrag.isDown = false
  } else {
    dom.scrollLeft += event.deltaY
  }
}
/**
 * 检查dom是否忽略
 * @param {*} e
 */
const checkDomIsIgnore = debounce(300, (e) => {
  let ignore = false
  ignoreClass.forEach(element => {
    var items = document.getElementsByClassName(element)
    if (items && !ignore) {
      for (let index = 0; index < items.length; index++) {
        const element = items[index]
        if (element.contains(e.target)) {
          ignore = true
          break
        }
      }
    }
  })
  return ignore
})
/**
 * 忽略滚轮
 * @param {*} e
 */
const checkIsIgnore = (e) => {
  let ignore = false
  ignoreClass.forEach(element => {
    var items = document.getElementsByClassName(element)
    if (items && !ignore) {
      for (let index = 0; index < items.length; index++) {
        const element = items[index]
        const rect = element.getBoundingClientRect()
        if ((e.clientY > rect.top && (e.clientY < (rect.top + rect.height))) && (e.clientX > rect.left && (e.clientX < (rect.left + rect.width)))) {
          ignore = true
          break
        }
      }
    }
  })
  return ignore
}
export default Vue.directive('scrollx', {
  bind: function (el, binding, vnode) {
    const valueData = binding.value
    ignoreClass = valueData.ignoreClass
  },
  inserted: function (el) {
    dom = el
    // 鼠标按下
    on(el, 'mousedown', scrollMousedown)
    on(el, 'mouseout', scrollMouseout)
    on(el, 'wheel', scrollMousewheel)
    // 鼠标释放
    on(el, 'mouseup', scrollMouseup)
    // 鼠标托拽
    on(el, 'mousemove', scrollMousemove)
  },
  unbind: function (el) {
    off(el, 'mousedown', scrollMousedown)
    off(el, 'mouseup', scrollMouseup)
    off(el, 'mouseout', scrollMouseout)
    off(el, 'wheel', scrollMousewheel)
    off(el, 'mousemove', scrollMousemove)
    // 清空
    targetDrag = { // 托拽
      isDown: false,
      coord: {
        x: 0,
        y: 0
      }
    }
  }
})
src/directives/style.scss
New file
@@ -0,0 +1,2 @@
@import './empty/empty.scss';
@import './photo/photo.scss';
src/filters/index.js
New file
@@ -0,0 +1,35 @@
// set function formatTime to filter
import {
  timestampToFormatTime,
  formatTimeToTimestamp
} from '@/utils'
/**
 * 时间戳到格式化时间
 * {{item.createTime|filterTimestampToFormatTime('MM-DD dddd')}}
 * @param {*} time
 * @param {*} cFormat
 */
export function filterTimestampToFormatTime (time, cFormat) {
  if (!cFormat) {
    cFormat = 'YYYY-MM-DD HH:mm'
  }
  if (!time || time === 0) {
    return ''
  }
  return timestampToFormatTime(time, cFormat)
}
/** 格式化时间到时间戳 */
export function filterFormatTimeToTimestamp (format) {
  return formatTimeToTimestamp(format)
}
/** 用户头像的占位图标 */
export function filterUserLazyImg (value) {
  return {
    src: value,
    error: require('@/assets/img/head.png'),
    loading: require('@/assets/img/loading.gif')
  }
}
src/main.js
New file
@@ -0,0 +1,88 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
// 组件ElementUI
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// vuex状态管理
import store from './store'
// 样式
import less from 'less'
import '@/styles/index.scss' // global css
import '@/styles/animate.css'
// 自定义全局点击空白处组件
import clickoutside from './directives' // global filters
import focus from './directives/focus'
import empty from './directives/empty'
import photo from './directives/photo'
import Lockr from 'lockr'
/** 常用flex组件 */
import {
  Flexbox,
  FlexboxItem
} from '@/components/flexbox'
/** 事件传递 */
import VueBus from 'vue-bus'
/** 懒加载图片 */
import VueLazyload from 'vue-lazyload'
import * as filters from './filters'
import moment from 'moment'
// 表情
import {
  emoji
} from './utils/emoji' // global filters
import fullCalendar from 'vue-fullcalendar'
// import cache from '@/utils/cache'
import 'lib-flexible'
// cache.loadingCache()
Vue.component('full-calendar', fullCalendar)
// 注册全局过滤器
Object.keys(filters).forEach(key => {
  Vue.filter(key, filters[key])
})
// 处理时间的过滤器
Vue.use(require('vue-moment'))
moment.locale('zh_cn')
Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: require('@/assets/img/send_img.png'),
  loading: require('@/assets/img/loading.gif'),
  attempt: 1
})
Vue.prototype.emoji = emoji
Vue.use(VueBus)
Vue.component('flexbox', Flexbox)
Vue.component('flexbox-item', FlexboxItem)
Vue.use(empty)
Vue.use(photo) // 本地存储插件
console.log(process.env.NODE_ENV)
window.Lockr = Lockr // 使用本地存储插件
Vue.directive('clickoutside', clickoutside)
Vue.directive('focus', focus)
Vue.use(ElementUI, {zIndex: 3000})
Vue.use(less)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})
src/router/index.js
New file
@@ -0,0 +1,190 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
const Login = () =>
    import('@/views/login/index')
const Logining = () =>
    import('@/views/login/logining')
const Home = () =>
    import('@/views/home/Home')
const Welcome = () =>
    import('@/views/welcome/Welcome')
    // 销售模块
const ClientsManage = () =>
    import('@/views/clients/customer/clientsManage')
const ClueIndex = () =>
    import('@/views/clients/clue/ClueIndex')
const ContactsIndex = () =>
    import('@/views/clients/contacts/ContactsIndex')
const BusinessIndex = () =>
    import('@/views/clients/business/BusinessIndex')
const ContractIndex = () =>
    import('@/views/clients/contract/ContractIndex')
const OfferIndex = () =>
    import('@/views/clients/offers/OfferIndex')
const ProductIndex = () =>
    import('@/views/clients/product/ProductIndex')
const EmployeeManage = () =>
    import('@/views/company/employeeManage/EmployeeManage')
const OffcialAuthority = () =>
    import('@/views/company/offcialAuthority')
const StaffLog = () =>
    import('@/views/company/staffLog')
const ApartmentManage = () =>
    import('@/views/company/ApartmentManage')
const SystemSetting = () =>
    import('@/views/company/systemSetting')
const ModuleManage = () =>
    import('@/views/module/ModuleManage')
    // 人事模块
const SealContractIndex = () =>
    import('@/views/clients/sealContract/SealContractIndex')
const SealOfferIndex = () =>
    import('@/views/clients/sealOffers/SealOfferIndex')
    // 商务模块
const BusinessCustomerManage = () =>
    import('@/views/clients/businessCustomer/BusinessCustomerManage')
const BusinessChancesIndex = () =>
    import('@/views/clients/businessChances/BusinessChancesIndex')
const BusinessContractsIndex = () =>
    import('@/views/clients/businessContracts/BusinessContractsIndex')
    // PWS API
const EwsAnalyze = () =>
    import('@/views/PWS/EwsAnalyze')
const Subscriptions = () =>
    import('@/views/PWS/Subscriptions')
Vue.use(VueRouter)
const routes = [{
  path: '',
  redirect: '/login'
},
{
  path: '/login',
  component: Login
},
{
  path: '/logining',
  component: Logining
},
{
  path: '/home',
  component: Home,
  redirect: '/welcome',
  children: [{
    path: '/welcome',
    component: Welcome
  },
  {
    path: '/ModuleManage',
    component: ModuleManage
  },
  {
    path: '/clientsManage',
    component: ClientsManage
  },
  {
    path: '/ClueIndex',
    component: ClueIndex
  },
  {
    path: '/ContactsIndex',
    component: ContactsIndex
  },
  {
    path: '/BusinessIndex',
    component: BusinessIndex
  },
  {
    path: '/ContractIndex',
    component: ContractIndex
  },
  {
    path: '/OfferIndex',
    component: OfferIndex
  },
  {
    path: '/SealContractIndex',
    component: SealContractIndex
  },
  {
    path: '/SealOfferIndex',
    component: SealOfferIndex
  },
  {
    path: '/BusinessCustomerManage',
    component: BusinessCustomerManage
  },
  {
    path: '/BusinessChancesIndex',
    component: BusinessChancesIndex
  },
  {
    path: '/BusinessContractsIndex',
    component: BusinessContractsIndex
  },
  {
    path: '/ProductIndex',
    component: ProductIndex
  },
  {
    path: '/ApartmentManage',
    component: ApartmentManage
  },
  {
    path: '/offcialAuthority',
    component: OffcialAuthority
  },
  {
    path: '/staffLog',
    component: StaffLog
  },
  {
    path: '/EmployeeManage',
    component: EmployeeManage
  },
  {
    path: '/systemSetting',
    component: SystemSetting
  },
  {
    path: '/ewsAnalyze',
    component: EwsAnalyze
  },
  {
    path: '/Subscriptions',
    component: Subscriptions
  }
  ]
}
]
const router = new VueRouter({
  routes,
  mode: 'hash'
})
// 路由导航守卫,在跳转前判断
router.beforeEach((to, from, next) => {
  if (window.location.href.indexOf('code') >= 0) { // 如果code存在
    // 如果url中包含code   split?分割成数组,取第二个
    let code = window.location.href.split('?')[1]
    console.log(window.location.href)
    code = code.substring(5, code.indexOf('&')) // 截取字符串第6位开始截取直到&出现截取成功
    console.log(code)
    sessionStorage.setItem('code', code)
    next()
  } else {
    if (to.path === '/login') { // 如果是登录页
      localStorage.removeItem('token')
    }
    if (!localStorage.getItem('token') && to.path !== '/login') { // 如果token不存在 并且 不是mylogin页面
      next({ path: '/login' })
    } else {
      next()
    }
  }
})
export default router
src/store/getters.js
New file
@@ -0,0 +1,48 @@
const getters = {
  moduleBlock: state => state.user.moduleBlock
  // userInfo: state => state.user.userInfo,
  // lang: state => state.app.lang,
  // logo: state => {
  //   if (state.app.logo) {
  //     return state.app.logo
  //   }
  //   return require('@/assets/img/logo.jpg')
  // },
  // name: state => {
  //   if (state.app.name) {
  //     return state.app.name
  //   }
  //   return '东晨工元CRM系统'
  // },
  // activeIndex: state => state.app.sidebar.activeIndex,
  // navActiveIndex: state => state.app.navbar.activeIndex,
  // // 权限
  // allAuth: state => state.user.allAuth,
  // crm: state => state.user.crm,
  // bi: state => state.user.bi,
  // manage: state => state.user.manage,
  // oa: state => state.user.oa,
  // project: state => state.user.project,
  // // 路由
  // addRouters: state => state.permission.addRouters,
  // oaRouters: state => state.permission.oaRouters,
  // crmRouters: state => state.permission.crmRouters,
  // biRouters: state => state.permission.biRouters,
  // manageRouters: state => state.permission.manageRouters,
  // // 客户管理信息
  // messageNum: state => state.customer.messageNum,
  // messageOANum: state => state.oa.messageOANum,
  // // 配置信息
  // CRMConfig: state => state.app.CRMConfig
}
/**
 * 使用说明
 * import { mapGetters } from 'vuex'
 * computed: {
    ...mapGetters([
      'userInfo'
    ])
  }
 */
export default getters
src/store/index.js
New file
@@ -0,0 +1,24 @@
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
// import permission from './modules/permission'
// import app from './modules/app'
// import oa from './modules/oa'
// import customer from './modules/customer'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
  modules: {
    // app,
    // permission,
    // oa,
    user
    // customer
  },
  getters
})
export default store
src/store/modules/app.js
New file
@@ -0,0 +1,85 @@
// import {
//   adminSystemIndex
// } from '@/api/systemManagement/SystemConfig'
// import {
//   crmSettingConfigData
// } from '@/api/systemManagement/SystemCustomer'
// import Lockr from 'lockr'
/** 记录 侧边索引 */
const app = {
  state: {
    logo: '',
    name: '',
    lang: localStorage.lang || 'cn',
    sidebar: {
      activeIndex: '' // 目前激活的 行
    },
    navbar: {
      activeIndex: '' // 导航目前是第几个 个人中心需要
    },
    /** CRM配置信息 */
    CRMConfig: {}
  },
  mutations: {
    SET_ACTIVEINDEX: (state, path) => {
      state.sidebar.activeIndex = path
    },
    SET_NAVACTIVEINDEX: (state, path) => {
      state.navbar.activeIndex = path
    },
    SET_APPLOGO: (state, logo) => {
      state.logo = logo
    },
    SET_APPNAME: (state, name) => {
      state.name = name
    },
    SET_LANG: (state, lang) => {
      state.lang = lang
      window.app.$i18n.locale = lang
      localStorage.setItem('lang', lang)
      window.location.reload()
    },
    SET_CRMCONFIG: (state, config) => {
      state.CRMConfig = config
    }
  },
  actions: {
    // 登录
    SystemLogoAndName ({
      commit
    }) {
      return new Promise((resolve, reject) => {
        // adminSystemIndex().then(response => {
        //   commit('SET_APPNAME', response.data.name)
        //   commit('SET_APPLOGO', response.data.logo)
        //   Lockr.set('systemLogo', response.data.logo)
        //   Lockr.set('systemName', response.data.name)
        //   resolve(response)
        // }).catch(error => {
        //   reject(error)
        // })
      })
    },
    /**
     * 获取客户管理配置
     */
    CRMSettingConfig ({
      commit
    }) {
      return new Promise((resolve, reject) => {
        // crmSettingConfigData().then(response => {
        //   commit('SET_CRMCONFIG', response.data)
        //   resolve(response)
        // }).catch(error => {
        //   reject(error)
        // })
      })
    }
  }
}
export default app
src/store/modules/customer.js
New file
@@ -0,0 +1,61 @@
// import {
//   crmMessagNumAPI
// } from '@/api/clients/message'
/**
 * 消息记录
 */
const app = {
  state: {
    // 待办事项消息
    messageNum: {
      todayCustomer: 0,
      followLeads: 0,
      followCustomer: 0,
      checkContract: 0,
      checkReceivables: 0,
      remindReceivablesPlan: 0,
      endContract: 0,
      totalNum: 0
    }
  },
  mutations: {
    /**
     * 更改待办事项
     */
    SET_MESSAGENUM: (state, messageNum) => {
      let totalNum = 0
      for (const key in messageNum) {
        if (key !== 'totalNum') {
          totalNum += (messageNum[key] || 0)
        }
      }
      messageNum.totalNum = totalNum
      state.messageNum = messageNum
    }
  },
  actions: {
    // 登录
    // GetMessageNum({
    //   state,
    //   commit
    // }) {
    //   return new Promise((resolve, reject) => {
    //     crmMessagNumAPI()
    //       .then(response => {
    //         commit('SET_MESSAGENUM', response.data)
    //         commit('SET_CRMROUTERSNUM', state.messageNum.totalNum)
    //         resolve(response)
    //       })
    //       .catch(error => {
    //         reject(error)
    //       })
    //   })
    // }
  }
}
export default app
src/store/modules/oa.js
New file
@@ -0,0 +1,70 @@
import {
  oaMessageNumAPI
} from '@/api/oamanagement/workbench'
import {
  objDeepCopy
} from '@/utils'
/**
 * 消息记录
 */
const oa = {
  state: {
    // 待办事项消息
    messageOANum: {
      eventNum: 0,
      taskNum: 0,
      announcementNum: 0,
      logNum: 0,
      examineNum: 0
    }
  },
  mutations: {
    /**
     * 更改待办事项
     */
    SET_MESSAGEOANUM: (state, messageOANum) => {
      state.messageOANum = messageOANum
    }
  },
  actions: {
    /**
     * 获取待办消息数
     * @param {*} param
     */
    GetOAMessageNum({
      state,
      commit
    }, type) {
      return new Promise((resolve, reject) => {
        const params = {}
        if (type) {
          params.type = type
        }
        oaMessageNumAPI(params)
          .then(response => {
            if (type) {
              const copyNum = objDeepCopy(state.messageOANum)
              copyNum[type + 'Num'] = response.data[type + 'Num'] || 0
              commit('SET_MESSAGEOANUM', copyNum)
            } else {
              commit('SET_MESSAGEOANUM', response.data)
            }
            if (resolve) {
              resolve(response)
            }
          })
          .catch(error => {
            if (reject) {
              reject(error)
            }
          })
      })
    }
  }
}
export default oa
src/store/modules/permission.js
New file
@@ -0,0 +1,141 @@
import {
  asyncRouterMap
} from '@/router'
import Vue from 'vue'
/**
 *
 * @param {*} router
 * @param {*} authInfo
 */
function checkAuth(router, authInfo) {
  // 判断当前路由在权限数组中是否存在
  if (router.meta) {
    const metaInfo = router.meta
    if (!metaInfo.requiresAuth) {
      return true
    } else {
      if (metaInfo.index === 0) {
        return !!authInfo[metaInfo.type]
      } else if (metaInfo.index === 1) {
        if (authInfo[metaInfo.type]) {
          return !!authInfo[metaInfo.type][metaInfo.subType]
        }
        return false
      } else {
        var typeAuth = authInfo[metaInfo.type]
        for (let index = 0; index < metaInfo.subType.length; index++) {
          const field = metaInfo.subType[index]
          typeAuth = typeAuth[field]
          if (typeAuth && metaInfo.subType.length - 1 === index) {
            return true
          } else if (!typeAuth) {
            return false
          }
        }
      }
    }
  }
  return true
}
/**
 *
 * @param {*} routers
 * @param {*} authInfo
 */
const filterAsyncRouter = function(routers, authInfo) {
  const res = []
  routers.forEach(router => {
    const tmp = {
      ...router
    }
    if (checkAuth(tmp, authInfo)) {
      if (tmp.children) {
        tmp.children = filterAsyncRouter(tmp.children, authInfo)
      }
      res.push(tmp)
    }
  })
  return res
}
const permission = {
  state: {
    addRouters: [],
    crmRouters: {
      name: 'crm',
      children: []
    },
    biRouters: {
      name: 'bi',
      children: []
    },
    manageRouters: {
      name: 'manager',
      children: []
    },
    oaRouters: {
      name: 'oa',
      children: []
    }
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      for (let index = 0; index < routers.length; index++) {
        const element = routers[index]
        if (element.name === 'oa') {
          state.oaRouters = element
        } else if (element.name === 'crm') {
          state.crmRouters = element
        } else if (element.name === 'bi') {
          state.biRouters = element
        } else if (element.name === 'manager') {
          state.manageRouters = element
        }
      }
    },
    /**
     * 客户管理待办消息数
     */
    SET_CRMROUTERSNUM: (state, num) => {
      const messageItem = state.crmRouters.children[1]
      messageItem.meta.num = num
      Vue.set(state.crmRouters.children, 1, messageItem)
    }
  },
  actions: {
    GenerateRoutes({
      commit
    }, data) {
      return new Promise(resolve => {
        const accessedRouters = filterAsyncRouter(asyncRouterMap, data)
        let redirect = ''
        for (let index = 0; index < accessedRouters.length; index++) {
          const element = accessedRouters[index]
          if (element.children && element.children.length > 0) {
            element.redirect = element.path + '/' + element.children[0].path
          }
          // 获取跳转
          if (element.redirect && !redirect) {
            redirect = element.redirect
          }
        }
        if (redirect) {
          accessedRouters.push({
            path: '/',
            redirect: redirect,
            hidden: true
          })
        }
        commit('SET_ROUTERS', accessedRouters)
        resolve()
      })
    }
  }
}
export default permission
src/store/modules/user.js
New file
@@ -0,0 +1,134 @@
// import {
//   login
// } from '@/api/login'
// import {
//   adminIndexAuthList
// } from '@/api/common'
// import {
//   adminUsersRead
// } from '@/api/personCenter/personCenter'
// import {
// addAuth,
// removeAuth
// } from '@/utils/auth'
import Lockr from 'lockr'
import { GetCurrentUserModules } from '@/api/moduleManage/moduleManage'
const user = {
  state: {
    userInfo: null, // 用户信息
    // 权限信息
    allAuth: null, // 总权限信息 默认空 调整动态路由
    crm: {}, // 客户管理
    bi: {}, // 商业智能
    manage: {}, // 管理后台
    oa: {}, // 办公
    project: {}, // 项目管理
    moduleBlock: {} // 模块管理
  },
  mutations: {
    SET_USERINFO: (state, userInfo) => {
      state.userInfo = userInfo
    },
    SET_ALLAUTH: (state, allAuth) => {
      state.allAuth = allAuth
    },
    SET_CRM: (state, crm) => {
      state.crm = crm
    },
    SET_BI: (state, bi) => {
      state.bi = bi
    },
    SET_MANAGE: (state, manage) => {
      state.manage = manage
    },
    SET_OA: (state, oa) => {
      state.oa = oa
    },
    SET_PROJECT: (state, project) => {
      state.project = project
    },
    SET_MODULE: (state, moduleBlock) => {
      state.moduleBlock = moduleBlock
    }
  },
  actions: {
    // 登录
    Login ({
      commit
    }, userInfo) {
      return new Promise((resolve, reject) => {
        // login(userInfo).then(data => {
        // Lockr.set('Admin-Token', data['Admin-Token'])
        // Lockr.set('loginUserInfo', data.user)
        // Lockr.set('authList', data.auth)
        // addAuth(data['Admin-Token'])
        // commit('SET_USERINFO', data.user)
        // // 权限
        // commit('SET_ALLAUTH', data.auth)
        // commit('SET_CRM', data.auth.crm)
        // commit('SET_BI', data.auth.bi)
        // commit('SET_MANAGE', data.auth.manage)
        // commit('SET_OA', data.auth.oa)
        // commit('SET_PROJECT', data.auth.project)
        //   resolve(data)
        // }).catch(error => {
        //   reject(error)
        // })
      })
    },
    // 获取权限
    getAuth ({
      commit
    }) {
      return new Promise((resolve, reject) => {
        GetCurrentUserModules().then((response) => {
          const data = response.data.Result
          Lockr.set('authList', data)
          commit('SET_MODULE', data)
          resolve(data)
        }).catch(error => {
          reject(error)
        })
      })
    },
    // 获取用户信息
    GetUserInfo ({
      commit,
      state
    }) {
      return new Promise((resolve, reject) => {
        // adminUsersRead().then(response => {
        //   commit('SET_USERINFO', response.data)
        //   resolve(response)
        // }).catch(error => {
        //   reject(error)
        // })
      })
    },
    // 登出
    LogOut ({
      commit
    }) {
      return new Promise((resolve, reject) => {
        // logout().then(() => {
        //   /** flush 清空localStorage .rm('authKey') 按照key清除 */
        //   removeAuth()
        //   resolve()
        // }).catch(error => {
        //   reject(error)
        // })
      })
    }
  }
}
export default user
src/styles/animate.css
New file
@@ -0,0 +1,3623 @@
@charset "UTF-8";
/*!
 * animate.css -http://daneden.me/animate
 * Version - 3.7.0
 * Licensed under the MIT license - http://opensource.org/licenses/MIT
 *
 * Copyright (c) 2018 Daniel Eden
 */
@-webkit-keyframes bounce {
  from,
  20%,
  53%,
  80%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  40%,
  43% {
    -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    -webkit-transform: translate3d(0, -30px, 0);
    transform: translate3d(0, -30px, 0);
  }
  70% {
    -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    -webkit-transform: translate3d(0, -15px, 0);
    transform: translate3d(0, -15px, 0);
  }
  90% {
    -webkit-transform: translate3d(0, -4px, 0);
    transform: translate3d(0, -4px, 0);
  }
}
@keyframes bounce {
  from,
  20%,
  53%,
  80%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  40%,
  43% {
    -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    -webkit-transform: translate3d(0, -30px, 0);
    transform: translate3d(0, -30px, 0);
  }
  70% {
    -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
    -webkit-transform: translate3d(0, -15px, 0);
    transform: translate3d(0, -15px, 0);
  }
  90% {
    -webkit-transform: translate3d(0, -4px, 0);
    transform: translate3d(0, -4px, 0);
  }
}
.bounce {
  -webkit-animation-name: bounce;
  animation-name: bounce;
  -webkit-transform-origin: center bottom;
  transform-origin: center bottom;
}
@-webkit-keyframes flash {
  from,
  50%,
  to {
    opacity: 1;
  }
  25%,
  75% {
    opacity: 0;
  }
}
@keyframes flash {
  from,
  50%,
  to {
    opacity: 1;
  }
  25%,
  75% {
    opacity: 0;
  }
}
.flash {
  -webkit-animation-name: flash;
  animation-name: flash;
}
/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
@-webkit-keyframes pulse {
  from {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
  50% {
    -webkit-transform: scale3d(1.05, 1.05, 1.05);
    transform: scale3d(1.05, 1.05, 1.05);
  }
  to {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
@keyframes pulse {
  from {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
  50% {
    -webkit-transform: scale3d(1.05, 1.05, 1.05);
    transform: scale3d(1.05, 1.05, 1.05);
  }
  to {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
.pulse {
  -webkit-animation-name: pulse;
  animation-name: pulse;
}
@-webkit-keyframes rubberBand {
  from {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
  30% {
    -webkit-transform: scale3d(1.25, 0.75, 1);
    transform: scale3d(1.25, 0.75, 1);
  }
  40% {
    -webkit-transform: scale3d(0.75, 1.25, 1);
    transform: scale3d(0.75, 1.25, 1);
  }
  50% {
    -webkit-transform: scale3d(1.15, 0.85, 1);
    transform: scale3d(1.15, 0.85, 1);
  }
  65% {
    -webkit-transform: scale3d(0.95, 1.05, 1);
    transform: scale3d(0.95, 1.05, 1);
  }
  75% {
    -webkit-transform: scale3d(1.05, 0.95, 1);
    transform: scale3d(1.05, 0.95, 1);
  }
  to {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
@keyframes rubberBand {
  from {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
  30% {
    -webkit-transform: scale3d(1.25, 0.75, 1);
    transform: scale3d(1.25, 0.75, 1);
  }
  40% {
    -webkit-transform: scale3d(0.75, 1.25, 1);
    transform: scale3d(0.75, 1.25, 1);
  }
  50% {
    -webkit-transform: scale3d(1.15, 0.85, 1);
    transform: scale3d(1.15, 0.85, 1);
  }
  65% {
    -webkit-transform: scale3d(0.95, 1.05, 1);
    transform: scale3d(0.95, 1.05, 1);
  }
  75% {
    -webkit-transform: scale3d(1.05, 0.95, 1);
    transform: scale3d(1.05, 0.95, 1);
  }
  to {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
.rubberBand {
  -webkit-animation-name: rubberBand;
  animation-name: rubberBand;
}
@-webkit-keyframes shake {
  from,
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  10%,
  30%,
  50%,
  70%,
  90% {
    -webkit-transform: translate3d(-10px, 0, 0);
    transform: translate3d(-10px, 0, 0);
  }
  20%,
  40%,
  60%,
  80% {
    -webkit-transform: translate3d(10px, 0, 0);
    transform: translate3d(10px, 0, 0);
  }
}
@keyframes shake {
  from,
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  10%,
  30%,
  50%,
  70%,
  90% {
    -webkit-transform: translate3d(-10px, 0, 0);
    transform: translate3d(-10px, 0, 0);
  }
  20%,
  40%,
  60%,
  80% {
    -webkit-transform: translate3d(10px, 0, 0);
    transform: translate3d(10px, 0, 0);
  }
}
.shake {
  -webkit-animation-name: shake;
  animation-name: shake;
}
@-webkit-keyframes headShake {
  0% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
  6.5% {
    -webkit-transform: translateX(-6px) rotateY(-9deg);
    transform: translateX(-6px) rotateY(-9deg);
  }
  18.5% {
    -webkit-transform: translateX(5px) rotateY(7deg);
    transform: translateX(5px) rotateY(7deg);
  }
  31.5% {
    -webkit-transform: translateX(-3px) rotateY(-5deg);
    transform: translateX(-3px) rotateY(-5deg);
  }
  43.5% {
    -webkit-transform: translateX(2px) rotateY(3deg);
    transform: translateX(2px) rotateY(3deg);
  }
  50% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
@keyframes headShake {
  0% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
  6.5% {
    -webkit-transform: translateX(-6px) rotateY(-9deg);
    transform: translateX(-6px) rotateY(-9deg);
  }
  18.5% {
    -webkit-transform: translateX(5px) rotateY(7deg);
    transform: translateX(5px) rotateY(7deg);
  }
  31.5% {
    -webkit-transform: translateX(-3px) rotateY(-5deg);
    transform: translateX(-3px) rotateY(-5deg);
  }
  43.5% {
    -webkit-transform: translateX(2px) rotateY(3deg);
    transform: translateX(2px) rotateY(3deg);
  }
  50% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
  }
}
.headShake {
  -webkit-animation-timing-function: ease-in-out;
  animation-timing-function: ease-in-out;
  -webkit-animation-name: headShake;
  animation-name: headShake;
}
@-webkit-keyframes swing {
  20% {
    -webkit-transform: rotate3d(0, 0, 1, 15deg);
    transform: rotate3d(0, 0, 1, 15deg);
  }
  40% {
    -webkit-transform: rotate3d(0, 0, 1, -10deg);
    transform: rotate3d(0, 0, 1, -10deg);
  }
  60% {
    -webkit-transform: rotate3d(0, 0, 1, 5deg);
    transform: rotate3d(0, 0, 1, 5deg);
  }
  80% {
    -webkit-transform: rotate3d(0, 0, 1, -5deg);
    transform: rotate3d(0, 0, 1, -5deg);
  }
  to {
    -webkit-transform: rotate3d(0, 0, 1, 0deg);
    transform: rotate3d(0, 0, 1, 0deg);
  }
}
@keyframes swing {
  20% {
    -webkit-transform: rotate3d(0, 0, 1, 15deg);
    transform: rotate3d(0, 0, 1, 15deg);
  }
  40% {
    -webkit-transform: rotate3d(0, 0, 1, -10deg);
    transform: rotate3d(0, 0, 1, -10deg);
  }
  60% {
    -webkit-transform: rotate3d(0, 0, 1, 5deg);
    transform: rotate3d(0, 0, 1, 5deg);
  }
  80% {
    -webkit-transform: rotate3d(0, 0, 1, -5deg);
    transform: rotate3d(0, 0, 1, -5deg);
  }
  to {
    -webkit-transform: rotate3d(0, 0, 1, 0deg);
    transform: rotate3d(0, 0, 1, 0deg);
  }
}
.swing {
  -webkit-transform-origin: top center;
  transform-origin: top center;
  -webkit-animation-name: swing;
  animation-name: swing;
}
@-webkit-keyframes tada {
  from {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
  10%,
  20% {
    -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
    transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
  }
  30%,
  50%,
  70%,
  90% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
  }
  40%,
  60%,
  80% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
  }
  to {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
@keyframes tada {
  from {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
  10%,
  20% {
    -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
    transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
  }
  30%,
  50%,
  70%,
  90% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
  }
  40%,
  60%,
  80% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
  }
  to {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
.tada {
  -webkit-animation-name: tada;
  animation-name: tada;
}
/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
@-webkit-keyframes wobble {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  15% {
    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
  }
  30% {
    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
  }
  45% {
    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
  }
  60% {
    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
  }
  75% {
    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes wobble {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  15% {
    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
  }
  30% {
    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
  }
  45% {
    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
  }
  60% {
    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
  }
  75% {
    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.wobble {
  -webkit-animation-name: wobble;
  animation-name: wobble;
}
@-webkit-keyframes jello {
  from,
  11.1%,
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  22.2% {
    -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
    transform: skewX(-12.5deg) skewY(-12.5deg);
  }
  33.3% {
    -webkit-transform: skewX(6.25deg) skewY(6.25deg);
    transform: skewX(6.25deg) skewY(6.25deg);
  }
  44.4% {
    -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
    transform: skewX(-3.125deg) skewY(-3.125deg);
  }
  55.5% {
    -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
    transform: skewX(1.5625deg) skewY(1.5625deg);
  }
  66.6% {
    -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
    transform: skewX(-0.78125deg) skewY(-0.78125deg);
  }
  77.7% {
    -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
    transform: skewX(0.390625deg) skewY(0.390625deg);
  }
  88.8% {
    -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
    transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
  }
}
@keyframes jello {
  from,
  11.1%,
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  22.2% {
    -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
    transform: skewX(-12.5deg) skewY(-12.5deg);
  }
  33.3% {
    -webkit-transform: skewX(6.25deg) skewY(6.25deg);
    transform: skewX(6.25deg) skewY(6.25deg);
  }
  44.4% {
    -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
    transform: skewX(-3.125deg) skewY(-3.125deg);
  }
  55.5% {
    -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
    transform: skewX(1.5625deg) skewY(1.5625deg);
  }
  66.6% {
    -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
    transform: skewX(-0.78125deg) skewY(-0.78125deg);
  }
  77.7% {
    -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
    transform: skewX(0.390625deg) skewY(0.390625deg);
  }
  88.8% {
    -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
    transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
  }
}
.jello {
  -webkit-animation-name: jello;
  animation-name: jello;
  -webkit-transform-origin: center;
  transform-origin: center;
}
@-webkit-keyframes heartBeat {
  0% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
  14% {
    -webkit-transform: scale(1.3);
    transform: scale(1.3);
  }
  28% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
  42% {
    -webkit-transform: scale(1.3);
    transform: scale(1.3);
  }
  70% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}
@keyframes heartBeat {
  0% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
  14% {
    -webkit-transform: scale(1.3);
    transform: scale(1.3);
  }
  28% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
  42% {
    -webkit-transform: scale(1.3);
    transform: scale(1.3);
  }
  70% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}
.heartBeat {
  -webkit-animation-name: heartBeat;
  animation-name: heartBeat;
  -webkit-animation-duration: 1.3s;
  animation-duration: 1.3s;
  -webkit-animation-timing-function: ease-in-out;
  animation-timing-function: ease-in-out;
}
@-webkit-keyframes bounceIn {
  from,
  20%,
  40%,
  60%,
  80%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  0% {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
  20% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1);
    transform: scale3d(1.1, 1.1, 1.1);
  }
  40% {
    -webkit-transform: scale3d(0.9, 0.9, 0.9);
    transform: scale3d(0.9, 0.9, 0.9);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(1.03, 1.03, 1.03);
    transform: scale3d(1.03, 1.03, 1.03);
  }
  80% {
    -webkit-transform: scale3d(0.97, 0.97, 0.97);
    transform: scale3d(0.97, 0.97, 0.97);
  }
  to {
    opacity: 1;
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
@keyframes bounceIn {
  from,
  20%,
  40%,
  60%,
  80%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  0% {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
  20% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1);
    transform: scale3d(1.1, 1.1, 1.1);
  }
  40% {
    -webkit-transform: scale3d(0.9, 0.9, 0.9);
    transform: scale3d(0.9, 0.9, 0.9);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(1.03, 1.03, 1.03);
    transform: scale3d(1.03, 1.03, 1.03);
  }
  80% {
    -webkit-transform: scale3d(0.97, 0.97, 0.97);
    transform: scale3d(0.97, 0.97, 0.97);
  }
  to {
    opacity: 1;
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}
.bounceIn {
  -webkit-animation-duration: 0.75s;
  animation-duration: 0.75s;
  -webkit-animation-name: bounceIn;
  animation-name: bounceIn;
}
@-webkit-keyframes bounceInDown {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, -3000px, 0);
    transform: translate3d(0, -3000px, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(0, 25px, 0);
    transform: translate3d(0, 25px, 0);
  }
  75% {
    -webkit-transform: translate3d(0, -10px, 0);
    transform: translate3d(0, -10px, 0);
  }
  90% {
    -webkit-transform: translate3d(0, 5px, 0);
    transform: translate3d(0, 5px, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes bounceInDown {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  0% {
    opacity: 0;
    -webkit-transform: translate3d(0, -3000px, 0);
    transform: translate3d(0, -3000px, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(0, 25px, 0);
    transform: translate3d(0, 25px, 0);
  }
  75% {
    -webkit-transform: translate3d(0, -10px, 0);
    transform: translate3d(0, -10px, 0);
  }
  90% {
    -webkit-transform: translate3d(0, 5px, 0);
    transform: translate3d(0, 5px, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.bounceInDown {
  -webkit-animation-name: bounceInDown;
  animation-name: bounceInDown;
}
@-webkit-keyframes bounceInLeft {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  0% {
    opacity: 0;
    -webkit-transform: translate3d(-3000px, 0, 0);
    transform: translate3d(-3000px, 0, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(25px, 0, 0);
    transform: translate3d(25px, 0, 0);
  }
  75% {
    -webkit-transform: translate3d(-10px, 0, 0);
    transform: translate3d(-10px, 0, 0);
  }
  90% {
    -webkit-transform: translate3d(5px, 0, 0);
    transform: translate3d(5px, 0, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes bounceInLeft {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  0% {
    opacity: 0;
    -webkit-transform: translate3d(-3000px, 0, 0);
    transform: translate3d(-3000px, 0, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(25px, 0, 0);
    transform: translate3d(25px, 0, 0);
  }
  75% {
    -webkit-transform: translate3d(-10px, 0, 0);
    transform: translate3d(-10px, 0, 0);
  }
  90% {
    -webkit-transform: translate3d(5px, 0, 0);
    transform: translate3d(5px, 0, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.bounceInLeft {
  -webkit-animation-name: bounceInLeft;
  animation-name: bounceInLeft;
}
@-webkit-keyframes bounceInRight {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  from {
    opacity: 0;
    -webkit-transform: translate3d(3000px, 0, 0);
    transform: translate3d(3000px, 0, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(-25px, 0, 0);
    transform: translate3d(-25px, 0, 0);
  }
  75% {
    -webkit-transform: translate3d(10px, 0, 0);
    transform: translate3d(10px, 0, 0);
  }
  90% {
    -webkit-transform: translate3d(-5px, 0, 0);
    transform: translate3d(-5px, 0, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes bounceInRight {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  from {
    opacity: 0;
    -webkit-transform: translate3d(3000px, 0, 0);
    transform: translate3d(3000px, 0, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(-25px, 0, 0);
    transform: translate3d(-25px, 0, 0);
  }
  75% {
    -webkit-transform: translate3d(10px, 0, 0);
    transform: translate3d(10px, 0, 0);
  }
  90% {
    -webkit-transform: translate3d(-5px, 0, 0);
    transform: translate3d(-5px, 0, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.bounceInRight {
  -webkit-animation-name: bounceInRight;
  animation-name: bounceInRight;
}
@-webkit-keyframes bounceInUp {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 3000px, 0);
    transform: translate3d(0, 3000px, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(0, -20px, 0);
    transform: translate3d(0, -20px, 0);
  }
  75% {
    -webkit-transform: translate3d(0, 10px, 0);
    transform: translate3d(0, 10px, 0);
  }
  90% {
    -webkit-transform: translate3d(0, -5px, 0);
    transform: translate3d(0, -5px, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes bounceInUp {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 3000px, 0);
    transform: translate3d(0, 3000px, 0);
  }
  60% {
    opacity: 1;
    -webkit-transform: translate3d(0, -20px, 0);
    transform: translate3d(0, -20px, 0);
  }
  75% {
    -webkit-transform: translate3d(0, 10px, 0);
    transform: translate3d(0, 10px, 0);
  }
  90% {
    -webkit-transform: translate3d(0, -5px, 0);
    transform: translate3d(0, -5px, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.bounceInUp {
  -webkit-animation-name: bounceInUp;
  animation-name: bounceInUp;
}
@-webkit-keyframes bounceOut {
  20% {
    -webkit-transform: scale3d(0.9, 0.9, 0.9);
    transform: scale3d(0.9, 0.9, 0.9);
  }
  50%,
  55% {
    opacity: 1;
    -webkit-transform: scale3d(1.1, 1.1, 1.1);
    transform: scale3d(1.1, 1.1, 1.1);
  }
  to {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
}
@keyframes bounceOut {
  20% {
    -webkit-transform: scale3d(0.9, 0.9, 0.9);
    transform: scale3d(0.9, 0.9, 0.9);
  }
  50%,
  55% {
    opacity: 1;
    -webkit-transform: scale3d(1.1, 1.1, 1.1);
    transform: scale3d(1.1, 1.1, 1.1);
  }
  to {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
}
.bounceOut {
  -webkit-animation-duration: 0.75s;
  animation-duration: 0.75s;
  -webkit-animation-name: bounceOut;
  animation-name: bounceOut;
}
@-webkit-keyframes bounceOutDown {
  20% {
    -webkit-transform: translate3d(0, 10px, 0);
    transform: translate3d(0, 10px, 0);
  }
  40%,
  45% {
    opacity: 1;
    -webkit-transform: translate3d(0, -20px, 0);
    transform: translate3d(0, -20px, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0);
  }
}
@keyframes bounceOutDown {
  20% {
    -webkit-transform: translate3d(0, 10px, 0);
    transform: translate3d(0, 10px, 0);
  }
  40%,
  45% {
    opacity: 1;
    -webkit-transform: translate3d(0, -20px, 0);
    transform: translate3d(0, -20px, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0);
  }
}
.bounceOutDown {
  -webkit-animation-name: bounceOutDown;
  animation-name: bounceOutDown;
}
@-webkit-keyframes bounceOutLeft {
  20% {
    opacity: 1;
    -webkit-transform: translate3d(20px, 0, 0);
    transform: translate3d(20px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(-2000px, 0, 0);
    transform: translate3d(-2000px, 0, 0);
  }
}
@keyframes bounceOutLeft {
  20% {
    opacity: 1;
    -webkit-transform: translate3d(20px, 0, 0);
    transform: translate3d(20px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(-2000px, 0, 0);
    transform: translate3d(-2000px, 0, 0);
  }
}
.bounceOutLeft {
  -webkit-animation-name: bounceOutLeft;
  animation-name: bounceOutLeft;
}
@-webkit-keyframes bounceOutRight {
  20% {
    opacity: 1;
    -webkit-transform: translate3d(-20px, 0, 0);
    transform: translate3d(-20px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(2000px, 0, 0);
    transform: translate3d(2000px, 0, 0);
  }
}
@keyframes bounceOutRight {
  20% {
    opacity: 1;
    -webkit-transform: translate3d(-20px, 0, 0);
    transform: translate3d(-20px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(2000px, 0, 0);
    transform: translate3d(2000px, 0, 0);
  }
}
.bounceOutRight {
  -webkit-animation-name: bounceOutRight;
  animation-name: bounceOutRight;
}
@-webkit-keyframes bounceOutUp {
  20% {
    -webkit-transform: translate3d(0, -10px, 0);
    transform: translate3d(0, -10px, 0);
  }
  40%,
  45% {
    opacity: 1;
    -webkit-transform: translate3d(0, 20px, 0);
    transform: translate3d(0, 20px, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -2000px, 0);
    transform: translate3d(0, -2000px, 0);
  }
}
@keyframes bounceOutUp {
  20% {
    -webkit-transform: translate3d(0, -10px, 0);
    transform: translate3d(0, -10px, 0);
  }
  40%,
  45% {
    opacity: 1;
    -webkit-transform: translate3d(0, 20px, 0);
    transform: translate3d(0, 20px, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -2000px, 0);
    transform: translate3d(0, -2000px, 0);
  }
}
.bounceOutUp {
  -webkit-animation-name: bounceOutUp;
  animation-name: bounceOutUp;
}
@-webkit-keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
.fadeIn {
  -webkit-animation-name: fadeIn;
  animation-name: fadeIn;
}
@-webkit-keyframes fadeInDown {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInDown {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInDown {
  -webkit-animation-name: fadeInDown;
  animation-name: fadeInDown;
}
@-webkit-keyframes fadeInDownBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, -2000px, 0);
    transform: translate3d(0, -2000px, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInDownBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, -2000px, 0);
    transform: translate3d(0, -2000px, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInDownBig {
  -webkit-animation-name: fadeInDownBig;
  animation-name: fadeInDownBig;
}
@-webkit-keyframes fadeInLeft {
  from {
    opacity: 0;
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInLeft {
  from {
    opacity: 0;
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInLeft {
  -webkit-animation-name: fadeInLeft;
  animation-name: fadeInLeft;
}
@-webkit-keyframes fadeInLeftBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(-2000px, 0, 0);
    transform: translate3d(-2000px, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInLeftBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(-2000px, 0, 0);
    transform: translate3d(-2000px, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInLeftBig {
  -webkit-animation-name: fadeInLeftBig;
  animation-name: fadeInLeftBig;
}
@-webkit-keyframes fadeInRight {
  from {
    opacity: 0;
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInRight {
  from {
    opacity: 0;
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInRight {
  -webkit-animation-name: fadeInRight;
  animation-name: fadeInRight;
}
@-webkit-keyframes fadeInRightBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(2000px, 0, 0);
    transform: translate3d(2000px, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInRightBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(2000px, 0, 0);
    transform: translate3d(2000px, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInRightBig {
  -webkit-animation-name: fadeInRightBig;
  animation-name: fadeInRightBig;
}
@-webkit-keyframes fadeInUp {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInUp {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInUp {
  -webkit-animation-name: fadeInUp;
  animation-name: fadeInUp;
}
@-webkit-keyframes fadeInUpBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInUpBig {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.fadeInUpBig {
  -webkit-animation-name: fadeInUpBig;
  animation-name: fadeInUpBig;
}
@-webkit-keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
.fadeOut {
  -webkit-animation-name: fadeOut;
  animation-name: fadeOut;
}
@-webkit-keyframes fadeOutDown {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }
}
@keyframes fadeOutDown {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }
}
.fadeOutDown {
  -webkit-animation-name: fadeOutDown;
  animation-name: fadeOutDown;
}
@-webkit-keyframes fadeOutDownBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0);
  }
}
@keyframes fadeOutDownBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, 2000px, 0);
    transform: translate3d(0, 2000px, 0);
  }
}
.fadeOutDownBig {
  -webkit-animation-name: fadeOutDownBig;
  animation-name: fadeOutDownBig;
}
@-webkit-keyframes fadeOutLeft {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
}
@keyframes fadeOutLeft {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
}
.fadeOutLeft {
  -webkit-animation-name: fadeOutLeft;
  animation-name: fadeOutLeft;
}
@-webkit-keyframes fadeOutLeftBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(-2000px, 0, 0);
    transform: translate3d(-2000px, 0, 0);
  }
}
@keyframes fadeOutLeftBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(-2000px, 0, 0);
    transform: translate3d(-2000px, 0, 0);
  }
}
.fadeOutLeftBig {
  -webkit-animation-name: fadeOutLeftBig;
  animation-name: fadeOutLeftBig;
}
@-webkit-keyframes fadeOutRight {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
  }
}
@keyframes fadeOutRight {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
  }
}
.fadeOutRight {
  -webkit-animation-name: fadeOutRight;
  animation-name: fadeOutRight;
}
@-webkit-keyframes fadeOutRightBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(2000px, 0, 0);
    transform: translate3d(2000px, 0, 0);
  }
}
@keyframes fadeOutRightBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(2000px, 0, 0);
    transform: translate3d(2000px, 0, 0);
  }
}
.fadeOutRightBig {
  -webkit-animation-name: fadeOutRightBig;
  animation-name: fadeOutRightBig;
}
@-webkit-keyframes fadeOutUp {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
  }
}
@keyframes fadeOutUp {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
  }
}
.fadeOutUp {
  -webkit-animation-name: fadeOutUp;
  animation-name: fadeOutUp;
}
@-webkit-keyframes fadeOutUpBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -2000px, 0);
    transform: translate3d(0, -2000px, 0);
  }
}
@keyframes fadeOutUpBig {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -2000px, 0);
    transform: translate3d(0, -2000px, 0);
  }
}
.fadeOutUpBig {
  -webkit-animation-name: fadeOutUpBig;
  animation-name: fadeOutUpBig;
}
@-webkit-keyframes flip {
  from {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, -360deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
    -webkit-animation-timing-function: ease-out;
    animation-timing-function: ease-out;
  }
  40% {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -190deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -190deg);
    -webkit-animation-timing-function: ease-out;
    animation-timing-function: ease-out;
  }
  50% {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -170deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -170deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  80% {
    -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, 0deg);
    transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, 0deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  to {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, 0deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
}
@keyframes flip {
  from {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, -360deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
    -webkit-animation-timing-function: ease-out;
    animation-timing-function: ease-out;
  }
  40% {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -190deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -190deg);
    -webkit-animation-timing-function: ease-out;
    animation-timing-function: ease-out;
  }
  50% {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -170deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)
      rotate3d(0, 1, 0, -170deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  80% {
    -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, 0deg);
    transform: perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, 0deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  to {
    -webkit-transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0)
      rotate3d(0, 1, 0, 0deg);
    transform: perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
}
.animated.flip {
  -webkit-backface-visibility: visible;
  backface-visibility: visible;
  -webkit-animation-name: flip;
  animation-name: flip;
}
@-webkit-keyframes flipInX {
  from {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0;
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  }
  to {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
}
@keyframes flipInX {
  from {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0;
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  }
  to {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
}
.flipInX {
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
  -webkit-animation-name: flipInX;
  animation-name: flipInX;
}
@-webkit-keyframes flipInY {
  from {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0;
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
    transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
    transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
    transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
  }
  to {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
}
@keyframes flipInY {
  from {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0;
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
    transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
    transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
    transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
  }
  to {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
}
.flipInY {
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
  -webkit-animation-name: flipInY;
  animation-name: flipInY;
}
@-webkit-keyframes flipOutX {
  from {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
  30% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    opacity: 1;
  }
  to {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    opacity: 0;
  }
}
@keyframes flipOutX {
  from {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
  30% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    opacity: 1;
  }
  to {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    opacity: 0;
  }
}
.flipOutX {
  -webkit-animation-duration: 0.75s;
  animation-duration: 0.75s;
  -webkit-animation-name: flipOutX;
  animation-name: flipOutX;
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
}
@-webkit-keyframes flipOutY {
  from {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
  30% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
    transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
    opacity: 1;
  }
  to {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    opacity: 0;
  }
}
@keyframes flipOutY {
  from {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
  30% {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
    transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
    opacity: 1;
  }
  to {
    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
    opacity: 0;
  }
}
.flipOutY {
  -webkit-animation-duration: 0.75s;
  animation-duration: 0.75s;
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
  -webkit-animation-name: flipOutY;
  animation-name: flipOutY;
}
@-webkit-keyframes lightSpeedIn {
  from {
    -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
    transform: translate3d(100%, 0, 0) skewX(-30deg);
    opacity: 0;
  }
  60% {
    -webkit-transform: skewX(20deg);
    transform: skewX(20deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: skewX(-5deg);
    transform: skewX(-5deg);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes lightSpeedIn {
  from {
    -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
    transform: translate3d(100%, 0, 0) skewX(-30deg);
    opacity: 0;
  }
  60% {
    -webkit-transform: skewX(20deg);
    transform: skewX(20deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: skewX(-5deg);
    transform: skewX(-5deg);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.lightSpeedIn {
  -webkit-animation-name: lightSpeedIn;
  animation-name: lightSpeedIn;
  -webkit-animation-timing-function: ease-out;
  animation-timing-function: ease-out;
}
@-webkit-keyframes lightSpeedOut {
  from {
    opacity: 1;
  }
  to {
    -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
    transform: translate3d(100%, 0, 0) skewX(30deg);
    opacity: 0;
  }
}
@keyframes lightSpeedOut {
  from {
    opacity: 1;
  }
  to {
    -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
    transform: translate3d(100%, 0, 0) skewX(30deg);
    opacity: 0;
  }
}
.lightSpeedOut {
  -webkit-animation-name: lightSpeedOut;
  animation-name: lightSpeedOut;
  -webkit-animation-timing-function: ease-in;
  animation-timing-function: ease-in;
}
@-webkit-keyframes rotateIn {
  from {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, -200deg);
    transform: rotate3d(0, 0, 1, -200deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
@keyframes rotateIn {
  from {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, -200deg);
    transform: rotate3d(0, 0, 1, -200deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
.rotateIn {
  -webkit-animation-name: rotateIn;
  animation-name: rotateIn;
}
@-webkit-keyframes rotateInDownLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, -45deg);
    transform: rotate3d(0, 0, 1, -45deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
@keyframes rotateInDownLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, -45deg);
    transform: rotate3d(0, 0, 1, -45deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
.rotateInDownLeft {
  -webkit-animation-name: rotateInDownLeft;
  animation-name: rotateInDownLeft;
}
@-webkit-keyframes rotateInDownRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, 45deg);
    transform: rotate3d(0, 0, 1, 45deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
@keyframes rotateInDownRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, 45deg);
    transform: rotate3d(0, 0, 1, 45deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
.rotateInDownRight {
  -webkit-animation-name: rotateInDownRight;
  animation-name: rotateInDownRight;
}
@-webkit-keyframes rotateInUpLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, 45deg);
    transform: rotate3d(0, 0, 1, 45deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
@keyframes rotateInUpLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, 45deg);
    transform: rotate3d(0, 0, 1, 45deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
.rotateInUpLeft {
  -webkit-animation-name: rotateInUpLeft;
  animation-name: rotateInUpLeft;
}
@-webkit-keyframes rotateInUpRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, -90deg);
    transform: rotate3d(0, 0, 1, -90deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
@keyframes rotateInUpRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, -90deg);
    transform: rotate3d(0, 0, 1, -90deg);
    opacity: 0;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}
.rotateInUpRight {
  -webkit-animation-name: rotateInUpRight;
  animation-name: rotateInUpRight;
}
@-webkit-keyframes rotateOut {
  from {
    -webkit-transform-origin: center;
    transform-origin: center;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, 200deg);
    transform: rotate3d(0, 0, 1, 200deg);
    opacity: 0;
  }
}
@keyframes rotateOut {
  from {
    -webkit-transform-origin: center;
    transform-origin: center;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: center;
    transform-origin: center;
    -webkit-transform: rotate3d(0, 0, 1, 200deg);
    transform: rotate3d(0, 0, 1, 200deg);
    opacity: 0;
  }
}
.rotateOut {
  -webkit-animation-name: rotateOut;
  animation-name: rotateOut;
}
@-webkit-keyframes rotateOutDownLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, 45deg);
    transform: rotate3d(0, 0, 1, 45deg);
    opacity: 0;
  }
}
@keyframes rotateOutDownLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, 45deg);
    transform: rotate3d(0, 0, 1, 45deg);
    opacity: 0;
  }
}
.rotateOutDownLeft {
  -webkit-animation-name: rotateOutDownLeft;
  animation-name: rotateOutDownLeft;
}
@-webkit-keyframes rotateOutDownRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, -45deg);
    transform: rotate3d(0, 0, 1, -45deg);
    opacity: 0;
  }
}
@keyframes rotateOutDownRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, -45deg);
    transform: rotate3d(0, 0, 1, -45deg);
    opacity: 0;
  }
}
.rotateOutDownRight {
  -webkit-animation-name: rotateOutDownRight;
  animation-name: rotateOutDownRight;
}
@-webkit-keyframes rotateOutUpLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, -45deg);
    transform: rotate3d(0, 0, 1, -45deg);
    opacity: 0;
  }
}
@keyframes rotateOutUpLeft {
  from {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: left bottom;
    transform-origin: left bottom;
    -webkit-transform: rotate3d(0, 0, 1, -45deg);
    transform: rotate3d(0, 0, 1, -45deg);
    opacity: 0;
  }
}
.rotateOutUpLeft {
  -webkit-animation-name: rotateOutUpLeft;
  animation-name: rotateOutUpLeft;
}
@-webkit-keyframes rotateOutUpRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, 90deg);
    transform: rotate3d(0, 0, 1, 90deg);
    opacity: 0;
  }
}
@keyframes rotateOutUpRight {
  from {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    opacity: 1;
  }
  to {
    -webkit-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate3d(0, 0, 1, 90deg);
    transform: rotate3d(0, 0, 1, 90deg);
    opacity: 0;
  }
}
.rotateOutUpRight {
  -webkit-animation-name: rotateOutUpRight;
  animation-name: rotateOutUpRight;
}
@-webkit-keyframes hinge {
  0% {
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }
  20%,
  60% {
    -webkit-transform: rotate3d(0, 0, 1, 80deg);
    transform: rotate3d(0, 0, 1, 80deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }
  40%,
  80% {
    -webkit-transform: rotate3d(0, 0, 1, 60deg);
    transform: rotate3d(0, 0, 1, 60deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
    opacity: 1;
  }
  to {
    -webkit-transform: translate3d(0, 700px, 0);
    transform: translate3d(0, 700px, 0);
    opacity: 0;
  }
}
@keyframes hinge {
  0% {
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }
  20%,
  60% {
    -webkit-transform: rotate3d(0, 0, 1, 80deg);
    transform: rotate3d(0, 0, 1, 80deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }
  40%,
  80% {
    -webkit-transform: rotate3d(0, 0, 1, 60deg);
    transform: rotate3d(0, 0, 1, 60deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
    opacity: 1;
  }
  to {
    -webkit-transform: translate3d(0, 700px, 0);
    transform: translate3d(0, 700px, 0);
    opacity: 0;
  }
}
.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
  -webkit-animation-name: hinge;
  animation-name: hinge;
}
@-webkit-keyframes jackInTheBox {
  from {
    opacity: 0;
    -webkit-transform: scale(0.1) rotate(30deg);
    transform: scale(0.1) rotate(30deg);
    -webkit-transform-origin: center bottom;
    transform-origin: center bottom;
  }
  50% {
    -webkit-transform: rotate(-10deg);
    transform: rotate(-10deg);
  }
  70% {
    -webkit-transform: rotate(3deg);
    transform: rotate(3deg);
  }
  to {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}
@keyframes jackInTheBox {
  from {
    opacity: 0;
    -webkit-transform: scale(0.1) rotate(30deg);
    transform: scale(0.1) rotate(30deg);
    -webkit-transform-origin: center bottom;
    transform-origin: center bottom;
  }
  50% {
    -webkit-transform: rotate(-10deg);
    transform: rotate(-10deg);
  }
  70% {
    -webkit-transform: rotate(3deg);
    transform: rotate(3deg);
  }
  to {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}
.jackInTheBox {
  -webkit-animation-name: jackInTheBox;
  animation-name: jackInTheBox;
}
/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
@-webkit-keyframes rollIn {
  from {
    opacity: 0;
    -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
    transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes rollIn {
  from {
    opacity: 0;
    -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
    transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.rollIn {
  -webkit-animation-name: rollIn;
  animation-name: rollIn;
}
/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
@-webkit-keyframes rollOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
    transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
  }
}
@keyframes rollOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
    transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
  }
}
.rollOut {
  -webkit-animation-name: rollOut;
  animation-name: rollOut;
}
@-webkit-keyframes zoomIn {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
  50% {
    opacity: 1;
  }
}
@keyframes zoomIn {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
  50% {
    opacity: 1;
  }
}
.zoomIn {
  -webkit-animation-name: zoomIn;
  animation-name: zoomIn;
}
@-webkit-keyframes zoomInDown {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
@keyframes zoomInDown {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
.zoomInDown {
  -webkit-animation-name: zoomInDown;
  animation-name: zoomInDown;
}
@-webkit-keyframes zoomInLeft {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
@keyframes zoomInLeft {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
.zoomInLeft {
  -webkit-animation-name: zoomInLeft;
  animation-name: zoomInLeft;
}
@-webkit-keyframes zoomInRight {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
@keyframes zoomInRight {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
.zoomInRight {
  -webkit-animation-name: zoomInRight;
  animation-name: zoomInRight;
}
@-webkit-keyframes zoomInUp {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
@keyframes zoomInUp {
  from {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
.zoomInUp {
  -webkit-animation-name: zoomInUp;
  animation-name: zoomInUp;
}
@-webkit-keyframes zoomOut {
  from {
    opacity: 1;
  }
  50% {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
  to {
    opacity: 0;
  }
}
@keyframes zoomOut {
  from {
    opacity: 1;
  }
  50% {
    opacity: 0;
    -webkit-transform: scale3d(0.3, 0.3, 0.3);
    transform: scale3d(0.3, 0.3, 0.3);
  }
  to {
    opacity: 0;
  }
}
.zoomOut {
  -webkit-animation-name: zoomOut;
  animation-name: zoomOut;
}
@-webkit-keyframes zoomOutDown {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  to {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
    -webkit-transform-origin: center bottom;
    transform-origin: center bottom;
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
@keyframes zoomOutDown {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  to {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
    -webkit-transform-origin: center bottom;
    transform-origin: center bottom;
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
.zoomOutDown {
  -webkit-animation-name: zoomOutDown;
  animation-name: zoomOutDown;
}
@-webkit-keyframes zoomOutLeft {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
    transform: scale(0.1) translate3d(-2000px, 0, 0);
    -webkit-transform-origin: left center;
    transform-origin: left center;
  }
}
@keyframes zoomOutLeft {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
    transform: scale(0.1) translate3d(-2000px, 0, 0);
    -webkit-transform-origin: left center;
    transform-origin: left center;
  }
}
.zoomOutLeft {
  -webkit-animation-name: zoomOutLeft;
  animation-name: zoomOutLeft;
}
@-webkit-keyframes zoomOutRight {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
    transform: scale(0.1) translate3d(2000px, 0, 0);
    -webkit-transform-origin: right center;
    transform-origin: right center;
  }
}
@keyframes zoomOutRight {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
  }
  to {
    opacity: 0;
    -webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
    transform: scale(0.1) translate3d(2000px, 0, 0);
    -webkit-transform-origin: right center;
    transform-origin: right center;
  }
}
.zoomOutRight {
  -webkit-animation-name: zoomOutRight;
  animation-name: zoomOutRight;
}
@-webkit-keyframes zoomOutUp {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  to {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
    -webkit-transform-origin: center bottom;
    transform-origin: center bottom;
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
@keyframes zoomOutUp {
  40% {
    opacity: 1;
    -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
    -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }
  to {
    opacity: 0;
    -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
    transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
    -webkit-transform-origin: center bottom;
    transform-origin: center bottom;
    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
    animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
  }
}
.zoomOutUp {
  -webkit-animation-name: zoomOutUp;
  animation-name: zoomOutUp;
}
@-webkit-keyframes slideInDown {
  from {
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes slideInDown {
  from {
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.slideInDown {
  -webkit-animation-name: slideInDown;
  animation-name: slideInDown;
}
@-webkit-keyframes slideInLeft {
  from {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes slideInLeft {
  from {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.slideInLeft {
  -webkit-animation-name: slideInLeft;
  animation-name: slideInLeft;
}
@-webkit-keyframes slideInRight {
  from {
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes slideInRight {
  from {
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.slideInRight {
  -webkit-animation-name: slideInRight;
  animation-name: slideInRight;
}
@-webkit-keyframes slideInUp {
  from {
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes slideInUp {
  from {
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
    visibility: visible;
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
.slideInUp {
  -webkit-animation-name: slideInUp;
  animation-name: slideInUp;
}
@-webkit-keyframes slideOutDown {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }
}
@keyframes slideOutDown {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }
}
.slideOutDown {
  -webkit-animation-name: slideOutDown;
  animation-name: slideOutDown;
}
@-webkit-keyframes slideOutLeft {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
}
@keyframes slideOutLeft {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
}
.slideOutLeft {
  -webkit-animation-name: slideOutLeft;
  animation-name: slideOutLeft;
}
@-webkit-keyframes slideOutRight {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
  }
}
@keyframes slideOutRight {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
  }
}
.slideOutRight {
  -webkit-animation-name: slideOutRight;
  animation-name: slideOutRight;
}
@-webkit-keyframes slideOutUp {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
  }
}
@keyframes slideOutUp {
  from {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
  to {
    visibility: hidden;
    -webkit-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
  }
}
.slideOutUp {
  -webkit-animation-name: slideOutUp;
  animation-name: slideOutUp;
}
.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated.delay-1s {
  -webkit-animation-delay: 1s;
  animation-delay: 1s;
}
.animated.delay-2s {
  -webkit-animation-delay: 2s;
  animation-delay: 2s;
}
.animated.delay-3s {
  -webkit-animation-delay: 3s;
  animation-delay: 3s;
}
.animated.delay-4s {
  -webkit-animation-delay: 4s;
  animation-delay: 4s;
}
.animated.delay-5s {
  -webkit-animation-delay: 5s;
  animation-delay: 5s;
}
.animated.fast {
  -webkit-animation-duration: 800ms;
  animation-duration: 800ms;
}
.animated.faster {
  -webkit-animation-duration: 500ms;
  animation-duration: 500ms;
}
.animated.slow {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}
.animated.slower {
  -webkit-animation-duration: 3s;
  animation-duration: 3s;
}
@media (prefers-reduced-motion) {
  .animated {
    -webkit-animation: unset !important;
    animation: unset !important;
    -webkit-transition: none !important;
    transition: none !important;
  }
}
src/styles/calendars.scss
New file
@@ -0,0 +1,168 @@
#calendar {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fff;
}
#calendar /deep/ .fc-license-message {
  display: none !important;
}
#calendar /deep/ .fc-toolbar {
  padding-top: 1em;
  .fc-left {
    padding-left: 20px;
    .fc-button-group {
      .fc-button {
        text-shadow: none;
      }
      .fc-state-default {
        background: #f0f0f0;
        padding: 0 1.2em;
        border: 0;
        margin-right: 3px;
      }
      .fc-state-down {
        box-shadow: none;
        text-shadow: none;
      }
      .fc-state-active {
        background: #4D88FF;
        color: #fff;
      }
    }
    .fc-today-button {
      background: #fff;
      margin-right: 50px;
    }
  }
  .fc-center {
    margin-left: -277px;
    h2 {
      font-size: 20px;
      font-weight: normal;
      margin-top: 5px;
    }
    .fc-prevYear-button,
    .fc-prev-button,
    .fc-next-button,
    .fc-nextYear-button {
      background: none;
      border: 0;
      color: #aaa;
      outline: none;
      box-shadow: none;
    }
    .fc-button-group {
      .fc-prev-button .fc-icon-left-single-arrow:after,
      .fc-next-button .fc-icon-right-single-arrow:after {
        font-size: 160%;
        font-weight: none;
      }
    }
  }
}
#calendar /deep/ .fc-view-container {
  .fc-body {
    .fc-row {
      .fc-day {
        border-color: #e9e9e9;
      }
      .fc-bg {
        .fc-sat,
        .fc-sun {
          background: #fbfbfb;
        }
        .fc-today {
          background: none;
        }
      }
      .fc-content-skeleton {
        .fc-today {
          .fc-day-number {
            background: #4D88FF;
            border-radius: 50%;
            padding: 3px;
            color: #fff;
            min-width: 16px;
            text-align: center;
          }
        }
        .fc-day-grid-event {
          border: 0 !important;
          border-radius: 23px;
          margin-left: 5px;
          margin-right: 5px;
          .fc-content {
            color: #fff;
            .fc-time {
              display: none;
            }
            .fc-title {
              float: left;
              width: 100%;
              overflow: hidden;
              white-space: nowrap;
              text-overflow: ellipsis;
            }
          }
        }
      }
      .fc-day-number {
        margin: 5px;
      }
      .fc-day-grid-event {
        border-left: 2px solid #ff9668 !important;
        border-radius: 0;
        margin-left: 0;
        margin-right: 0;
        padding: 2px 15px;
      }
    }
  }
  .fc-body>tr>.fc-widget-content {
    border: 0;
  }
  .fc-head {
    .fc-head-container {
      border: 0;
      border-bottom: 1px solid #ddd;
    }
  }
}
#calendar /deep/ .fc-day-header {
  background: #f5f5f5;
  border-width: 0;
  font-weight: normal;
  span {
    height: 50px;
    line-height: 50px;
  }
}
src/styles/element-ui.scss
New file
@@ -0,0 +1,122 @@
 //to reset element-ui default css
// .el-upload {
//   input[type="file"] {
//     display: none !important;
//   }
// }
// .el-upload__input {
//   display: none;
// }
// //暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
// .el-dialog {
//   transform: none;
//   left: 0;
//   position: relative;
//   margin: 0 auto;
// }
// //element ui upload
// .upload-container {
//   .el-upload {
//     width: 100%;
//     .el-upload-dragger {
//       width: 100%;
//       height: 200px;
//     }
//   }
// }
// /** checkbox 更改 */
// .el-checkbox__label {
//   font-size: 13px;
//   color: #333333;
// }
// .el-checkbox__input.is-checked+.el-checkbox__label {
//   color: #333333;
// }
.el-dialog{
  border-radius: 8px !important;
}
.el-dialog__header{
  border-bottom: 1px solid #F1F1F1;
}
.el-dialog .el-dialog__title{
  color: #333;
  font-weight: 550;
}
.el-dialog .el-dialog__footer{
  text-align: center;
}
// .el-dialog .el-form--inline.el-form--label-top .el-form-item__content{
//   display: inline-block;
//   width: 70%;
// }
// .el-dialog .el-form--inline .el-form-item__label{
//   width: 21%;
//   text-align: right;
// }
.el-input .el-input__inner {
  padding: 0 8px;
  height: 36px ;
  line-height: 36px;
}
.el-input .el-input__inner:hover{
  border-color: #4D88FF !important;
}
.el-cascader:not(.is-disabled):hover .el-input__inner{
  border-color: #4D88FF !important;
}
.el-cascader-node:not(.is-disabled):hover, .el-cascader-node:not(.is-disabled):focus{
  background: #F7FAFF !important;
}
.el-select-dropdown__item.hover, .el-select-dropdown__item:hover{
  background: #F7FAFF !important;
}
.el-tooltip__popper.is-light{
  color: #fff;
  background: #4D88FF !important;
  border: 1px solid #4D88FF !important;
}
.el-tooltip__popper[x-placement^="right"] .popper__arrow{
  border-right-color: #4D88FF !important;
}
.el-tooltip__popper[x-placement^="right"] .popper__arrow::after{
  border-right-color: #4D88FF !important;
}
.el-form-item.is-error .el-input__inner, .el-form-item.is-error .el-input__inner:focus, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner:focus{
  border-color: #FF4D4D !important;
  background: rgba(255, 77, 77, 0.05) !important;
}
.el-form-item__error{
  color: #FF4D4D !important;
}
.el-popper[x-placement^="bottom"] .popper__arrow{
  display: none;
}
.el-textarea .el-textarea__inner {
  padding: 5px 8px;
}
.el-radio .el-radio__label {
  padding-left: 8px;
}
.el-checkbox .el-checkbox__label {
  padding-left: 8px;
}
body .el-table th.gutter{
  display: table-cell !important;
}
body .el-table colgroup.gutter{
  display: table-cell !important;
}
.el-button--primary{
  background-color: #4D88FF !important;
  border-color: #4D88FF !important;
}
src/styles/element-variables.scss
New file
@@ -0,0 +1,38 @@
/* 改变主题色变量 */
$--color-primary: #4D88FF;
/** border */
$--border-color-base: #ddd;
$--border-radius-base: 2px;
$--font-size-base: 13px;
// $--color-text-primary: #303133;
$--color-text-regular: #333;
// $--color-text-secondary: #909399; #aaa 说明文字
// $--color-text-placeholder: #c0c4cc;
/** input */
// $--input-border-radius: 3px;
$--input-height: 34px;
$--input-border-radius:3px;
/** button */
$--button-padding-vertical: 8px;
$--button-padding-horizontal: 12px;
$--button-font-size: 13px;
/* Radio
-------------------------- */
$--radio-font-size: 13px;
$--radio-checked-text-color: $--color-text-regular;
$--select-font-size: 12px;
/* Checkbox
-------------------------- */
$--checkbox-font-size: 13px;
$--checkbox-checked-text-color: $--color-text-regular;
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
src/styles/emoji-sprite.scss
New file
@@ -0,0 +1,3558 @@
[class*="sprite-"] {
  width:25px;
  height: 25px;
  background: url('../assets/img/sprite/vue-emoji.png');
  background-repeat: no-repeat;
  vertical-align: top;
  display: inline-block;
  margin: 5px;
  background-size: 882.8125px 867.1875px;
}
.sprite-a {
  background-position: -1.953125px -1.953125px;
}
.sprite-a-100 {
  background-position: -30.859375px -1.953125px;
}
.sprite-a-1234 {
  background-position: -59.765625px -1.953125px;
}
.sprite-a-8ball {
  background-position: -88.671875px -1.953125px;
}
.sprite-ab {
  background-position: -117.578125px -1.953125px;
}
.sprite-abc {
  background-position: -146.484375px -1.953125px;
}
.sprite-abcd {
  background-position: -175.390625px -1.953125px;
}
.sprite-accept {
  background-position: -204.296875px -1.953125px;
}
.sprite-aerial_tramway {
  background-position: -233.203125px -1.953125px;
}
.sprite-agree {
  background-position: -262.109375px -1.953125px;
}
.sprite-airplane {
  background-position: -291.015625px -1.953125px;
}
.sprite-alarm_clock {
  background-position: -319.921875px -1.953125px;
}
.sprite-alien {
  background-position: -348.828125px -1.953125px;
}
.sprite-ambulance {
  background-position: -377.734375px -1.953125px;
}
.sprite-anchor {
  background-position: -406.640625px -1.953125px;
}
.sprite-angel {
  background-position: -435.546875px -1.953125px;
}
.sprite-anger {
  background-position: -464.453125px -1.953125px;
}
.sprite-angry {
  background-position: -493.359375px -1.953125px;
}
.sprite-anguished {
  background-position: -522.265625px -1.953125px;
}
.sprite-ant {
  background-position: -551.171875px -1.953125px;
}
.sprite-apple {
  background-position: -580.078125px -1.953125px;
}
.sprite-aquarius {
  background-position: -608.984375px -1.953125px;
}
.sprite-aries {
  background-position: -637.890625px -1.953125px;
}
.sprite-arrow_backward {
  background-position: -666.796875px -1.953125px;
}
.sprite-arrow_double_down {
  background-position: -695.703125px -1.953125px;
}
.sprite-arrow_double_up {
  background-position: -724.609375px -1.953125px;
}
.sprite-arrow_down {
  background-position: -753.515625px -1.953125px;
}
.sprite-arrow_down_small {
  background-position: -782.421875px -1.953125px;
}
.sprite-arrow_forward {
  background-position: -811.328125px -1.953125px;
}
.sprite-arrow_heading_down {
  background-position: -1.953125px -30.859375px;
}
.sprite-arrow_heading_up {
  background-position: -30.859375px -30.859375px;
}
.sprite-arrow_left {
  background-position: -59.765625px -30.859375px;
}
.sprite-arrow_lower_left {
  background-position: -88.671875px -30.859375px;
}
.sprite-arrow_lower_right {
  background-position: -117.578125px -30.859375px;
}
.sprite-arrow_right {
  background-position: -146.484375px -30.859375px;
}
.sprite-arrow_right_hook {
  background-position: -175.390625px -30.859375px;
}
.sprite-arrow_up {
  background-position: -204.296875px -30.859375px;
}
.sprite-arrow_up_down {
  background-position: -233.203125px -30.859375px;
}
.sprite-arrow_up_small {
  background-position: -262.109375px -30.859375px;
}
.sprite-arrow_upper_left {
  background-position: -291.015625px -30.859375px;
}
.sprite-arrow_upper_right {
  background-position: -319.921875px -30.859375px;
}
.sprite-arrows_clockwise {
  background-position: -348.828125px -30.859375px;
}
.sprite-arrows_counterclockwise {
  background-position: -377.734375px -30.859375px;
}
.sprite-art {
  background-position: -406.640625px -30.859375px;
}
.sprite-articulated_lorry {
  background-position: -435.546875px -30.859375px;
}
.sprite-astonished {
  background-position: -464.453125px -30.859375px;
}
.sprite-atm {
  background-position: -493.359375px -30.859375px;
}
.sprite-b {
  background-position: -522.265625px -30.859375px;
}
.sprite-baby {
  background-position: -551.171875px -30.859375px;
}
.sprite-baby_bottle {
  background-position: -580.078125px -30.859375px;
}
.sprite-baby_chick {
  background-position: -608.984375px -30.859375px;
}
.sprite-baby_symbol {
  background-position: -637.890625px -30.859375px;
}
.sprite-back {
  background-position: -666.796875px -30.859375px;
}
.sprite-baggage_claim {
  background-position: -695.703125px -30.859375px;
}
.sprite-balloon {
  background-position: -724.609375px -30.859375px;
}
.sprite-ballot_box_with_check {
  background-position: -753.515625px -30.859375px;
}
.sprite-bamboo {
  background-position: -782.421875px -30.859375px;
}
.sprite-banana {
  background-position: -811.328125px -30.859375px;
}
.sprite-bangbang {
  background-position: -1.953125px -59.765625px;
}
.sprite-bank {
  background-position: -30.859375px -59.765625px;
}
.sprite-bar_chart {
  background-position: -59.765625px -59.765625px;
}
.sprite-barber {
  background-position: -88.671875px -59.765625px;
}
.sprite-baseball {
  background-position: -117.578125px -59.765625px;
}
.sprite-basketball {
  background-position: -146.484375px -59.765625px;
}
.sprite-bath {
  background-position: -175.390625px -59.765625px;
}
.sprite-bathtub {
  background-position: -204.296875px -59.765625px;
}
.sprite-battery {
  background-position: -233.203125px -59.765625px;
}
.sprite-bear {
  background-position: -262.109375px -59.765625px;
}
.sprite-bee {
  background-position: -291.015625px -59.765625px;
}
.sprite-beer {
  background-position: -319.921875px -59.765625px;
}
.sprite-beers {
  background-position: -348.828125px -59.765625px;
}
.sprite-beetle {
  background-position: -377.734375px -59.765625px;
}
.sprite-beginner {
  background-position: -406.640625px -59.765625px;
}
.sprite-bell {
  background-position: -435.546875px -59.765625px;
}
.sprite-bento {
  background-position: -464.453125px -59.765625px;
}
.sprite-bicyclist {
  background-position: -493.359375px -59.765625px;
}
.sprite-bike {
  background-position: -522.265625px -59.765625px;
}
.sprite-bikini {
  background-position: -551.171875px -59.765625px;
}
.sprite-bird {
  background-position: -580.078125px -59.765625px;
}
.sprite-birthday {
  background-position: -608.984375px -59.765625px;
}
.sprite-black_circle {
  background-position: -637.890625px -59.765625px;
}
.sprite-black_joker {
  background-position: -666.796875px -59.765625px;
}
.sprite-black_medium_small_square {
  background-position: -695.703125px -59.765625px;
}
.sprite-black_medium_square {
  background-position: -724.609375px -59.765625px;
}
.sprite-black_nib {
  background-position: -753.515625px -59.765625px;
}
.sprite-black_small_square {
  background-position: -782.421875px -59.765625px;
}
.sprite-black_square {
  background-position: -811.328125px -59.765625px;
}
.sprite-black_square_button {
  background-position: -1.953125px -88.671875px;
}
.sprite-blossom {
  background-position: -30.859375px -88.671875px;
}
.sprite-blowfish {
  background-position: -59.765625px -88.671875px;
}
.sprite-blue_book {
  background-position: -88.671875px -88.671875px;
}
.sprite-blue_car {
  background-position: -117.578125px -88.671875px;
}
.sprite-blue_heart {
  background-position: -146.484375px -88.671875px;
}
.sprite-blush {
  background-position: -175.390625px -88.671875px;
}
.sprite-boar {
  background-position: -204.296875px -88.671875px;
}
.sprite-boat {
  background-position: -233.203125px -88.671875px;
}
.sprite-bomb {
  background-position: -262.109375px -88.671875px;
}
.sprite-book {
  background-position: -291.015625px -88.671875px;
}
.sprite-bookmark {
  background-position: -319.921875px -88.671875px;
}
.sprite-bookmark_tabs {
  background-position: -348.828125px -88.671875px;
}
.sprite-books {
  background-position: -377.734375px -88.671875px;
}
.sprite-boom {
  background-position: -406.640625px -88.671875px;
}
.sprite-boot {
  background-position: -435.546875px -88.671875px;
}
.sprite-bouquet {
  background-position: -464.453125px -88.671875px;
}
.sprite-bow {
  background-position: -493.359375px -88.671875px;
}
.sprite-bowling {
  background-position: -522.265625px -88.671875px;
}
.sprite-bowtie {
  background-position: -551.171875px -88.671875px;
}
.sprite-boy {
  background-position: -580.078125px -88.671875px;
}
.sprite-bread {
  background-position: -608.984375px -88.671875px;
}
.sprite-bride_with_veil {
  background-position: -637.890625px -88.671875px;
}
.sprite-bridge_at_night {
  background-position: -666.796875px -88.671875px;
}
.sprite-briefcase {
  background-position: -695.703125px -88.671875px;
}
.sprite-broken_heart {
  background-position: -724.609375px -88.671875px;
}
.sprite-bug {
  background-position: -753.515625px -88.671875px;
}
.sprite-bulb {
  background-position: -782.421875px -88.671875px;
}
.sprite-bullettrain_front {
  background-position: -811.328125px -88.671875px;
}
.sprite-bullettrain_side {
  background-position: -1.953125px -117.578125px;
}
.sprite-bus {
  background-position: -30.859375px -117.578125px;
}
.sprite-busstop {
  background-position: -59.765625px -117.578125px;
}
.sprite-bust_in_silhouette {
  background-position: -88.671875px -117.578125px;
}
.sprite-busts_in_silhouette {
  background-position: -117.578125px -117.578125px;
}
.sprite-cactus {
  background-position: -146.484375px -117.578125px;
}
.sprite-cake {
  background-position: -175.390625px -117.578125px;
}
.sprite-calendar {
  background-position: -204.296875px -117.578125px;
}
.sprite-calling {
  background-position: -233.203125px -117.578125px;
}
.sprite-camel {
  background-position: -262.109375px -117.578125px;
}
.sprite-camera {
  background-position: -291.015625px -117.578125px;
}
.sprite-cancer {
  background-position: -319.921875px -117.578125px;
}
.sprite-candy {
  background-position: -348.828125px -117.578125px;
}
.sprite-capital_abcd {
  background-position: -377.734375px -117.578125px;
}
.sprite-capricorn {
  background-position: -406.640625px -117.578125px;
}
.sprite-car {
  background-position: -435.546875px -117.578125px;
}
.sprite-card_index {
  background-position: -464.453125px -117.578125px;
}
.sprite-carousel_horse {
  background-position: -493.359375px -117.578125px;
}
.sprite-cat {
  background-position: -522.265625px -117.578125px;
}
.sprite-cat2 {
  background-position: -551.171875px -117.578125px;
}
.sprite-cd {
  background-position: -580.078125px -117.578125px;
}
.sprite-chart {
  background-position: -608.984375px -117.578125px;
}
.sprite-chart_with_downwards_trend {
  background-position: -637.890625px -117.578125px;
}
.sprite-chart_with_upwards_trend {
  background-position: -666.796875px -117.578125px;
}
.sprite-checkered_flag {
  background-position: -695.703125px -117.578125px;
}
.sprite-cherries {
  background-position: -724.609375px -117.578125px;
}
.sprite-cherry_blossom {
  background-position: -753.515625px -117.578125px;
}
.sprite-chestnut {
  background-position: -782.421875px -117.578125px;
}
.sprite-chicken {
  background-position: -811.328125px -117.578125px;
}
.sprite-children_crossing {
  background-position: -1.953125px -146.484375px;
}
.sprite-chocolate_bar {
  background-position: -30.859375px -146.484375px;
}
.sprite-christmas_tree {
  background-position: -59.765625px -146.484375px;
}
.sprite-church {
  background-position: -88.671875px -146.484375px;
}
.sprite-cinema {
  background-position: -117.578125px -146.484375px;
}
.sprite-circus_tent {
  background-position: -146.484375px -146.484375px;
}
.sprite-city_sunrise {
  background-position: -175.390625px -146.484375px;
}
.sprite-city_sunset {
  background-position: -204.296875px -146.484375px;
}
.sprite-cl {
  background-position: -233.203125px -146.484375px;
}
.sprite-clap {
  background-position: -262.109375px -146.484375px;
}
.sprite-clapper {
  background-position: -291.015625px -146.484375px;
}
.sprite-clipboard {
  background-position: -319.921875px -146.484375px;
}
.sprite-clock1 {
  background-position: -348.828125px -146.484375px;
}
.sprite-clock10 {
  background-position: -377.734375px -146.484375px;
}
.sprite-clock1030 {
  background-position: -406.640625px -146.484375px;
}
.sprite-clock11 {
  background-position: -435.546875px -146.484375px;
}
.sprite-clock1130 {
  background-position: -464.453125px -146.484375px;
}
.sprite-clock12 {
  background-position: -493.359375px -146.484375px;
}
.sprite-clock1230 {
  background-position: -522.265625px -146.484375px;
}
.sprite-clock130 {
  background-position: -551.171875px -146.484375px;
}
.sprite-clock2 {
  background-position: -580.078125px -146.484375px;
}
.sprite-clock230 {
  background-position: -608.984375px -146.484375px;
}
.sprite-clock3 {
  background-position: -637.890625px -146.484375px;
}
.sprite-clock330 {
  background-position: -666.796875px -146.484375px;
}
.sprite-clock4 {
  background-position: -695.703125px -146.484375px;
}
.sprite-clock430 {
  background-position: -724.609375px -146.484375px;
}
.sprite-clock5 {
  background-position: -753.515625px -146.484375px;
}
.sprite-clock530 {
  background-position: -782.421875px -146.484375px;
}
.sprite-clock6 {
  background-position: -811.328125px -146.484375px;
}
.sprite-clock630 {
  background-position: -1.953125px -175.390625px;
}
.sprite-clock7 {
  background-position: -30.859375px -175.390625px;
}
.sprite-clock730 {
  background-position: -59.765625px -175.390625px;
}
.sprite-clock8 {
  background-position: -88.671875px -175.390625px;
}
.sprite-clock830 {
  background-position: -117.578125px -175.390625px;
}
.sprite-clock9 {
  background-position: -146.484375px -175.390625px;
}
.sprite-clock930 {
  background-position: -175.390625px -175.390625px;
}
.sprite-closed_book {
  background-position: -204.296875px -175.390625px;
}
.sprite-closed_lock_with_key {
  background-position: -233.203125px -175.390625px;
}
.sprite-closed_umbrella {
  background-position: -262.109375px -175.390625px;
}
.sprite-cloud {
  background-position: -291.015625px -175.390625px;
}
.sprite-clubs {
  background-position: -319.921875px -175.390625px;
}
.sprite-cn {
  background-position: -348.828125px -175.390625px;
}
.sprite-cocktail {
  background-position: -377.734375px -175.390625px;
}
.sprite-coffee {
  background-position: -406.640625px -175.390625px;
}
.sprite-cold_sweat {
  background-position: -435.546875px -175.390625px;
}
.sprite-collision {
  background-position: -464.453125px -175.390625px;
}
.sprite-computer {
  background-position: -493.359375px -175.390625px;
}
.sprite-confetti_ball {
  background-position: -522.265625px -175.390625px;
}
.sprite-confounded {
  background-position: -551.171875px -175.390625px;
}
.sprite-confused {
  background-position: -580.078125px -175.390625px;
}
.sprite-congratulations {
  background-position: -608.984375px -175.390625px;
}
.sprite-construction {
  background-position: -637.890625px -175.390625px;
}
.sprite-construction_worker {
  background-position: -666.796875px -175.390625px;
}
.sprite-convenience_store {
  background-position: -695.703125px -175.390625px;
}
.sprite-cookie {
  background-position: -724.609375px -175.390625px;
}
.sprite-cool {
  background-position: -753.515625px -175.390625px;
}
.sprite-cop {
  background-position: -782.421875px -175.390625px;
}
.sprite-copyright {
  background-position: -811.328125px -175.390625px;
}
.sprite-corn {
  background-position: -1.953125px -204.296875px;
}
.sprite-couple {
  background-position: -30.859375px -204.296875px;
}
.sprite-couple_with_heart {
  background-position: -59.765625px -204.296875px;
}
.sprite-couplekiss {
  background-position: -88.671875px -204.296875px;
}
.sprite-cow {
  background-position: -117.578125px -204.296875px;
}
.sprite-cow2 {
  background-position: -146.484375px -204.296875px;
}
.sprite-credit_card {
  background-position: -175.390625px -204.296875px;
}
.sprite-crescent_moon {
  background-position: -204.296875px -204.296875px;
}
.sprite-crocodile {
  background-position: -233.203125px -204.296875px;
}
.sprite-crossed_flags {
  background-position: -262.109375px -204.296875px;
}
.sprite-crown {
  background-position: -291.015625px -204.296875px;
}
.sprite-cry {
  background-position: -319.921875px -204.296875px;
}
.sprite-crying_cat_face {
  background-position: -348.828125px -204.296875px;
}
.sprite-crystal_ball {
  background-position: -377.734375px -204.296875px;
}
.sprite-cupid {
  background-position: -406.640625px -204.296875px;
}
.sprite-curly_loop {
  background-position: -435.546875px -204.296875px;
}
.sprite-currency_exchange {
  background-position: -464.453125px -204.296875px;
}
.sprite-curry {
  background-position: -493.359375px -204.296875px;
}
.sprite-custard {
  background-position: -522.265625px -204.296875px;
}
.sprite-customs {
  background-position: -551.171875px -204.296875px;
}
.sprite-cyclone {
  background-position: -580.078125px -204.296875px;
}
.sprite-dancer {
  background-position: -608.984375px -204.296875px;
}
.sprite-dancers {
  background-position: -637.890625px -204.296875px;
}
.sprite-dango {
  background-position: -666.796875px -204.296875px;
}
.sprite-dart {
  background-position: -695.703125px -204.296875px;
}
.sprite-dash {
  background-position: -724.609375px -204.296875px;
}
.sprite-date {
  background-position: -753.515625px -204.296875px;
}
.sprite-de {
  background-position: -782.421875px -204.296875px;
}
.sprite-deciduous_tree {
  background-position: -811.328125px -204.296875px;
}
.sprite-department_store {
  background-position: -1.953125px -233.203125px;
}
.sprite-diamond_shape_with_a_dot_inside {
  background-position: -30.859375px -233.203125px;
}
.sprite-diamonds {
  background-position: -59.765625px -233.203125px;
}
.sprite-disappointed {
  background-position: -88.671875px -233.203125px;
}
.sprite-disappointed_relieved {
  background-position: -117.578125px -233.203125px;
}
.sprite-dizzy {
  background-position: -146.484375px -233.203125px;
}
.sprite-dizzy_face {
  background-position: -175.390625px -233.203125px;
}
.sprite-do_not_litter {
  background-position: -204.296875px -233.203125px;
}
.sprite-dog {
  background-position: -233.203125px -233.203125px;
}
.sprite-dog2 {
  background-position: -262.109375px -233.203125px;
}
.sprite-dollar {
  background-position: -291.015625px -233.203125px;
}
.sprite-dolls {
  background-position: -319.921875px -233.203125px;
}
.sprite-dolphin {
  background-position: -348.828125px -233.203125px;
}
.sprite-donut {
  background-position: -377.734375px -233.203125px;
}
.sprite-door {
  background-position: -406.640625px -233.203125px;
}
.sprite-doughnut {
  background-position: -435.546875px -233.203125px;
}
.sprite-dragon {
  background-position: -464.453125px -233.203125px;
}
.sprite-dragon_face {
  background-position: -493.359375px -233.203125px;
}
.sprite-dress {
  background-position: -522.265625px -233.203125px;
}
.sprite-dromedary_camel {
  background-position: -551.171875px -233.203125px;
}
.sprite-droplet {
  background-position: -580.078125px -233.203125px;
}
.sprite-dvd {
  background-position: -608.984375px -233.203125px;
}
.sprite-e-mail {
  background-position: -637.890625px -233.203125px;
}
.sprite-ear {
  background-position: -666.796875px -233.203125px;
}
.sprite-ear_of_rice {
  background-position: -695.703125px -233.203125px;
}
.sprite-earth_africa {
  background-position: -724.609375px -233.203125px;
}
.sprite-earth_americas {
  background-position: -753.515625px -233.203125px;
}
.sprite-earth_asia {
  background-position: -782.421875px -233.203125px;
}
.sprite-egg {
  background-position: -811.328125px -233.203125px;
}
.sprite-eggplant {
  background-position: -1.953125px -262.109375px;
}
.sprite-eight {
  background-position: -30.859375px -262.109375px;
}
.sprite-eight_pointed_black_star {
  background-position: -59.765625px -262.109375px;
}
.sprite-eight_spoked_asterisk {
  background-position: -88.671875px -262.109375px;
}
.sprite-electric_plug {
  background-position: -117.578125px -262.109375px;
}
.sprite-elephant {
  background-position: -146.484375px -262.109375px;
}
.sprite-email {
  background-position: -175.390625px -262.109375px;
}
.sprite-end {
  background-position: -204.296875px -262.109375px;
}
.sprite-envelope {
  background-position: -233.203125px -262.109375px;
}
.sprite-es {
  background-position: -262.109375px -262.109375px;
}
.sprite-euro {
  background-position: -291.015625px -262.109375px;
}
.sprite-european_castle {
  background-position: -319.921875px -262.109375px;
}
.sprite-european_post_office {
  background-position: -348.828125px -262.109375px;
}
.sprite-evergreen_tree {
  background-position: -377.734375px -262.109375px;
}
.sprite-exclamation {
  background-position: -406.640625px -262.109375px;
}
.sprite-expressionless {
  background-position: -435.546875px -262.109375px;
}
.sprite-eyeglasses {
  background-position: -464.453125px -262.109375px;
}
.sprite-eyes {
  background-position: -493.359375px -262.109375px;
}
.sprite-facepunch {
  background-position: -522.265625px -262.109375px;
}
.sprite-factory {
  background-position: -551.171875px -262.109375px;
}
.sprite-fallen_leaf {
  background-position: -580.078125px -262.109375px;
}
.sprite-family {
  background-position: -608.984375px -262.109375px;
}
.sprite-fast_forward {
  background-position: -637.890625px -262.109375px;
}
.sprite-fax {
  background-position: -666.796875px -262.109375px;
}
.sprite-fearful {
  background-position: -695.703125px -262.109375px;
}
.sprite-feelsgood {
  background-position: -724.609375px -262.109375px;
}
.sprite-feet {
  background-position: -753.515625px -262.109375px;
}
.sprite-ferris_wheel {
  background-position: -782.421875px -262.109375px;
}
.sprite-file_folder {
  background-position: -811.328125px -262.109375px;
}
.sprite-finnadie {
  background-position: -1.953125px -291.015625px;
}
.sprite-fire {
  background-position: -30.859375px -291.015625px;
}
.sprite-fire_engine {
  background-position: -59.765625px -291.015625px;
}
.sprite-fireworks {
  background-position: -88.671875px -291.015625px;
}
.sprite-first_quarter_moon {
  background-position: -117.578125px -291.015625px;
}
.sprite-first_quarter_moon_with_face {
  background-position: -146.484375px -291.015625px;
}
.sprite-fish {
  background-position: -175.390625px -291.015625px;
}
.sprite-fish_cake {
  background-position: -204.296875px -291.015625px;
}
.sprite-fishing_pole_and_fish {
  background-position: -233.203125px -291.015625px;
}
.sprite-fist {
  background-position: -262.109375px -291.015625px;
}
.sprite-five {
  background-position: -291.015625px -291.015625px;
}
.sprite-flags {
  background-position: -319.921875px -291.015625px;
}
.sprite-flashlight {
  background-position: -348.828125px -291.015625px;
}
.sprite-floppy_disk {
  background-position: -377.734375px -291.015625px;
}
.sprite-flower_playing_cards {
  background-position: -406.640625px -291.015625px;
}
.sprite-flushed {
  background-position: -435.546875px -291.015625px;
}
.sprite-foggy {
  background-position: -464.453125px -291.015625px;
}
.sprite-football {
  background-position: -493.359375px -291.015625px;
}
.sprite-fork_and_knife {
  background-position: -522.265625px -291.015625px;
}
.sprite-fountain {
  background-position: -551.171875px -291.015625px;
}
.sprite-four {
  background-position: -580.078125px -291.015625px;
}
.sprite-four_leaf_clover {
  background-position: -608.984375px -291.015625px;
}
.sprite-fr {
  background-position: -637.890625px -291.015625px;
}
.sprite-free {
  background-position: -666.796875px -291.015625px;
}
.sprite-fried_shrimp {
  background-position: -695.703125px -291.015625px;
}
.sprite-fries {
  background-position: -724.609375px -291.015625px;
}
.sprite-frog {
  background-position: -753.515625px -291.015625px;
}
.sprite-frowning {
  background-position: -782.421875px -291.015625px;
}
.sprite-fu {
  background-position: -811.328125px -291.015625px;
}
.sprite-fuelpump {
  background-position: -1.953125px -319.921875px;
}
.sprite-full_moon {
  background-position: -30.859375px -319.921875px;
}
.sprite-full_moon_with_face {
  background-position: -59.765625px -319.921875px;
}
.sprite-game_die {
  background-position: -88.671875px -319.921875px;
}
.sprite-gb {
  background-position: -117.578125px -319.921875px;
}
.sprite-gem {
  background-position: -146.484375px -319.921875px;
}
.sprite-gemini {
  background-position: -175.390625px -319.921875px;
}
.sprite-ghost {
  background-position: -204.296875px -319.921875px;
}
.sprite-gift {
  background-position: -233.203125px -319.921875px;
}
.sprite-gift_heart {
  background-position: -262.109375px -319.921875px;
}
.sprite-girl {
  background-position: -291.015625px -319.921875px;
}
.sprite-github {
  background-position: -840.234375px -1.953125px;
}
.sprite-globe_with_meridians {
  background-position: -319.921875px -319.921875px;
}
.sprite-gmail {
  background-position: -840.234375px -17.578125px;
}
.sprite-goat {
  background-position: -348.828125px -319.921875px;
}
.sprite-goberserk {
  background-position: -377.734375px -319.921875px;
}
.sprite-godmode {
  background-position: -406.640625px -319.921875px;
}
.sprite-golf {
  background-position: -435.546875px -319.921875px;
}
.sprite-grapes {
  background-position: -464.453125px -319.921875px;
}
.sprite-green_apple {
  background-position: -493.359375px -319.921875px;
}
.sprite-green_book {
  background-position: -522.265625px -319.921875px;
}
.sprite-green_heart {
  background-position: -551.171875px -319.921875px;
}
.sprite-grey_exclamation {
  background-position: -580.078125px -319.921875px;
}
.sprite-grey_question {
  background-position: -608.984375px -319.921875px;
}
.sprite-grimacing {
  background-position: -637.890625px -319.921875px;
}
.sprite-grin {
  background-position: -666.796875px -319.921875px;
}
.sprite-grinning {
  background-position: -695.703125px -319.921875px;
}
.sprite-guardsman {
  background-position: -724.609375px -319.921875px;
}
.sprite-guitar {
  background-position: -753.515625px -319.921875px;
}
.sprite-gun {
  background-position: -782.421875px -319.921875px;
}
.sprite-haircut {
  background-position: -811.328125px -319.921875px;
}
.sprite-hamburger {
  background-position: -1.953125px -348.828125px;
}
.sprite-hammer {
  background-position: -30.859375px -348.828125px;
}
.sprite-hamster {
  background-position: -59.765625px -348.828125px;
}
.sprite-hand {
  background-position: -88.671875px -348.828125px;
}
.sprite-handbag {
  background-position: -117.578125px -348.828125px;
}
.sprite-hankey {
  background-position: -146.484375px -348.828125px;
}
.sprite-hash {
  background-position: -175.390625px -348.828125px;
}
.sprite-hatched_chick {
  background-position: -204.296875px -348.828125px;
}
.sprite-hatching_chick {
  background-position: -233.203125px -348.828125px;
}
.sprite-headphones {
  background-position: -262.109375px -348.828125px;
}
.sprite-hear_no_evil {
  background-position: -291.015625px -348.828125px;
}
.sprite-heart {
  background-position: -319.921875px -348.828125px;
}
.sprite-heart_decoration {
  background-position: -348.828125px -348.828125px;
}
.sprite-heart_eyes {
  background-position: -377.734375px -348.828125px;
}
.sprite-heart_eyes_cat {
  background-position: -406.640625px -348.828125px;
}
.sprite-heartbeat {
  background-position: -435.546875px -348.828125px;
}
.sprite-heartpulse {
  background-position: -464.453125px -348.828125px;
}
.sprite-hearts {
  background-position: -493.359375px -348.828125px;
}
.sprite-heavy_check_mark {
  background-position: -522.265625px -348.828125px;
}
.sprite-heavy_division_sign {
  background-position: -551.171875px -348.828125px;
}
.sprite-heavy_dollar_sign {
  background-position: -580.078125px -348.828125px;
}
.sprite-heavy_exclamation_mark {
  background-position: -608.984375px -348.828125px;
}
.sprite-heavy_minus_sign {
  background-position: -637.890625px -348.828125px;
}
.sprite-heavy_multiplication_x {
  background-position: -666.796875px -348.828125px;
}
.sprite-heavy_plus_sign {
  background-position: -695.703125px -348.828125px;
}
.sprite-helicopter {
  background-position: -724.609375px -348.828125px;
}
.sprite-herb {
  background-position: -753.515625px -348.828125px;
}
.sprite-hibiscus {
  background-position: -782.421875px -348.828125px;
}
.sprite-high_brightness {
  background-position: -811.328125px -348.828125px;
}
.sprite-high_heel {
  background-position: -1.953125px -377.734375px;
}
.sprite-hocho {
  background-position: -30.859375px -377.734375px;
}
.sprite-honey_pot {
  background-position: -59.765625px -377.734375px;
}
.sprite-honeybee {
  background-position: -88.671875px -377.734375px;
}
.sprite-horse {
  background-position: -117.578125px -377.734375px;
}
.sprite-horse_racing {
  background-position: -146.484375px -377.734375px;
}
.sprite-hospital {
  background-position: -175.390625px -377.734375px;
}
.sprite-hotel {
  background-position: -204.296875px -377.734375px;
}
.sprite-hotsprings {
  background-position: -233.203125px -377.734375px;
}
.sprite-hourglass {
  background-position: -262.109375px -377.734375px;
}
.sprite-hourglass_flowing_sand {
  background-position: -291.015625px -377.734375px;
}
.sprite-house {
  background-position: -319.921875px -377.734375px;
}
.sprite-house_with_garden {
  background-position: -348.828125px -377.734375px;
}
.sprite-hurtrealbad {
  background-position: -377.734375px -377.734375px;
}
.sprite-hushed {
  background-position: -406.640625px -377.734375px;
}
.sprite-ice_cream {
  background-position: -435.546875px -377.734375px;
}
.sprite-icecream {
  background-position: -464.453125px -377.734375px;
}
.sprite-id {
  background-position: -493.359375px -377.734375px;
}
.sprite-ideograph_advantage {
  background-position: -522.265625px -377.734375px;
}
.sprite-imp {
  background-position: -551.171875px -377.734375px;
}
.sprite-inbox_tray {
  background-position: -580.078125px -377.734375px;
}
.sprite-incoming_envelope {
  background-position: -608.984375px -377.734375px;
}
.sprite-information_desk_person {
  background-position: -637.890625px -377.734375px;
}
.sprite-information_source {
  background-position: -666.796875px -377.734375px;
}
.sprite-innocent {
  background-position: -695.703125px -377.734375px;
}
.sprite-interrobang {
  background-position: -724.609375px -377.734375px;
}
.sprite-iphone {
  background-position: -753.515625px -377.734375px;
}
.sprite-it {
  background-position: -782.421875px -377.734375px;
}
.sprite-izakaya_lantern {
  background-position: -811.328125px -377.734375px;
}
.sprite-jack_o_lantern {
  background-position: -1.953125px -406.640625px;
}
.sprite-japan {
  background-position: -30.859375px -406.640625px;
}
.sprite-japanese_castle {
  background-position: -59.765625px -406.640625px;
}
.sprite-japanese_goblin {
  background-position: -88.671875px -406.640625px;
}
.sprite-japanese_ogre {
  background-position: -117.578125px -406.640625px;
}
.sprite-jeans {
  background-position: -146.484375px -406.640625px;
}
.sprite-joy {
  background-position: -175.390625px -406.640625px;
}
.sprite-joy_cat {
  background-position: -204.296875px -406.640625px;
}
.sprite-jp {
  background-position: -233.203125px -406.640625px;
}
.sprite-key {
  background-position: -262.109375px -406.640625px;
}
.sprite-keycap_ten {
  background-position: -291.015625px -406.640625px;
}
.sprite-kimono {
  background-position: -319.921875px -406.640625px;
}
.sprite-kiss {
  background-position: -348.828125px -406.640625px;
}
.sprite-kissing {
  background-position: -377.734375px -406.640625px;
}
.sprite-kissing_cat {
  background-position: -406.640625px -406.640625px;
}
.sprite-kissing_closed_eyes {
  background-position: -435.546875px -406.640625px;
}
.sprite-kissing_face {
  background-position: -464.453125px -406.640625px;
}
.sprite-kissing_heart {
  background-position: -493.359375px -406.640625px;
}
.sprite-kissing_smiling_eyes {
  background-position: -522.265625px -406.640625px;
}
.sprite-koala {
  background-position: -551.171875px -406.640625px;
}
.sprite-koko {
  background-position: -580.078125px -406.640625px;
}
.sprite-kr {
  background-position: -608.984375px -406.640625px;
}
.sprite-large_blue_circle {
  background-position: -637.890625px -406.640625px;
}
.sprite-large_blue_diamond {
  background-position: -666.796875px -406.640625px;
}
.sprite-large_orange_diamond {
  background-position: -695.703125px -406.640625px;
}
.sprite-last_quarter_moon {
  background-position: -724.609375px -406.640625px;
}
.sprite-last_quarter_moon_with_face {
  background-position: -753.515625px -406.640625px;
}
.sprite-laughing {
  background-position: -782.421875px -406.640625px;
}
.sprite-leaves {
  background-position: -811.328125px -406.640625px;
}
.sprite-ledger {
  background-position: -1.953125px -435.546875px;
}
.sprite-left_luggage {
  background-position: -30.859375px -435.546875px;
}
.sprite-left_right_arrow {
  background-position: -59.765625px -435.546875px;
}
.sprite-leftwards_arrow_with_hook {
  background-position: -88.671875px -435.546875px;
}
.sprite-lemon {
  background-position: -117.578125px -435.546875px;
}
.sprite-leo {
  background-position: -146.484375px -435.546875px;
}
.sprite-leopard {
  background-position: -175.390625px -435.546875px;
}
.sprite-libra {
  background-position: -204.296875px -435.546875px;
}
.sprite-light_rail {
  background-position: -233.203125px -435.546875px;
}
.sprite-link {
  background-position: -262.109375px -435.546875px;
}
.sprite-linkedin {
  background-position: -840.234375px -33.203125px;
}
.sprite-lips {
  background-position: -291.015625px -435.546875px;
}
.sprite-lipstick {
  background-position: -319.921875px -435.546875px;
}
.sprite-lock {
  background-position: -348.828125px -435.546875px;
}
.sprite-lock_with_ink_pen {
  background-position: -377.734375px -435.546875px;
}
.sprite-lollipop {
  background-position: -406.640625px -435.546875px;
}
.sprite-loop {
  background-position: -435.546875px -435.546875px;
}
.sprite-loudspeaker {
  background-position: -464.453125px -435.546875px;
}
.sprite-love_hotel {
  background-position: -493.359375px -435.546875px;
}
.sprite-love_letter {
  background-position: -522.265625px -435.546875px;
}
.sprite-low_brightness {
  background-position: -551.171875px -435.546875px;
}
.sprite-m {
  background-position: -580.078125px -435.546875px;
}
.sprite-mag {
  background-position: -608.984375px -435.546875px;
}
.sprite-mag_right {
  background-position: -637.890625px -435.546875px;
}
.sprite-mahjong {
  background-position: -666.796875px -435.546875px;
}
.sprite-mailbox {
  background-position: -695.703125px -435.546875px;
}
.sprite-mailbox_closed {
  background-position: -724.609375px -435.546875px;
}
.sprite-mailbox_with_mail {
  background-position: -753.515625px -435.546875px;
}
.sprite-mailbox_with_no_mail {
  background-position: -782.421875px -435.546875px;
}
.sprite-man {
  background-position: -811.328125px -435.546875px;
}
.sprite-man_with_gua_pi_mao {
  background-position: -1.953125px -464.453125px;
}
.sprite-man_with_turban {
  background-position: -30.859375px -464.453125px;
}
.sprite-mans_shoe {
  background-position: -59.765625px -464.453125px;
}
.sprite-maple_leaf {
  background-position: -88.671875px -464.453125px;
}
.sprite-mask {
  background-position: -117.578125px -464.453125px;
}
.sprite-massage {
  background-position: -146.484375px -464.453125px;
}
.sprite-meat_on_bone {
  background-position: -175.390625px -464.453125px;
}
.sprite-mega {
  background-position: -204.296875px -464.453125px;
}
.sprite-melon {
  background-position: -233.203125px -464.453125px;
}
.sprite-memo {
  background-position: -262.109375px -464.453125px;
}
.sprite-mens {
  background-position: -291.015625px -464.453125px;
}
.sprite-metal {
  background-position: -319.921875px -464.453125px;
}
.sprite-metro {
  background-position: -348.828125px -464.453125px;
}
.sprite-microphone {
  background-position: -377.734375px -464.453125px;
}
.sprite-microscope {
  background-position: -406.640625px -464.453125px;
}
.sprite-milky_way {
  background-position: -435.546875px -464.453125px;
}
.sprite-minibus {
  background-position: -464.453125px -464.453125px;
}
.sprite-minidisc {
  background-position: -493.359375px -464.453125px;
}
.sprite-mobile_phone_off {
  background-position: -522.265625px -464.453125px;
}
.sprite-money_with_wings {
  background-position: -551.171875px -464.453125px;
}
.sprite-moneybag {
  background-position: -580.078125px -464.453125px;
}
.sprite-monkey {
  background-position: -608.984375px -464.453125px;
}
.sprite-monkey_face {
  background-position: -637.890625px -464.453125px;
}
.sprite-monorail {
  background-position: -666.796875px -464.453125px;
}
.sprite-mortar_board {
  background-position: -695.703125px -464.453125px;
}
.sprite-mount_fuji {
  background-position: -724.609375px -464.453125px;
}
.sprite-mountain_bicyclist {
  background-position: -753.515625px -464.453125px;
}
.sprite-mountain_cableway {
  background-position: -782.421875px -464.453125px;
}
.sprite-mountain_railway {
  background-position: -811.328125px -464.453125px;
}
.sprite-mouse {
  background-position: -1.953125px -493.359375px;
}
.sprite-mouse2 {
  background-position: -30.859375px -493.359375px;
}
.sprite-movie_camera {
  background-position: -59.765625px -493.359375px;
}
.sprite-moyai {
  background-position: -88.671875px -493.359375px;
}
.sprite-muscle {
  background-position: -117.578125px -493.359375px;
}
.sprite-mushroom {
  background-position: -146.484375px -493.359375px;
}
.sprite-musical_keyboard {
  background-position: -175.390625px -493.359375px;
}
.sprite-musical_note {
  background-position: -204.296875px -493.359375px;
}
.sprite-musical_score {
  background-position: -233.203125px -493.359375px;
}
.sprite-mute {
  background-position: -262.109375px -493.359375px;
}
.sprite-nail_care {
  background-position: -291.015625px -493.359375px;
}
.sprite-name_badge {
  background-position: -319.921875px -493.359375px;
}
.sprite-neckbeard {
  background-position: -348.828125px -493.359375px;
}
.sprite-necktie {
  background-position: -377.734375px -493.359375px;
}
.sprite-negative_squared_cross_mark {
  background-position: -406.640625px -493.359375px;
}
.sprite-neutral_face {
  background-position: -435.546875px -493.359375px;
}
.sprite-new {
  background-position: -464.453125px -493.359375px;
}
.sprite-new_moon {
  background-position: -493.359375px -493.359375px;
}
.sprite-new_moon_with_face {
  background-position: -522.265625px -493.359375px;
}
.sprite-newspaper {
  background-position: -551.171875px -493.359375px;
}
.sprite-ng {
  background-position: -580.078125px -493.359375px;
}
.sprite-nine {
  background-position: -608.984375px -493.359375px;
}
.sprite-no_bell {
  background-position: -637.890625px -493.359375px;
}
.sprite-no_bicycles {
  background-position: -666.796875px -493.359375px;
}
.sprite-no_entry {
  background-position: -695.703125px -493.359375px;
}
.sprite-no_entry_sign {
  background-position: -724.609375px -493.359375px;
}
.sprite-no_good {
  background-position: -753.515625px -493.359375px;
}
.sprite-no_mobile_phones {
  background-position: -782.421875px -493.359375px;
}
.sprite-no_mouth {
  background-position: -811.328125px -493.359375px;
}
.sprite-no_pedestrians {
  background-position: -1.953125px -522.265625px;
}
.sprite-no_smoking {
  background-position: -30.859375px -522.265625px;
}
.sprite-non-potable_water {
  background-position: -59.765625px -522.265625px;
}
.sprite-nose {
  background-position: -88.671875px -522.265625px;
}
.sprite-notebook {
  background-position: -117.578125px -522.265625px;
}
.sprite-notebook_with_decorative_cover {
  background-position: -146.484375px -522.265625px;
}
.sprite-notes {
  background-position: -175.390625px -522.265625px;
}
.sprite-nut_and_bolt {
  background-position: -204.296875px -522.265625px;
}
.sprite-o {
  background-position: -233.203125px -522.265625px;
}
.sprite-o2 {
  background-position: -262.109375px -522.265625px;
}
.sprite-ocean {
  background-position: -291.015625px -522.265625px;
}
.sprite-octocat {
  background-position: -319.921875px -522.265625px;
}
.sprite-octopus {
  background-position: -348.828125px -522.265625px;
}
.sprite-oden {
  background-position: -377.734375px -522.265625px;
}
.sprite-office {
  background-position: -406.640625px -522.265625px;
}
.sprite-ok {
  background-position: -435.546875px -522.265625px;
}
.sprite-ok_hand {
  background-position: -464.453125px -522.265625px;
}
.sprite-ok_woman {
  background-position: -493.359375px -522.265625px;
}
.sprite-older_man {
  background-position: -522.265625px -522.265625px;
}
.sprite-older_woman {
  background-position: -551.171875px -522.265625px;
}
.sprite-on {
  background-position: -580.078125px -522.265625px;
}
.sprite-oncoming_automobile {
  background-position: -608.984375px -522.265625px;
}
.sprite-oncoming_bus {
  background-position: -637.890625px -522.265625px;
}
.sprite-oncoming_police_car {
  background-position: -666.796875px -522.265625px;
}
.sprite-oncoming_taxi {
  background-position: -695.703125px -522.265625px;
}
.sprite-one {
  background-position: -724.609375px -522.265625px;
}
.sprite-open_file_folder {
  background-position: -753.515625px -522.265625px;
}
.sprite-open_hands {
  background-position: -782.421875px -522.265625px;
}
.sprite-open_mouth {
  background-position: -811.328125px -522.265625px;
}
.sprite-ophiuchus {
  background-position: -1.953125px -551.171875px;
}
.sprite-orange_book {
  background-position: -30.859375px -551.171875px;
}
.sprite-outbox_tray {
  background-position: -59.765625px -551.171875px;
}
.sprite-ox {
  background-position: -88.671875px -551.171875px;
}
.sprite-package {
  background-position: -117.578125px -551.171875px;
}
.sprite-page_facing_up {
  background-position: -146.484375px -551.171875px;
}
.sprite-page_with_curl {
  background-position: -175.390625px -551.171875px;
}
.sprite-pager {
  background-position: -204.296875px -551.171875px;
}
.sprite-palm_tree {
  background-position: -233.203125px -551.171875px;
}
.sprite-panda_face {
  background-position: -262.109375px -551.171875px;
}
.sprite-paperclip {
  background-position: -291.015625px -551.171875px;
}
.sprite-parking {
  background-position: -319.921875px -551.171875px;
}
.sprite-part_alternation_mark {
  background-position: -348.828125px -551.171875px;
}
.sprite-partly_sunny {
  background-position: -377.734375px -551.171875px;
}
.sprite-passport_control {
  background-position: -406.640625px -551.171875px;
}
.sprite-paw_prints {
  background-position: -435.546875px -551.171875px;
}
.sprite-peach {
  background-position: -464.453125px -551.171875px;
}
.sprite-pear {
  background-position: -493.359375px -551.171875px;
}
.sprite-pencil {
  background-position: -522.265625px -551.171875px;
}
.sprite-pencil2 {
  background-position: -551.171875px -551.171875px;
}
.sprite-penguin {
  background-position: -580.078125px -551.171875px;
}
.sprite-pensive {
  background-position: -608.984375px -551.171875px;
}
.sprite-performing_arts {
  background-position: -637.890625px -551.171875px;
}
.sprite-persevere {
  background-position: -666.796875px -551.171875px;
}
.sprite-person_frowning {
  background-position: -695.703125px -551.171875px;
}
.sprite-person_with_blond_hair {
  background-position: -724.609375px -551.171875px;
}
.sprite-person_with_pouting_face {
  background-position: -753.515625px -551.171875px;
}
.sprite-phone {
  background-position: -782.421875px -551.171875px;
}
.sprite-pig {
  background-position: -811.328125px -551.171875px;
}
.sprite-pig2 {
  background-position: -1.953125px -580.078125px;
}
.sprite-pig_nose {
  background-position: -30.859375px -580.078125px;
}
.sprite-pill {
  background-position: -59.765625px -580.078125px;
}
.sprite-pineapple {
  background-position: -88.671875px -580.078125px;
}
.sprite-pisces {
  background-position: -117.578125px -580.078125px;
}
.sprite-pizza {
  background-position: -146.484375px -580.078125px;
}
.sprite-plus1 {
  background-position: -175.390625px -580.078125px;
}
.sprite-point_down {
  background-position: -204.296875px -580.078125px;
}
.sprite-point_left {
  background-position: -233.203125px -580.078125px;
}
.sprite-point_right {
  background-position: -262.109375px -580.078125px;
}
.sprite-point_up {
  background-position: -291.015625px -580.078125px;
}
.sprite-point_up_2 {
  background-position: -319.921875px -580.078125px;
}
.sprite-police_car {
  background-position: -348.828125px -580.078125px;
}
.sprite-poodle {
  background-position: -377.734375px -580.078125px;
}
.sprite-poop {
  background-position: -406.640625px -580.078125px;
}
.sprite-post_office {
  background-position: -435.546875px -580.078125px;
}
.sprite-postal_horn {
  background-position: -464.453125px -580.078125px;
}
.sprite-postbox {
  background-position: -493.359375px -580.078125px;
}
.sprite-potable_water {
  background-position: -522.265625px -580.078125px;
}
.sprite-pouch {
  background-position: -551.171875px -580.078125px;
}
.sprite-poultry_leg {
  background-position: -580.078125px -580.078125px;
}
.sprite-pound {
  background-position: -608.984375px -580.078125px;
}
.sprite-pouting_cat {
  background-position: -637.890625px -580.078125px;
}
.sprite-pray {
  background-position: -666.796875px -580.078125px;
}
.sprite-princess {
  background-position: -695.703125px -580.078125px;
}
.sprite-punch {
  background-position: -724.609375px -580.078125px;
}
.sprite-purple_heart {
  background-position: -753.515625px -580.078125px;
}
.sprite-purse {
  background-position: -782.421875px -580.078125px;
}
.sprite-pushpin {
  background-position: -811.328125px -580.078125px;
}
.sprite-put_litter_in_its_place {
  background-position: -1.953125px -608.984375px;
}
.sprite-question {
  background-position: -30.859375px -608.984375px;
}
.sprite-rabbit {
  background-position: -59.765625px -608.984375px;
}
.sprite-rabbit2 {
  background-position: -88.671875px -608.984375px;
}
.sprite-racehorse {
  background-position: -117.578125px -608.984375px;
}
.sprite-radio {
  background-position: -146.484375px -608.984375px;
}
.sprite-radio_button {
  background-position: -175.390625px -608.984375px;
}
.sprite-rage {
  background-position: -204.296875px -608.984375px;
}
.sprite-rage1 {
  background-position: -233.203125px -608.984375px;
}
.sprite-rage2 {
  background-position: -262.109375px -608.984375px;
}
.sprite-rage3 {
  background-position: -291.015625px -608.984375px;
}
.sprite-rage4 {
  background-position: -319.921875px -608.984375px;
}
.sprite-railway_car {
  background-position: -348.828125px -608.984375px;
}
.sprite-rainbow {
  background-position: -377.734375px -608.984375px;
}
.sprite-raised_hand {
  background-position: -406.640625px -608.984375px;
}
.sprite-raised_hands {
  background-position: -435.546875px -608.984375px;
}
.sprite-raising_hand {
  background-position: -464.453125px -608.984375px;
}
.sprite-ram {
  background-position: -493.359375px -608.984375px;
}
.sprite-ramen {
  background-position: -522.265625px -608.984375px;
}
.sprite-rat {
  background-position: -551.171875px -608.984375px;
}
.sprite-recycle {
  background-position: -580.078125px -608.984375px;
}
.sprite-red_car {
  background-position: -608.984375px -608.984375px;
}
.sprite-red_circle {
  background-position: -637.890625px -608.984375px;
}
.sprite-refuse {
  background-position: -666.796875px -608.984375px;
}
.sprite-registered {
  background-position: -695.703125px -608.984375px;
}
.sprite-relaxed {
  background-position: -724.609375px -608.984375px;
}
.sprite-relieved {
  background-position: -753.515625px -608.984375px;
}
.sprite-repeat {
  background-position: -782.421875px -608.984375px;
}
.sprite-repeat_one {
  background-position: -811.328125px -608.984375px;
}
.sprite-restroom {
  background-position: -1.953125px -637.890625px;
}
.sprite-revolving_hearts {
  background-position: -30.859375px -637.890625px;
}
.sprite-rewind {
  background-position: -59.765625px -637.890625px;
}
.sprite-ribbon {
  background-position: -88.671875px -637.890625px;
}
.sprite-rice {
  background-position: -117.578125px -637.890625px;
}
.sprite-rice_ball {
  background-position: -146.484375px -637.890625px;
}
.sprite-rice_cracker {
  background-position: -175.390625px -637.890625px;
}
.sprite-rice_scene {
  background-position: -204.296875px -637.890625px;
}
.sprite-ring {
  background-position: -233.203125px -637.890625px;
}
.sprite-rocket {
  background-position: -262.109375px -637.890625px;
}
.sprite-roller_coaster {
  background-position: -291.015625px -637.890625px;
}
.sprite-rooster {
  background-position: -319.921875px -637.890625px;
}
.sprite-rose {
  background-position: -348.828125px -637.890625px;
}
.sprite-rotating_light {
  background-position: -377.734375px -637.890625px;
}
.sprite-round_pushpin {
  background-position: -406.640625px -637.890625px;
}
.sprite-rowboat {
  background-position: -435.546875px -637.890625px;
}
.sprite-ru {
  background-position: -464.453125px -637.890625px;
}
.sprite-rugby_football {
  background-position: -493.359375px -637.890625px;
}
.sprite-runner {
  background-position: -522.265625px -637.890625px;
}
.sprite-running {
  background-position: -551.171875px -637.890625px;
}
.sprite-running_shirt_with_sash {
  background-position: -580.078125px -637.890625px;
}
.sprite-sa {
  background-position: -608.984375px -637.890625px;
}
.sprite-sagittarius {
  background-position: -637.890625px -637.890625px;
}
.sprite-sailboat {
  background-position: -666.796875px -637.890625px;
}
.sprite-sake {
  background-position: -695.703125px -637.890625px;
}
.sprite-sandal {
  background-position: -724.609375px -637.890625px;
}
.sprite-santa {
  background-position: -753.515625px -637.890625px;
}
.sprite-satellite {
  background-position: -782.421875px -637.890625px;
}
.sprite-satisfied {
  background-position: -811.328125px -637.890625px;
}
.sprite-saxophone {
  background-position: -1.953125px -666.796875px;
}
.sprite-school {
  background-position: -30.859375px -666.796875px;
}
.sprite-school_satchel {
  background-position: -59.765625px -666.796875px;
}
.sprite-scissors {
  background-position: -88.671875px -666.796875px;
}
.sprite-scorpius {
  background-position: -117.578125px -666.796875px;
}
.sprite-scream {
  background-position: -146.484375px -666.796875px;
}
.sprite-scream_cat {
  background-position: -175.390625px -666.796875px;
}
.sprite-scroll {
  background-position: -204.296875px -666.796875px;
}
.sprite-seat {
  background-position: -233.203125px -666.796875px;
}
.sprite-secret {
  background-position: -262.109375px -666.796875px;
}
.sprite-see_no_evil {
  background-position: -291.015625px -666.796875px;
}
.sprite-seedling {
  background-position: -319.921875px -666.796875px;
}
.sprite-seven {
  background-position: -348.828125px -666.796875px;
}
.sprite-shaved_ice {
  background-position: -377.734375px -666.796875px;
}
.sprite-sheep {
  background-position: -406.640625px -666.796875px;
}
.sprite-shell {
  background-position: -435.546875px -666.796875px;
}
.sprite-ship {
  background-position: -464.453125px -666.796875px;
}
.sprite-shipit {
  background-position: -493.359375px -666.796875px;
}
.sprite-shirt {
  background-position: -526.5625px -666.796875px;
}
.sprite-shit {
  background-position: -555.46875px -666.796875px;
}
.sprite-shoe {
  background-position: -584.375px -666.796875px;
}
.sprite-shower {
  background-position: -613.28125px -666.796875px;
}
.sprite-signal_strength {
  background-position: -642.1875px -666.796875px;
}
.sprite-six {
  background-position: -671.09375px -666.796875px;
}
.sprite-six_pointed_star {
  background-position: -700px -666.796875px;
}
.sprite-ski {
  background-position: -728.90625px -666.796875px;
}
.sprite-skull {
  background-position: -757.8125px -666.796875px;
}
.sprite-sleeping {
  background-position: -786.71875px -666.796875px;
}
.sprite-sleepy {
  background-position: -815.625px -666.796875px;
}
.sprite-slot_machine {
  background-position: -1.953125px -695.703125px;
}
.sprite-small_blue_diamond {
  background-position: -30.859375px -695.703125px;
}
.sprite-small_orange_diamond {
  background-position: -59.765625px -695.703125px;
}
.sprite-small_red_triangle {
  background-position: -88.671875px -695.703125px;
}
.sprite-small_red_triangle_down {
  background-position: -117.578125px -695.703125px;
}
.sprite-smile {
  background-position: -146.484375px -695.703125px;
}
.sprite-smile_cat {
  background-position: -175.390625px -695.703125px;
}
.sprite-smiley {
  background-position: -204.296875px -695.703125px;
}
.sprite-smiley_cat {
  background-position: -233.203125px -695.703125px;
}
.sprite-smiling_imp {
  background-position: -262.109375px -695.703125px;
}
.sprite-smirk {
  background-position: -291.015625px -695.703125px;
}
.sprite-smirk_cat {
  background-position: -319.921875px -695.703125px;
}
.sprite-smoking {
  background-position: -348.828125px -695.703125px;
}
.sprite-snail {
  background-position: -377.734375px -695.703125px;
}
.sprite-snake {
  background-position: -406.640625px -695.703125px;
}
.sprite-snowboarder {
  background-position: -435.546875px -695.703125px;
}
.sprite-snowflake {
  background-position: -464.453125px -695.703125px;
}
.sprite-snowman {
  background-position: -526.5625px -695.703125px;
}
.sprite-sob {
  background-position: -555.46875px -695.703125px;
}
.sprite-soccer {
  background-position: -584.375px -695.703125px;
}
.sprite-soon {
  background-position: -613.28125px -695.703125px;
}
.sprite-sos {
  background-position: -642.1875px -695.703125px;
}
.sprite-sound {
  background-position: -671.09375px -695.703125px;
}
.sprite-space_invader {
  background-position: -700px -695.703125px;
}
.sprite-spades {
  background-position: -728.90625px -695.703125px;
}
.sprite-spaghetti {
  background-position: -757.8125px -695.703125px;
}
.sprite-sparkle {
  background-position: -786.71875px -695.703125px;
}
.sprite-sparkler {
  background-position: -815.625px -695.703125px;
}
.sprite-sparkles {
  background-position: -1.953125px -724.609375px;
}
.sprite-sparkling_heart {
  background-position: -30.859375px -724.609375px;
}
.sprite-speak_no_evil {
  background-position: -59.765625px -724.609375px;
}
.sprite-speaker {
  background-position: -88.671875px -724.609375px;
}
.sprite-speech_balloon {
  background-position: -117.578125px -724.609375px;
}
.sprite-speedboat {
  background-position: -146.484375px -724.609375px;
}
.sprite-squirrel {
  background-position: -175.390625px -724.609375px;
}
.sprite-stackoverflow {
  background-position: -840.234375px -48.828125px;
}
.sprite-star {
  background-position: -208.59375px -724.609375px;
}
.sprite-star2 {
  background-position: -237.5px -724.609375px;
}
.sprite-stars {
  background-position: -266.40625px -724.609375px;
}
.sprite-station {
  background-position: -295.3125px -724.609375px;
}
.sprite-statue_of_liberty {
  background-position: -324.21875px -724.609375px;
}
.sprite-steam_locomotive {
  background-position: -353.125px -724.609375px;
}
.sprite-stew {
  background-position: -382.03125px -724.609375px;
}
.sprite-straight_ruler {
  background-position: -410.9375px -724.609375px;
}
.sprite-strawberry {
  background-position: -439.84375px -724.609375px;
}
.sprite-stuck_out_tongue {
  background-position: -468.75px -724.609375px;
}
.sprite-stuck_out_tongue_closed_eyes {
  background-position: -497.65625px -724.609375px;
}
.sprite-stuck_out_tongue_winking_eye {
  background-position: -526.5625px -724.609375px;
}
.sprite-sun_with_face {
  background-position: -555.46875px -724.609375px;
}
.sprite-sunflower {
  background-position: -584.375px -724.609375px;
}
.sprite-sunglasses {
  background-position: -613.28125px -724.609375px;
}
.sprite-sunny {
  background-position: -642.1875px -724.609375px;
}
.sprite-sunrise {
  background-position: -671.09375px -724.609375px;
}
.sprite-sunrise_over_mountains {
  background-position: -700px -724.609375px;
}
.sprite-surfer {
  background-position: -728.90625px -724.609375px;
}
.sprite-sushi {
  background-position: -757.8125px -724.609375px;
}
.sprite-suspect {
  background-position: -786.71875px -724.609375px;
}
.sprite-suspension_railway {
  background-position: -815.625px -724.609375px;
}
.sprite-sweat {
  background-position: -1.953125px -753.515625px;
}
.sprite-sweat_drops {
  background-position: -30.859375px -753.515625px;
}
.sprite-sweat_smile {
  background-position: -59.765625px -753.515625px;
}
.sprite-sweet_potato {
  background-position: -88.671875px -753.515625px;
}
.sprite-swimmer {
  background-position: -117.578125px -753.515625px;
}
.sprite-symbols {
  background-position: -146.484375px -753.515625px;
}
.sprite-syringe {
  background-position: -208.59375px -753.515625px;
}
.sprite-tada {
  background-position: -237.5px -753.515625px;
}
.sprite-tanabata_tree {
  background-position: -266.40625px -753.515625px;
}
.sprite-tangerine {
  background-position: -295.3125px -753.515625px;
}
.sprite-taurus {
  background-position: -324.21875px -753.515625px;
}
.sprite-taxi {
  background-position: -353.125px -753.515625px;
}
.sprite-tea {
  background-position: -382.03125px -753.515625px;
}
.sprite-telephone {
  background-position: -410.9375px -753.515625px;
}
.sprite-telephone_receiver {
  background-position: -439.84375px -753.515625px;
}
.sprite-telescope {
  background-position: -468.75px -753.515625px;
}
.sprite-tennis {
  background-position: -497.65625px -753.515625px;
}
.sprite-tent {
  background-position: -526.5625px -753.515625px;
}
.sprite-thought_balloon {
  background-position: -555.46875px -753.515625px;
}
.sprite-three {
  background-position: -584.375px -753.515625px;
}
.sprite-thumbsdown {
  background-position: -613.28125px -753.515625px;
}
.sprite-thumbsup {
  background-position: -642.1875px -753.515625px;
}
.sprite-ticket {
  background-position: -671.09375px -753.515625px;
}
.sprite-tiger {
  background-position: -700px -753.515625px;
}
.sprite-tiger2 {
  background-position: -728.90625px -753.515625px;
}
.sprite-tired_face {
  background-position: -757.8125px -753.515625px;
}
.sprite-tm {
  background-position: -786.71875px -753.515625px;
}
.sprite-toilet {
  background-position: -815.625px -753.515625px;
}
.sprite-tokyo_tower {
  background-position: -1.953125px -782.421875px;
}
.sprite-tomato {
  background-position: -30.859375px -782.421875px;
}
.sprite-tongue {
  background-position: -59.765625px -782.421875px;
}
.sprite-top {
  background-position: -88.671875px -782.421875px;
}
.sprite-tophat {
  background-position: -117.578125px -782.421875px;
}
.sprite-tractor {
  background-position: -146.484375px -782.421875px;
}
.sprite-traffic_light {
  background-position: -175.390625px -782.421875px;
}
.sprite-train {
  background-position: -204.296875px -782.421875px;
}
.sprite-train2 {
  background-position: -233.203125px -782.421875px;
}
.sprite-tram {
  background-position: -262.109375px -782.421875px;
}
.sprite-triangular_flag_on_post {
  background-position: -291.015625px -782.421875px;
}
.sprite-triangular_ruler {
  background-position: -319.921875px -782.421875px;
}
.sprite-trident {
  background-position: -348.828125px -782.421875px;
}
.sprite-triumph {
  background-position: -377.734375px -782.421875px;
}
.sprite-trolleybus {
  background-position: -406.640625px -782.421875px;
}
.sprite-trollface {
  background-position: -435.546875px -782.421875px;
}
.sprite-trophy {
  background-position: -464.453125px -782.421875px;
}
.sprite-tropical_drink {
  background-position: -493.359375px -782.421875px;
}
.sprite-tropical_fish {
  background-position: -522.265625px -782.421875px;
}
.sprite-truck {
  background-position: -551.171875px -782.421875px;
}
.sprite-trumpet {
  background-position: -580.078125px -782.421875px;
}
.sprite-tshirt {
  background-position: -608.984375px -782.421875px;
}
.sprite-tulip {
  background-position: -637.890625px -782.421875px;
}
.sprite-tumblr {
  background-position: -840.234375px -64.453125px;
}
.sprite-turtle {
  background-position: -666.796875px -782.421875px;
}
.sprite-tv {
  background-position: -695.703125px -782.421875px;
}
.sprite-twisted_rightwards_arrows {
  background-position: -724.609375px -782.421875px;
}
.sprite-twitter {
  background-position: -840.234375px -80.078125px;
}
.sprite-two {
  background-position: -753.515625px -782.421875px;
}
.sprite-two_hearts {
  background-position: -782.421875px -782.421875px;
}
.sprite-two_men_holding_hands {
  background-position: -811.328125px -782.421875px;
}
.sprite-two_women_holding_hands {
  background-position: -1.953125px -811.328125px;
}
.sprite-u5272 {
  background-position: -30.859375px -811.328125px;
}
.sprite-u5408 {
  background-position: -59.765625px -811.328125px;
}
.sprite-u55b6 {
  background-position: -88.671875px -811.328125px;
}
.sprite-u6307 {
  background-position: -117.578125px -811.328125px;
}
.sprite-u6708 {
  background-position: -146.484375px -811.328125px;
}
.sprite-u6709 {
  background-position: -175.390625px -811.328125px;
}
.sprite-u6e80 {
  background-position: -204.296875px -811.328125px;
}
.sprite-u7121 {
  background-position: -233.203125px -811.328125px;
}
.sprite-u7533 {
  background-position: -262.109375px -811.328125px;
}
.sprite-u7981 {
  background-position: -291.015625px -811.328125px;
}
.sprite-u7a7a {
  background-position: -319.921875px -811.328125px;
}
.sprite-uk {
  background-position: -348.828125px -811.328125px;
}
.sprite-umbrella {
  background-position: -377.734375px -811.328125px;
}
.sprite-unamused {
  background-position: -406.640625px -811.328125px;
}
.sprite-underage {
  background-position: -435.546875px -811.328125px;
}
.sprite-unlock {
  background-position: -464.453125px -811.328125px;
}
.sprite-up {
  background-position: -493.359375px -811.328125px;
}
.sprite-us {
  background-position: -522.265625px -811.328125px;
}
.sprite-v {
  background-position: -551.171875px -811.328125px;
}
.sprite-vertical_traffic_light {
  background-position: -580.078125px -811.328125px;
}
.sprite-vhs {
  background-position: -608.984375px -811.328125px;
}
.sprite-vibration_mode {
  background-position: -637.890625px -811.328125px;
}
.sprite-video_camera {
  background-position: -666.796875px -811.328125px;
}
.sprite-video_game {
  background-position: -695.703125px -811.328125px;
}
.sprite-violin {
  background-position: -724.609375px -811.328125px;
}
.sprite-virgo {
  background-position: -753.515625px -811.328125px;
}
.sprite-volcano {
  background-position: -782.421875px -811.328125px;
}
.sprite-vs {
  background-position: -811.328125px -811.328125px;
}
.sprite-walking {
  background-position: -855.859375px -1.953125px;
}
.sprite-waning_crescent_moon {
  background-position: -855.859375px -30.859375px;
}
.sprite-waning_gibbous_moon {
  background-position: -855.859375px -59.765625px;
}
.sprite-warning {
  background-position: -855.859375px -88.671875px;
}
.sprite-watch {
  background-position: -840.234375px -117.578125px;
}
.sprite-water_buffalo {
  background-position: -840.234375px -146.484375px;
}
.sprite-watermelon {
  background-position: -840.234375px -175.390625px;
}
.sprite-wave {
  background-position: -840.234375px -204.296875px;
}
.sprite-wavy_dash {
  background-position: -840.234375px -233.203125px;
}
.sprite-waxing_crescent_moon {
  background-position: -840.234375px -262.109375px;
}
.sprite-waxing_gibbous_moon {
  background-position: -840.234375px -291.015625px;
}
.sprite-wc {
  background-position: -840.234375px -319.921875px;
}
.sprite-weary {
  background-position: -840.234375px -348.828125px;
}
.sprite-wedding {
  background-position: -840.234375px -377.734375px;
}
.sprite-whale {
  background-position: -840.234375px -406.640625px;
}
.sprite-whale2 {
  background-position: -840.234375px -435.546875px;
}
.sprite-wheelchair {
  background-position: -840.234375px -464.453125px;
}
.sprite-white_check_mark {
  background-position: -840.234375px -493.359375px;
}
.sprite-white_circle {
  background-position: -840.234375px -522.265625px;
}
.sprite-white_flower {
  background-position: -840.234375px -551.171875px;
}
.sprite-white_large_square {
  background-position: -840.234375px -580.078125px;
}
.sprite-white_medium_small_square {
  background-position: -840.234375px -608.984375px;
}
.sprite-white_medium_square {
  background-position: -840.234375px -637.890625px;
}
.sprite-white_small_square {
  background-position: -844.53125px -666.796875px;
}
.sprite-white_square_button {
  background-position: -844.53125px -695.703125px;
}
.sprite-wind_chime {
  background-position: -844.53125px -724.609375px;
}
.sprite-wine_glass {
  background-position: -844.53125px -753.515625px;
}
.sprite-wink {
  background-position: -840.234375px -782.421875px;
}
.sprite-wolf {
  background-position: -840.234375px -811.328125px;
}
.sprite-woman {
  background-position: -1.953125px -840.234375px;
}
.sprite-womans_clothes {
  background-position: -30.859375px -840.234375px;
}
.sprite-womans_hat {
  background-position: -59.765625px -840.234375px;
}
.sprite-womens {
  background-position: -88.671875px -840.234375px;
}
.sprite-worried {
  background-position: -117.578125px -840.234375px;
}
.sprite-wrench {
  background-position: -146.484375px -840.234375px;
}
.sprite-x {
  background-position: -175.390625px -840.234375px;
}
.sprite-yellow_heart {
  background-position: -204.296875px -840.234375px;
}
.sprite-yen {
  background-position: -233.203125px -840.234375px;
}
.sprite-yum {
  background-position: -262.109375px -840.234375px;
}
.sprite-zap {
  background-position: -291.015625px -840.234375px;
}
.sprite-zero {
  background-position: -319.921875px -840.234375px;
}
.sprite-zzz {
  background-position: -348.828125px -840.234375px;
}
Diff truncated after the above file
src/styles/iconPath.scss src/styles/index.scss src/styles/mixin.scss src/styles/transition.scss src/styles/xr-theme.css src/styles/xr-theme.scss src/utils/auth.js src/utils/baseconfig.js src/utils/cache.js src/utils/dist/request.dev.js src/utils/dom.js src/utils/emoji-data.js src/utils/emoji.js src/utils/index.js src/utils/request.js src/utils/types.js src/utils/validate.js src/views/401.vue src/views/404.vue src/views/OAManagement/addressBook/department.vue src/views/OAManagement/addressBook/index.vue src/views/OAManagement/addressBook/staff.vue src/views/OAManagement/components/fileCell/index.vue src/views/OAManagement/components/relatedBusinessCell/index.vue src/views/OAManagement/examine/components/content.vue src/views/OAManagement/examine/components/examineCategorySelect.vue src/views/OAManagement/examine/components/examineCell.vue src/views/OAManagement/examine/components/examineCreateView.vue src/views/OAManagement/examine/components/examineDetail.vue src/views/OAManagement/examine/components/examineSection.vue src/views/OAManagement/examine/components/relatedBusiness.vue src/views/OAManagement/examine/components/xhExpenses.vue src/views/OAManagement/examine/components/xhLeaves.vue src/views/OAManagement/examine/index.vue src/views/OAManagement/journal/content.vue src/views/OAManagement/journal/index.vue src/views/OAManagement/journal/journalCell.vue src/views/OAManagement/journal/newDialog.vue src/views/OAManagement/notice/details.vue src/views/OAManagement/notice/edit.vue src/views/OAManagement/notice/index.vue src/views/OAManagement/notice/newDialog.vue src/views/OAManagement/notice/noticeCell.vue src/views/OAManagement/schedule/components/createSchedule.vue src/views/OAManagement/schedule/components/details.vue src/views/OAManagement/schedule/index.vue src/views/OAManagement/styles/content.scss src/views/OAManagement/styles/tabs.scss src/views/OAManagement/task/components/myTask.vue src/views/OAManagement/task/components/newDialog.vue src/views/OAManagement/task/components/particulars.vue src/views/OAManagement/task/components/subTask.vue src/views/OAManagement/task/components/tag/editTag.vue src/views/OAManagement/task/components/tag/newTag.vue src/views/OAManagement/task/components/tag/tagIndex.vue src/views/OAManagement/task/components/taskCell.vue src/views/OAManagement/task/index.vue src/views/OAManagement/task/mixins/listTaskDetail.js src/views/OAManagement/workbench/index.vue src/views/OAManagement/workbench/schedule.vue src/views/OAManagement/workbench/tabsContent.vue src/views/OAManagement/workbench/tabsJournal.vue src/views/OAManagement/workbench/task.vue src/views/PWS/EwsAnalyze.vue src/views/PWS/Subscriptions.vue src/views/clients/business/BusinessDetail.vue src/views/clients/business/BusinessIndex.vue src/views/clients/business/components/BusinessFollow.vue src/views/clients/businessChances/BusinessChancesDetail.vue src/views/clients/businessChances/BusinessChancesIndex.vue src/views/clients/businessChances/components/BusinessFollow.vue src/views/clients/businessContracts/BusinessContractsDetail.vue src/views/clients/businessContracts/BusinessContractsIndex.vue src/views/clients/businessContracts/components/ContractFollow.vue src/views/clients/businessCustomer/BusinessCustomerDetail.vue src/views/clients/businessCustomer/BusinessCustomerManage.vue src/views/clients/businessCustomer/components/BusinessCheck.vue src/views/clients/businessCustomer/components/CustomerFollow.vue src/views/clients/clue/ClueDetail.vue src/views/clients/clue/ClueIndex.vue src/views/clients/clue/components/ClueFollow.vue src/views/clients/components/CRMAllDetail.vue src/views/clients/components/CRMBaseInfo.vue src/views/clients/components/CRMCreateFileView.vue src/views/clients/components/CRMCreateView.vue src/views/clients/components/CRMDetailHead.vue src/views/clients/components/CRMExport.vue src/views/clients/components/CRMFullScreenDetail.vue src/views/clients/components/CRMImport.vue src/views/clients/components/CRMListHead.vue src/views/clients/components/CRMTableFilter.vue src/views/clients/components/CRMTableHead.vue src/views/clients/components/MixAdd.vue src/views/clients/components/RelativeApproval.vue src/views/clients/components/RelativeBusiness.vue src/views/clients/components/RelativeContacts.vue src/views/clients/components/RelativeContract.vue src/views/clients/components/RelativeFiles.vue src/views/clients/components/RelativeHandle.vue src/views/clients/components/RelativeOffers.vue src/views/clients/components/RelativeProduct.vue src/views/clients/components/RelativeReturnMoney.vue src/views/clients/components/RelativeSchedule.vue src/views/clients/components/RelativeTeam.vue src/views/clients/components/Sections.vue src/views/clients/components/duplicateCheck/checkContent.vue src/views/clients/components/duplicateCheck/index.vue src/views/clients/components/fieldsManager/FieldsSet.vue src/views/clients/components/filterForm/filterContent.vue src/views/clients/components/filterForm/index.vue src/views/clients/components/followLog/ExamineLog.vue src/views/clients/components/followLog/JournalLog.vue src/views/clients/components/followLog/RecordLog.vue src/views/clients/components/followLog/ScheduleLog.vue src/views/clients/components/followLog/TaskLog.vue src/views/clients/components/followLog/components/FollowRecordCell.vue src/views/clients/components/followLog/components/FollowRecordTable.vue src/views/clients/components/followLog/components/FollowScheduleCell.vue src/views/clients/components/followLog/styles/followcell.scss src/views/clients/components/sceneForm/SceneCreate.vue src/views/clients/components/sceneForm/SceneList.vue src/views/clients/components/sceneForm/SceneSet.vue src/views/clients/components/selectionHandle/AllocHandle.vue src/views/clients/components/selectionHandle/DealStatusHandle.vue src/views/clients/components/selectionHandle/TeamsHandle.vue src/views/clients/components/selectionHandle/TransferHandle.vue src/views/clients/contacts/ContactsDetail.vue src/views/clients/contacts/ContactsIndex.vue src/views/clients/contacts/components/ContactsFollow.vue src/views/clients/contract/ContractDetail.vue src/views/clients/contract/ContractIndex.vue src/views/clients/contract/components/ContractFollow.vue src/views/clients/customer/CustomerDetail.vue src/views/clients/customer/clientsManage.vue src/views/clients/customer/components/BusinessCheck.vue src/views/clients/customer/components/CustomerFollow.vue src/views/clients/customer/test.vue src/views/clients/mixins/detail.js src/views/clients/mixins/followLogType.js src/views/clients/mixins/loading.js src/views/clients/mixins/table.js src/views/clients/model/crmTypeModel.js src/views/clients/offers/OfferIndex.vue src/views/clients/product/ProductIndex.vue src/views/clients/sealContract/SealContractDetail.vue src/views/clients/sealContract/SealContractIndex.vue src/views/clients/sealOffers/SealOfferIndex.vue src/views/clients/styles/crmdetail.scss src/views/clients/styles/detailview.scss src/views/clients/styles/followcell.scss src/views/clients/styles/followlog.scss src/views/clients/styles/relativecrm.scss src/views/clients/styles/table.scss src/views/company/ApartmentManage.vue src/views/company/employeeManage/EmployeeManage.vue src/views/company/employeeManage/components/EmployeeDetail.vue src/views/company/offcialAuthority.vue src/views/company/staffLog.vue src/views/company/systemSetting.vue src/views/home/Home.vue src/views/login/index.vue src/views/login/logining.vue src/views/module/ModuleManage.vue src/views/welcome/Welcome.vue static/.gitkeep static/client.js webpack-dev-server