[
  {
    "path": ".editorconfig",
    "content": "root = true\r\n\r\n[*]\r\ncharset = utf-8\r\nindent_style = space\r\nindent_size = 2\r\nend_of_line = lf\r\ninsert_final_newline = true\r\ntrim_trailing_whitespace = true\r\n"
  },
  {
    "path": ".eslintignore",
    "content": "/src/campus-card-page/components/wxcharts-min.js\r\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\r\n  root: true,\r\n  parser: \"babel-eslint\",\r\n  parserOptions: {\r\n    sourceType: \"module\"\r\n  },\r\n  env: {\r\n    browser: true\r\n  },\r\n  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style\r\n  extends: [\"prettier\"],\r\n  // required to lint *.wpy files\r\n  plugins: [\"html\", \"prettier\"],\r\n  settings: {\r\n    \"html/html-extensions\": [\".html\", \".wpy\"]\r\n  },\r\n  // add your custom rules here\r\n  rules: {\r\n    \"prettier/prettier\": \"error\",\r\n    // allow paren-stylus arrow functions\r\n    \"arrow-parens\": 0,\r\n    // allow async-await\r\n    \"generator-star-spacing\": 0,\r\n    // allow debugger during development\r\n    \"no-debugger\": process.env.NODE_ENV === \"production\" ? 2 : 0,\r\n    \"space-before-function-paren\": 0,\r\n    \"standard/computed-property-even-spacing\": 0\r\n  },\r\n  prettier: {\r\n    singleQuote: true,\r\n    semi: false\r\n  },\r\n  globals: {\r\n    getCurrentPages: true\r\n  }\r\n};\r\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Smartphone (please complete the following information):**\n - Device: [e.g. iPhone6]\n - OS: [e.g. iOS8.1]\n - Browser [e.g. stock browser, safari]\n - Version [e.g. 22]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".gitignore",
    "content": "dist/*\r\nnode_modules/*\r\nsrc/config/*\r\n.DS_Store\r\n.idea/*\r\n.vscode/*\r\n.wepycache\r\nsrc/api/*"
  },
  {
    "path": ".prettierrc",
    "content": "{\r\n  \"singleQuote\": false,\r\n  \"semi\": true,\r\n  \"overrides\": [\r\n    {\r\n      \"files\": \"*.wpy\",\r\n      \"options\": {\r\n        \"parser\": \"babylon\"\r\n      }\r\n    }\r\n  ]\r\n}\r\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "### 3.4.6 (2018-12-25)\n\n- 添加电费余额查询\n\n### 3.4.5 (2018-12-22)\n\n- 添加 `wx.updateManager`\n\n### 3.4.4 (2018-12-21)\n\n- 添加金额操作记录页面\n\n### 3.4.3 (2018-12-16)\n\n- 更改一卡通支付逻辑\n- 修复电费充值的若干 bug\n\n### 3.4.2 (2018-12-07)\n\n- module 接口改为到具体页面接入,让首页顶部的 icon 加载更快\n\n### 3.4.1 (2018-12-04)\n\n- 将体育部,问卷页面和 userInfo 解耦\n- 问卷,考试倒计时,体育部页面添加 Loading\n\n### 3.4.0 (2018-11-10)\n\n- 消息盒子的提示红点\n- 资讯 TabBar 的小红点\n- 拦截器的 API 替换\n- 校园卡拾取的匿名\n\n### 3.3.4 (2018-10-23)\n\n- 修复消息盒子不提示的 bug\n- 优化图书馆模块的代码\n- 修复淘宝口令会弹出社团招新模态框的 bug 以及添加可以关闭模态框\n\n### 3.3.1 (2018-10-17)\n\n- 增加 `wx-axios` 模块以及拦截器的整合,重构 API 列表\n- 修复来回登录的 bug 以及更新错误处理\n- 首页的逻辑,代码优化\n\n### 3.3.0 (2018-10-16)\n\n- 整合开源版本\n- 修复充值组件需要嵌套 `$parent` 的 bug\n\n### 3.2.2 (2018-10-01)\n\n- 导航栏切换为迎国庆\n\n### 3.2.1 (2018-09-07)\n\n- 导航栏切换为开学季\n\n### 3.2.0 (2018-8-13)\n\n- 修改注册登录的逻辑\n- 增加了修改绑定手机功能\n- 更新了一卡通的页面风格\n- 增加了电费充值绑定宿舍的功能\n- 增加了学费查询功能\n- 添加跳转到校谈的入口\n- 微调了一些 ui，修复了一些 bug\n- 运营在痛骂程序员不给力\n\n### 3.0.1 (2018-4-20)\n\n- 登录注册添加友好错误提示\n- 修复图书馆搜索结果 bug\n- 修复反馈对话界面的消息排版出错 bug\n- 修复挂失列表加载问题\n- 完成考试倒计时\n\n### 3.0.0 (2018-4-8)\n\n- 新增绑定用户手机号功能\n- 新增电费、网费充值\n- 新增用户消息系统\n- 新增搜索功能页\n- 新增 GPA 计算器\n- 完善课表查询\n- 完善考试倒计时\n- 祭天了一个产品经理\n\n### 2.4.0 (2017-10-12)\n\n- 增加了青柚工作室招新\n- 更改了欢迎页面\n- 增加了我的反馈页面，大家可以看到自己的反馈状态\n- 程序员已经快要祭不动了\n\n### 2.3.0 (2017-9-1)\n\n- 修复社团招新的一些 bug\n- 校园卡功能恢复\n- 新增了欢迎页面\n- 体育部功能恢复正常使用\n- 祭天的程序员被拉出来又祭了一次\n\n### 2.0.0 (2017-8-10)\n\n- 新增更多功能入口\n- 新增考试查询、补考查询，等级考试，补考辅导课查询功能\n- 新增查学费功能\n- 新增图书馆荐购功能\n- 新增校园卡挂失，解挂失，发布挂失消息功能\n- 新增资讯详情页附件在线预览功能\n- 完善更新密码的方式\n- 完善课表查询功能"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    Undergraduate\n    Copyright (C) 2018  GreenPomelo\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published\n    by the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README-zh_CN.md",
    "content": "## 南京邮电大学小程序\n\n[English](./README.md) | 简体中文\n\n### 介绍\n\n南京邮电大学小程序是由南京邮电大学青柚工作室开发，一款方便快捷，无需下载安装即可在微信客户端即开即用的 APP，有别于一般需要下载安装的 APP，也不同于微信公众号，具有方便快捷的特点。\n\n<p align=\"center\">\n<img src=\"https://static.airbob.org/under-graduate/undergraduate-qrcode.jpg\" alt=\"菊花码\" width=\"200\" height=\"200\">\n</p>\n\n### 学习本项目\n\n整套前端使用 [Wepy](https://github.com/tencent/wepy) 开发，提倡前端组件化工程化，高效的完成前端项目。\n\n#### 项目文件结构\n\n```\nproject\n│\n└───src\n│   │   assets 静态图片\n│   │\n│   └───campus-card-page\n│   │    │   components 校园卡模块组件\n│   │    │   pages      校园卡模块页面\n│   │\n│   └───components 全局组件\n│   │    │   qy-container.wpy\n│   │    │   qy-navigation.wpy\n│   │    │   ...\n│   │\n│   └───css 全局样式\n│   │    │   global-style.styl\n│   │    │   loading.styl\n│   │    │   ...\n│   │\n│   └───edu-admin-page\n│   │    │   components 正方模块组件\n│   │    │   pages      正方模块页面\n│   │\n│   └───mixins 混入\n│   │    │   Gpa                  Gpa 计算器的 mixin\n│   │    │   class.js             课表的 mixin\n│   │    │   all-search-thing.js  模块开关的控制\n│   │    │   ...\n│   │\n│   └───others-edu-page\n│   │    │   components 体育部模块组件\n│   │    │   pages      体育部模块页面\n│   │\n│   └───others-page\n│   │    │   components 其他模块组件\n│   │    │   pages      其他模块页面\n│   │\n│   └───pages 三个主页面\n│   │    │   index.wpy     首页\n│   │    │   news-list.wpy 资讯页\n│   │    │   profile.wpy   个人中心页\n│   │\n│   └───store 状态管理\n│   │\n│   └───utils 工具辅助函数\n│   │\n│   └───app.wpy 项目配置\n│\n│   .editorconfig\n│   .eslintignore\n│   .eslintrc.js\n│   .gitignore\n│   .prettierrc\n│   CHANGELOG.md\n│   LICENSE\n│   README.md\n│   package.json\n│   wepy.config.js\n\n```\n\n#### 安装（更新） wepy 命令行工具\n\n> node >= 8.9\n\n```bash\n$ npm install -g wepy-cli\n```\n\n#### 安装依赖 & 开发实时编译\n\n```\n$ cd [project]\n\n$ npm install\n\n$ npm run dev\n```\n\n------\n\n### 青柚工作室\n\n[青柚工作室的主页](https://qingyou.njupt.edu.cn)\n\n青柚工作室是由南京邮电大学信息办指导建设，以学生开发为核心的互联网工作团队。\n\n倡导使用新技术、优秀的技术去实现智慧校园，服务同学。\n\n本项目至少会持续维护到南京邮电大学本科生 3.x 版本结束。\n\n------\n\n### 开源许可\n\n本项目使用开源许可证 `License AGPLv3` ，代码开源仅供学习。\n\n请认真阅读并遵守以下开源协议\n\n`AGPLv3` [GNU Affero General Public License v3.0](https://github.com/GreenPomelo/Undergraduate/blob/master/LICENSE)\n\n#### 青柚工作室开源计划：\n\n希望能够将实战中的技术成果回报社区，并且鼓励社区为这个项目做出贡献，大家可以通过 `Pull Requests` 的方式帮我们解决目前存在的不足，或者通过 `Issues` 告知我们。\n\n------\n\n### 青柚工作室招新计划：\n\n青柚工作室持续招新，对象为南京邮电大学全日制本科生，主要以大二大三在校学生为主，大一能力强者亦可。招新岗位为技术、外联、运营、办公、程序员鼓励师......希望有兴趣的同学能投递简历至`qingyou@njupt.edu.cn`，一起来用爱发电，为南邮做出更多方便师生的项目。\n\n------\n\n### 更新日志\n\n[CHANGELOG](./CHANGELOG.md)\n\n\n<table>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/solojiang\"><img src=\"https://github.com/solojiang.png?s=64\" width=\"100px;\"/><br /><sub><b>狒狒神</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/Bosspwn\"><img src=\"https://github.com/Bosspwn.png?s=64\" width=\"100px;\"/><br /><sub><b>Boss Pwn</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/flytam\"><img src=\"https://github.com/flytam.png?s=64\" width=\"100px;\"/><br /><sub><b>Flytam</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/GooeyNyan\"><img src=\"https://github.com/GooeyNyan.png?s=64\" width=\"100px;\"/><br /><sub><b>GooeyNyan</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/UZIhuhuhu\"><img src=\"https://github.com/UZIhuhuhu.png?s=64\" width=\"100px;\"/><br /><sub><b>WynnXin</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/niffler-bkkkk\"><img src=\"https://github.com/niffler-bkkkkk.png?s=64\" width=\"100px;\"/><br /><sub><b>niffler-bkkkk</b></sub></a><br /></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/kishivn\"><img src=\"https://github.com/kishivn.png?s=64\" width=\"100px;\"/><br /><sub><b>kishivn</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/ChenKS12138\"><img src=\"https://github.com/ChenKS12138.png?s=64\" width=\"100px;\"/><br /><sub><b>ChenKS12138</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/cucu6\"><img src=\"https://github.com/cucu6.png?s=64\" width=\"100px;\"/><br /><sub><b>cucu6</b></sub></a><br /></td>\n  </tr>\n</table>\n"
  },
  {
    "path": "README.md",
    "content": "## MiniProgram of Nanjing University of Posts and Telecommunications\n\nEnglish | [简体中文](./README-zh_CN.md)\n\n### Introduction\n\nThe MiniProgram of Nanjing University of Posts and Telecommunications(hereinafter called NJUPT MiniProgram), developed by QingYou Studio of NJUPT, which is a convenient and swift application that can launch in WeChat client immediately dispense with download and install. Different from the common applications that need to download and install and WeChat Official Account, it is convenient and efficient.\n\n<p align=\"center\">\n<img src=\"https://static.airbob.org/under-graduate/undergraduate-qrcode.jpg\" alt=\"菊花码\" width=\"200\" height=\"200\">\n</p>\n\n### Learn this Project\n\nAdvocating componentization and engineering of front-end, this project is developed by [Wepy](https://github.com/tencent/wepy), to finish front-end project efficiently.\n\n### Files Structure\n\n```\nproject\n│\n└───src\n│   │   assets                          static images\n│   │\n│   └───campus-card-page\n│   │    │   components                 components of Campus-card module\n│   │    │   pages                      pages of Campus-card module\n│   │\n│   └───components                      global components\n│   │    │   qy-container.wpy\n│   │    │   qy-navigation.wpy\n│   │    │   ...\n│   │\n│   └───css               \t\t\t    global css style\n│   │    │   global-style.styl\n│   │    │   loading.styl\n│   │    │   ...\n│   │\n│   └───edu-admin-page\n│   │    │   components                 components of ZHENGFANG module\n│   │    │   pages                      pages of ZHENGFANG module\n│   │\n│   └───mixins\n│   │    │   Gpa                        mixin of GPA Calculator\n│   │    │   class.js                   mixin of Curriculum\n│   │    │   all-search-thing.js        controller of modules\n│   │    │   ...\n│   │\n│   └───others-edu-page\n│   │    │   components                 components of PE module\n│   │    │   pages                      pages of PE module\n│   │\n│   └───others-page\n│   │    │   components                 components of other modules\n│   │    │   pages                      pages of other modules\n│   │\n│   └───pages                           Main Pages\n│   │    │   index.wpy                  Homepage\n│   │    │   news-list.wpy\t\t\t    Information Page\n│   │    │   profile.wpy   \t\t\t    Personal Page\n│   │\n│   └───store \t\t\t\t\t\t    state management\n│   │\n│   └───utils \t\t\t\t\t\t    auxiliary functions\n│   │\n│   └───app.wpy \t\t\t\t\t    project config\n│\n│   .editorconfig\n│   .eslintignore\n│   .eslintrc.js\n│   .gitignore\n│   .prettierrc\n│   CHANGELOG.md\n│   LICENSE\n│   README.md\n│   package.json\n│   wepy.config.js\n\n```\n\n### Install (Update) Wepy-Cli\n\n> node >= 8.9\n\n```bash\n$ npm install -g wepy-cli\n```\n\n### Install Dependencies & Serve with Hot Reload\n\n```\n$ cd [project]\n\n$ npm install\n\n$ npm run dev\n```\n\n------\n\n### QingYou Studio\n\n[Homepage of QingYou Studio](https://qingyou.njupt.edu.cn)\n\nBuilt up by Information Office of NJUPT, QingYou Studio is an Internet working team with student developement as its core.\n\nWe advocate to use new and excellent technologies to achieve the Smart Campus and to serve students.\n\nThis project will be maintained at least until the end of the 3.x version of NJUPT-Undergraduate.\n\n------\n\n### License\n\nThis project uses the license `License AGPLv3`,and the code is open source for learning.\n\nPlease read and abide by the following open source agreements:\n\n`AGPLv3` [GNU Affero General Public License v3.0](https://github.com/GreenPomelo/Undergraduate/blob/master/LICENSE)\n\n### QingYou Studio Open Source\n\nWe hope that we can return the technical achievements to the community, and we encourage the community to contribute to this project. You can help us resolve the existing deficiencises through `Pull Request`, or tell us through `Issue`.\n\n------\n\n### QingYou Studio Recruitment\n\nMainly in the sophomore and junior students, QingYou Studio is recruiting new members from the full-time undergraduates in NJUPT, and the freshman who has excellent ability can be also recruited. Our posts contain technology, outreach, operations, office and ...... We hope anyone interested in can submit your resume to `qingyou@njupt.edu.cn`, together with us to do more projects for teachers and students in NJUPT.\n\n------\n\n### Update Log\n\n[CHANGELOG](./CHANGELOG.md)\n\n-----\n\n### Core Team(Contributors)\n\n<table>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/solojiang\"><img src=\"https://github.com/solojiang.png?s=64\" width=\"100px;\"/><br /><sub><b>狒狒神</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/Bosspwn\"><img src=\"https://github.com/Bosspwn.png?s=64\" width=\"100px;\"/><br /><sub><b>Boss Pwn</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/flytam\"><img src=\"https://github.com/flytam.png?s=64\" width=\"100px;\"/><br /><sub><b>Flytam</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/GooeyNyan\"><img src=\"https://github.com/GooeyNyan.png?s=64\" width=\"100px;\"/><br /><sub><b>GooeyNyan</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/UZIhuhuhu\"><img src=\"https://github.com/UZIhuhuhu.png?s=64\" width=\"100px;\"/><br /><sub><b>WynnXin</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/niffler-bkkkk\"><img src=\"https://github.com/niffler-bkkkkk.png?s=64\" width=\"100px;\"/><br /><sub><b>niffler-bkkkk</b></sub></a><br /></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/kishivn\"><img src=\"https://github.com/kishivn.png?s=64\" width=\"100px;\"/><br /><sub><b>kishivn</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/ChenKS12138\"><img src=\"https://github.com/ChenKS12138.png?s=64\" width=\"100px;\"/><br /><sub><b>ChenKS12138</b></sub></a><br /></td>\n    <td align=\"center\"><a href=\"https://github.com/cucu6\"><img src=\"https://github.com/cucu6.png?s=64\" width=\"100px;\"/><br /><sub><b>cucu6</b></sub></a><br /></td>\n  </tr>\n</table>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"undergraduate\",\n  \"version\": \"3.4.24\",\n  \"description\": \"NJUPT wechat app for undergraduate students\",\n  \"main\": \"dist/app.js\",\n  \"file\": [\n    \"src\"\n  ],\n  \"scripts\": {\n    \"dev\": \"wepy build --watch\",\n    \"build\": \"cross-env NODE_ENV=production wepy build --no-cache\",\n    \"lint\": \"./node_modules/.bin/eslint --fix src/**\",\n    \"precommit\": \"lint-staged\",\n    \"format\": \"prettier-eslint --write *.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/GreenPomelo/Undergraduate\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/GreenPomelo/Undergraduate/issues\"\n  },\n  \"keywords\": [\n    \"wechat-app\"\n  ],\n  \"author\": \"GreenPomelo <qingyou@njupt.edu.cn>\",\n  \"license\": \"AGPL\",\n  \"lint-staged\": {\n    \"*.{js,wpy}\": [\n      \"./node_modules/.bin/eslint --fix\",\n      \"git add\"\n    ]\n  },\n  \"dependencies\": {\n    \"@types/crypto-js\": \"^3.1.43\",\n    \"crypto-js\": \"^3.1.9-1\",\n    \"qs\": \"^6.5.2\",\n    \"redux\": \"^3.7.2\",\n    \"redux-actions\": \"^2.2.1\",\n    \"redux-promise\": \"^0.5.3\",\n    \"stylus\": \"^0.54.5\",\n    \"we-rich\": \"^1.0.2\",\n    \"wepy\": \"^1.7.1\",\n    \"wepy-async-function\": \"^1.4.4\",\n    \"wepy-redux\": \"^1.5.3\",\n    \"wx-axios\": \"^0.0.7\"\n  },\n  \"devDependencies\": {\n    \"babel-eslint\": \"^7.2.1\",\n    \"babel-plugin-transform-class-properties\": \"^6.24.1\",\n    \"babel-plugin-transform-decorators-legacy\": \"^1.3.4\",\n    \"babel-plugin-transform-export-extensions\": \"^6.22.0\",\n    \"babel-plugin-transform-object-rest-spread\": \"^6.26.0\",\n    \"babel-preset-env\": \"^1.6.1\",\n    \"babel-preset-stage-1\": \"^6.24.1\",\n    \"cross-env\": \"^5.1.1\",\n    \"eslint\": \">=4.18.2\",\n    \"eslint-config-prettier\": \"^2.9.0\",\n    \"eslint-friendly-formatter\": \"^2.0.7\",\n    \"eslint-plugin-html\": \"^3.2.2\",\n    \"eslint-plugin-prettier\": \"^2.3.1\",\n    \"eslint-plugin-promise\": \"^3.5.0\",\n    \"husky\": \"^0.14.3\",\n    \"lint-staged\": \"^4.3.0\",\n    \"prettier\": \"^1.7.4\",\n    \"prettier-eslint-cli\": \"^4.7.0\",\n    \"wepy-compiler-babel\": \"^1.5.1\",\n    \"wepy-compiler-pug\": \"^1.4.7\",\n    \"wepy-compiler-stylus\": \"^1.3.10\",\n    \"wepy-eslint\": \"^1.5.2\",\n    \"wepy-plugin-autoprefixer\": \"^1.5.10\",\n    \"wepy-plugin-imagemin\": \"^1.5.2\",\n    \"wepy-plugin-uglifyjs\": \"^1.3.6\"\n  },\n  \"homepage\": \"https://qingyou.njupt.edu.cn\"\n}\n"
  },
  {
    "path": "src/app.wpy",
    "content": "<style lang=\"stylus\">\n.container\n  font-family -apple-system-font, Helvetica Neue, Helvetica, sans-serif\n</style>\n\n<script>\nimport wepy from \"wepy\";\nimport { setStore } from \"wepy-redux\";\nimport configStore from \"./store/index\";\n// 抽离api\nimport \"wepy-async-function\";\n// redux store\nconst store = configStore();\nsetStore(store);\nwepy.$store = store;\n\n// override showToast\nexport default class extends wepy.app {\n  config = {\n    pages: [\"pages/index\", \"pages/news-list\", \"pages/profile\"],\n    subPackages: [\n      {\n        root: \"others-page/\",\n        pages: [\n          \"pages/search\",\n          \"pages/login\",\n          \"pages/news\",\n          \"pages/information-box\",\n          \"pages/libraryPages/library\",\n          \"pages/libraryPages/library-recommened\",\n          \"pages/libraryPages/library-history\",\n          \"pages/run\",\n          \"pages/feedbackPages/feedback\",\n          \"pages/feedbackPages/myfeedback\",\n          \"pages/feedbackPages/historyfeedback\",\n          \"pages/more\",\n          \"pages/personalPages/changelog\",\n          \"pages/personalPages/aboutus\",\n          \"pages/close\",\n          \"pages/personalPages/protocol\",\n          \"pages/advertisement\",\n          \"pages/display-webview\",\n          \"pages/tuition\",\n          \"pages/personalPages/change-phone\",\n          \"pages/personalPages/change-password\",\n          \"pages/associationPages/association\",\n          \"pages/associationPages/association-detail\",\n          \"pages/associationPages/association-register\",\n          \"pages/associationPages/register-success\",\n          \"pages/associationPages/club-personal\",\n          \"pages/auth\",\n          \"pages/questionnairePages/questionnaire-homepage\",\n          \"pages/questionnairePages/questionnaire\",\n          \"pages/nicpPages/nicp-check-in\",\n          \"pages/nicpPages/nicp-vote\",\n          \"pages/nicpPages/nicp-more\",\n          \"pages/school-bus\"\n        ]\n      },\n      {\n        root: \"edu-admin-page/\",\n        pages: [\n          \"pages/supplement-and-tutorials\",\n          \"pages/check-grade\",\n          \"pages/cut-down\",\n          \"pages/course\",\n          \"pages/search-course\",\n          \"pages/score-inquire\",\n          \"pages/credit\"\n        ]\n      },\n      {\n        root: \"others-edu-page/\",\n        pages: [\n          \"pages/pe-score\",\n          \"pages/GpaCalculator\",\n          \"pages/calendar\",\n          \"graduatePages/index\",\n          \"graduatePages/memory-choose\",\n          \"graduatePages/memory-mode\",\n          \"graduatePages/clear-memory\",\n          \"graduatePages/say-goodbye\"\n          // \"pages/avatar\"\n        ]\n      },\n      {\n        root: \"campus-card-page/\",\n        pages: [\n          \"pages/campus-card-index\",\n          \"pages/campus-card-charge\",\n          \"pages/campus-card-loss\",\n          \"pages/money-log\",\n          \"pages/campus-card-lossPage\",\n          \"pages/consumption-detail\",\n          \"pages/electric-charge\",\n          \"pages/net-charge\",\n          \"pages/select-room\",\n          \"pages/add-room\"\n        ]\n      }\n    ],\n    window: {\n      backgroundTextStyle: \"dark\",\n      navigationBarBackgroundColor: \"#ffffff\",\n      navigationBarTitleText: \"NJUPT\",\n      navigationBarTextStyle: \"black\",\n      navigationStyle: \"custom\"\n    },\n    tabBar: {\n      color: \"#353535\",\n      selectedColor: \"#47CFF5\",\n      backgroundColor: \"#ffffff\",\n      list: [\n        {\n          pagePath: \"pages/index\",\n          text: \"首页\",\n          iconPath: \"assets/index.png\",\n          selectedIconPath: \"assets/index-active.png\"\n        },\n        {\n          pagePath: \"pages/news-list\",\n          text: \"资讯\",\n          iconPath: \"assets/news-list.png\",\n          selectedIconPath: \"assets/news-list-active.png\"\n        },\n        {\n          pagePath: \"pages/profile\",\n          text: \"我的\",\n          iconPath: \"assets/profile.png\",\n          selectedIconPath: \"assets/profile-active.png\"\n        }\n      ]\n    },\n    navigateToMiniProgramAppIdList: [\"wx7d66d77988bbeab3\", \"wxf8b4559a02c8266d\"]\n  };\n  globalData = {\n    cancelTokenData: {\n      name: \"123\"\n    },\n    userInfo: null,\n    associationUserTableInfo: {},\n    associationStatus: [],\n    modules: [\n      {\n        name: \"课表\",\n        path: \"../edu-admin-page/pages/course\",\n        src: \"https://static.airbob.org/under-graduate/more/timetable.png\",\n        isIndex: true,\n        id: 16,\n        isOpen: true,\n        isNew: false,\n        module: \"正方\"\n      },\n      {\n        name: \"成绩查询\",\n        path: \"../edu-admin-page/pages/score-inquire\",\n        src: \"https://static.airbob.org/under-graduate/more/results query.png\",\n        isIndex: true,\n        id: 9,\n        isOpen: true,\n        isNew: false,\n        module: \"正方\"\n      },\n      {\n        name: \"一卡通\",\n        path: \"../campus-card-page/pages/campus-card-index\",\n        src: \"https://static.airbob.org/under-graduate/more/card.png\",\n        isIndex: true,\n        id: 4,\n        isOpen: true,\n        isNew: false,\n        module: \"一卡通\"\n      },\n      {\n        name: \"图书馆\",\n        path: \"../others-page/pages/libraryPages/library\",\n        src: \"https://static.airbob.org/under-graduate/more/library.png\",\n        isIndex: true,\n        id: 0,\n        isOpen: true,\n        isNew: false,\n        module: \"图书馆\"\n      },\n      {\n        name: \"晨跑\",\n        path: \"../others-page/pages/run\",\n        src: \"https://static.airbob.org/under-graduate/more/run.png\",\n        isIndex: true,\n        id: 19,\n        isOpen: true,\n        isNew: false,\n        module: \"晨跑\"\n      },\n      {\n        name: \"体育部\",\n        path: \"../others-edu-page/pages/pe-score\",\n        src: \"https://static.airbob.org/under-graduate/more/sport.png\",\n        isIndex: true,\n        id: 10,\n        isOpen: true,\n        isNew: false,\n        module: \"体育部\"\n      },\n      {\n        name: \"GPA计算器\",\n        src: \"https://static.airbob.org/under-graduate/more/gpa.png\",\n        isIndex: true,\n        id: 21,\n        path: \"../others-edu-page/pages/GpaCalculator\",\n        module: \"正方\",\n        isOpen: true,\n        isNew: false\n      },\n      {\n        name: \"更多\",\n        path: \"../others-page/pages/more\",\n        src: \"https://static.airbob.org/under-graduate/more/more.png\",\n        isIndex: true,\n        id: -1,\n        isNew: false\n      }\n    ]\n  };\n  constructor() {\n    super();\n    this.use(\"requestfix\");\n    this.use(\"promisify\");\n  }\n  onLaunch() {\n    const updateManager = wx.getUpdateManager();\n\n    updateManager.onUpdateReady(function() {\n      wepy\n        .showModal({\n          title: \"更新提示\",\n          content: \"新版本已经准备好，是否重启应用？\"\n        })\n        .then(res => {\n          if (res.confirm) {\n            updateManager.applyUpdate();\n          }\n        });\n    });\n  }\n  showTip(title = \"请求发生错误\") {\n    wepy.showToast({\n      title,\n      icon: \"none\"\n    });\n  }\n  timeToDate(timestamp) {\n    const date = new Date(timestamp);\n    const Y = date.getFullYear() + \"-\";\n    const M =\n      (date.getMonth() + 1 < 10\n        ? \"0\" + (date.getMonth() + 1)\n        : date.getMonth() + 1) + \"-\";\n    const D = date.getDate() + \" \";\n    return Y + M + D;\n  }\n}\n</script>\n\n\n"
  },
  {
    "path": "src/campus-card-page/components/consumption-detail-card.wpy",
    "content": "<template>\n    <view class=\"card-container\">\n        <view class=\"time\">{{occTime}}</view>\n        <repeat for=\"{{list}}\" key=\"index\">\n          <view class=\"card-list\">\n              <view class=\"list-item\" >{{item.mercname}}</view>\n              <view class=\"list-item\">{{item.tranname}}</view>\n              <view class=\"list-item {{item.tranamt>0?'add':'des'}}\">{{item.tranamt}}</view>\n          </view>\n        </repeat>\n\n    </view>\n</template>\n<script>\nimport wepy from \"wepy\";\nexport default class ConsumptionDetail extends wepy.component {\n  props = {\n    list: {\n      default: [],\n      type: Array\n    },\n    occTime: {\n      default: \"\",\n      type: String\n    }\n  };\n}\n</script>\n<style lang=\"stylus\" scoped>\n.card-container\n  color #353535\n  display flex\n  flex-direction column\n  align-items center\n  .time\n    font-size 24rpx\n    font-weight bold\n    height 60rpx\n    line-height 60rpx\n    color #888\n  .card-list\n    display flex\n    width 100%\n    background-color rgb(255,255,255)\n    & + .card-list\n      border-top 2rpx solid #E3E3E3\n    .list-item\n      width 33%\n      font-size 28rpx\n      text-align center\n      word-break keep-all\n      white-space nowrap\n      overflow hidden\n      text-overflow ellipsis\n      height 84rpx\n      line-height 84rpx\n    .add\n      color #09BB07\n      font-weight bold\n    .des\n      color #E64340\n      font-weight bold\n</style>\n"
  },
  {
    "path": "src/campus-card-page/components/pay-flow.wpy",
    "content": "<template>\n  <view class=\"mask-container\" hidden=\"{{!open}}\" animation=\"{{coverAnimation}}\">\n    <view class=\"pay-container\" style=\"height: {{soterPay ? '635rpx' : '770rpx'}}\">\n      <image\n        @tap.stop=\"closeModal\"\n        mode=\"widthFix\"\n        src=\"https://static.airbob.org/under-graduate/charge/btu_close.png\"\n        class=\"close\"\n      />\n      <view class=\"confirm\">确认充值</view>\n      <view class=\"change-pay-type\" @tap=\"changePayType\" wx:if=\"{{isSoterAble && failPayTimes < 5}}\">{{ soterPay ? \"输入密码\" : \"使用指纹\" }}</view>\n      <block>\n        <view class=\"charge-text\">￥ {{showCharge}}</view>\n        <view class=\"small-list\">\n          <view class=\"text1\">操作内容</view>\n          <view class=\"text2\">{{operateContent}}</view>\n        </view>\n        <view class=\"small-list\">\n          <view class=\"text1\">充值方式</view>\n          <view class=\"text2\">{{payWay}}</view>\n        </view>\n        <view wx:if=\"{{open && soterPay}}\" class=\"confirm-button\">\n          <button class=\"pay-button\" @tap.stop=\"handlePay\">确认支付</button>\n        </view>\n        <view wx:if=\"{{open && !soterPay}}\">\n          <Pw color=\"black\"/>\n        </view>\n      </block>\n    </view>\n  </view>\n</template>\n\n<script>\n// 支付流程\nimport wepy from \"wepy\";\nimport Pw from \"./pwdfield\";\nimport {\n  transferCard,\n  transferNet,\n  transferEle,\n  verifyFingerPrint\n} from \"@/api/campusCard\";\n\nexport default class PayFlow extends wepy.component {\n  props = {\n    charge: {\n      default: 0,\n      type: [Number, String],\n      twoWay: true\n    },\n    payWay: String,\n    operateContent: String,\n    open: {\n      default: false,\n      type: Boolean,\n      twoWay: true\n    },\n    electricURL: {\n      type: String,\n      twoWay: true,\n      default: \"\" // 只有电费才用这个\n    },\n    type: String // 充值的类型 card net electric\n  };\n  components = {\n    Pw\n  };\n  data = {\n    coverAnimation: {},\n    password: \"\",\n    showCharge: 0,\n    //  是否支持生物认证\n    isSoterAble: false,\n    //  支付方式\n    soterPay: false,\n    //  识别失败次数，大于5次后使用密码支付\n    failPayTimes: 0\n  };\n  watch = {\n    open: next => {\n      const coverAnimation = wepy.createAnimation({\n        timingFunction: \"ease-in-out\"\n      });\n      if (next) {\n        this.coverAnimation = coverAnimation\n          .backgroundColor(\"rgba(0,0,0,0.5)\")\n          .step()\n          .export();\n      } else {\n        this.coverAnimation = coverAnimation\n          .backgroundColor(\"rgba(0,0,0,0)\")\n          .step()\n          .export();\n      }\n      this.$invoke(\"Pw\", \"clear\");\n      this.$apply();\n    },\n    charge: next => {\n      if (typeof next === \"number\") {\n        this.showCharge = next.toFixed(2);\n        this.$apply();\n      }\n    }\n  };\n  events = {\n    value: val => {\n      // 发起支付\n      this.password = val;\n      this.enterPay();\n      this.$apply();\n    }\n  };\n  methods = {\n    closeModal() {\n      this.handleGG();\n    },\n    handlePay() {\n      wx.startSoterAuthentication({\n        requestAuthModes: [\"facial\", \"fingerPrint\"],\n        challenge: wepy.getStorageSync(\"token\"),\n        authContent: \"验证身份进行支付\",\n        success: async res => {\n          const { resultJSON, resultJSONSignature } = res;\n          //  验证指纹\n          wepy.showLoading({\n            title: \"正在验证\"\n          });\n          const { code } = await wepy.login();\n          verifyFingerPrint(resultJSON, resultJSONSignature, code).then(\n            verifyResponse => {\n              const {\n                data: { data, success }\n              } = verifyResponse;\n              wepy.hideLoading();\n              if (success && data.is_ok) {\n                //  密码赋值，调支付接口\n                this.password = data.password;\n                this.enterPay();\n              } else {\n                if (++this.failPayTimes >= 5) {\n                  wepy.showToast({\n                    title: \"失败次数过多，请使用密码支付\",\n                    icon: \"none\",\n                    duration: 1500\n                  });\n                } else {\n                  wepy.showToast({\n                    title: \"验证失败，请重试！\",\n                    icon: \"none\",\n                    duration: 1500\n                  });\n                  ++this.failPayTimes;\n                }\n              }\n              this.$apply();\n            }\n          );\n        },\n        fail: res => {\n          const { errCode } = res;\n          switch (errCode) {\n            //  重试次数过多冻结\n            case 90010:\n              wepy.showToast({\n                title: \"失败次数过多，请使用密码支付\",\n                icon: \"none\",\n                duration: 1500\n              });\n              this.failPayTimes = 999;\n              this.soterPay = false;\n              break;\n            //  识别失败\n            case 90009:\n              if (++this.failPayTimes >= 5) {\n                wepy.showToast({\n                  title: \"失败次数过多，请使用密码支付\",\n                  icon: \"none\",\n                  duration: 1500\n                });\n                this.soterPay = false;\n              } else {\n                wepy.showToast({\n                  title: \"识别失败，请重试\",\n                  icon: \"none\",\n                  duration: 1500\n                });\n              }\n              break;\n            //  用户取消授权\n            case 90008:\n              this.handleGG();\n              break;\n            //  锁屏\n            case 90007:\n              wepy.showToast({\n                title: \"验证已取消，请重新支付\",\n                icon: \"none\",\n                duration: 1500\n              });\n              break;\n            //  内部错误\n            default:\n              wepy.showToast({\n                title: \"未知错误，请使用密码支付\",\n                icon: \"none\",\n                duration: 1500\n              });\n              this.soterPay = false;\n          }\n          this.$apply();\n        }\n      });\n    },\n    changePayType() {\n      this.soterPay = !this.soterPay;\n    }\n  };\n  handleGG() {\n    this.open = false;\n    this.soterPay = this.isSoterAble && this.failPayTimes < 5;\n    this.charge = \"\";\n    this.$invoke(\"Pw\", \"clear\");\n    this.$apply();\n  }\n  chargeCard() {\n    // 充值校园卡\n    transferCard(this.charge * 100, this.password).then(res => {\n      wepy.hideLoading();\n      if (res.data) {\n        // 充值成功\n        const resData = JSON.parse(res.data.data);\n        if (resData.transfer.retcode === \"0\") {\n          wepy.showToast({\n            title: \"充值成功\",\n            icon: \"success\",\n            duration: 2000\n          });\n          this.handleGG();\n        } else {\n          // 余额不足之类的\n          wepy\n            .showModal({\n              content: resData.transfer.errmsg,\n              confirmText: \"知道了\",\n              showCancel: false,\n              confirmColor: \"#353535\"\n            })\n            .then(res => {\n              this.handleGG();\n            });\n        }\n      }\n      this.$apply();\n    });\n  }\n  chargeNet() {\n    // 充值网费\n    transferNet(this.charge * 100, this.password).then(res => {\n      wepy.hideLoading();\n      if (res.data) {\n        // 密码正确的情况\n        const resData = JSON.parse(res.data.data);\n        if (resData.pay_net_gdc.retcode === \"0\") {\n          // 充值成功\n          wepy.showToast({\n            title: \"充值成功\",\n            icon: \"success\",\n            duration: 2000\n          });\n          this.handleGG();\n        } else {\n          // 余额不足之类的\n          wepy\n            .showModal({\n              content: resData.pay_net_gdc.errmsg,\n              confirmText: \"知道了\",\n              showCancel: false,\n              confirmColor: \"#353535\"\n            })\n            .then(res => {\n              this.handleGG();\n            });\n        }\n      }\n    });\n  }\n  async chargeEle() {\n    //充值电费\n    transferEle(this.electricURL, this.charge * 100, this.password).then(\n      res => {\n        wepy.hideLoading();\n        if (res.data) {\n          // 密码正确的情况\n          const resData = JSON.parse(res.data.data);\n          if (resData.pay_elec_gdc.retcode === \"0\") {\n            // 充值成功\n            wepy.showToast({\n              title: \"充值成功\",\n              icon: \"success\",\n              duration: 2000\n            });\n            this.handleGG();\n          } else {\n            // 余额不足之类\n            wepy\n              .showModal({\n                content: resData.pay_elec_gdc.errmsg,\n                confirmText: \"知道了\",\n                showCancel: false,\n                confirmColor: \"#353535\"\n              })\n              .then(res => {\n                this.handleGG();\n              });\n          }\n        }\n      }\n    );\n  }\n  enterPay() {\n    wepy.showLoading({\n      title: \"正在发起支付\"\n    });\n    switch (this.type) {\n      case \"card\":\n        this.chargeCard();\n        break;\n      case \"net\":\n        this.chargeNet();\n        break;\n      case \"electric\":\n        this.chargeEle();\n        break;\n    }\n  }\n  onLoad() {\n    if (wx.canIUse(\"checkIsSupportSoterAuthentication\")) {\n      wx.checkIsSupportSoterAuthentication({\n        success: res => {\n          //  检查设备是否支持人脸识别/指纹，优先人脸\n          const soterType = res.supportMode.includes(\"facial\")\n            ? \"facial\"\n            : res.supportMode.includes(\"fingerPrint\")\n            ? \"fingerPrint\"\n            : \"\";\n          if (soterType) {\n            //  检查设备是否录入信息\n            wx.checkIsSoterEnrolledInDevice({\n              checkAuthMode: soterType,\n              success: res => {\n                if (res.isEnrolled) {\n                  this.isSoterAble = this.soterPay = true;\n                } else {\n                  this.isSoterAble = this.soterPay = false;\n                }\n              }\n            });\n          } else {\n            this.isSoterAble = this.soterPay = false;\n          }\n        },\n        fail: () => {\n          this.isSoterAble = this.soterPay = false;\n        }\n      });\n    } else {\n      this.isSoterAble = this.soterPay = false;\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.mask-container\n  width 100vw\n  height 100vh\n  position fixed\n  bottom 0\n  background-color rgba(0, 0, 0, 0.5)\n  z-index 100\n  .pay-container\n    position absolute\n    bottom 0\n    height 770rpx\n    background-color rgb(255, 255, 255)\n    display flex\n    flex-direction column\n    align-items center\n    width 100%\n    .confirm-button\n      width 100vw\n      margin-top 60rpx\n      .pay-button\n        margin 16rpx auto\n        background-color #47cff5\n        color #fff\n        width 38%\n        border-radius 48rpx\n    .close\n      width 35rpx\n      position absolute\n      top 25rpx\n      left 22rpx\n    .change-pay-type\n      position absolute \n      top 41rpx\n      right 22rpx\n      transform translateY(-50%)\n      color #47cff5\n    .charge-text\n      font-size 80rpx\n      color #353535\n      font-weight bold\n      margin 35rpx 0 60rpx\n    .confirm\n      width 100%\n      height 82rpx\n      line-height 82rpx\n      // text-align center\n      justify-content center\n      display flex\n      border-bottom 2rpx solid #E3E3E3\n    .input-password\n      font-size 27rpx\n      border-bottom 2rpx solid black\n      width 438rpx\n      text-align center\n      margin-top 84rpx\n    .small-list\n      display flex\n      justify-content space-between\n      width 90%\n      border-bottom 2rpx solid #E3E3E3\n      height 60rpx\n      line-height 60rpx\n      .text1\n        font-size 30rpx\n        color #888888\n      .text2\n        font-size 30rpx\n        color #353535\n</style>\n\n"
  },
  {
    "path": "src/campus-card-page/components/pwdfield.wpy",
    "content": "<template>\n  <view class=\"band-pwdfield\" style=\"border-color:{{color}};\">\n    <input focus=\"{{focus}}\" type=\"number\" class=\"band-pwdfield-input\" maxlength=\"6\" password=\"{{!display}}\" @input=\"handleInput\" selection-start=\"-100\" selection-end=\"-100\" />\n    <repeat for=\"{{6}}\" item=\"i\">\n      <view class=\"band-pwdfield-item\">\n        {{display ? currentValue[i] : secret[i]}}\n      </view>\n    </repeat>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class PwdField extends wepy.component {\n  props = {\n    display: {\n      type: Boolean,\n      default: false\n    },\n    color: String\n  };\n  data = {\n    currentValue: \"\",\n    secret: \"\",\n    focus: true\n  };\n  watch = {\n    currentValue: val => {\n      // 6位触发支付\n      if (val.length === 0) return (this.secret = \"\");\n      const l = val => (val === 1 ? \"●\" : \"●\" + l(val - 1));\n      this.secret = l(val.length);\n      if (val.length === 6) {\n        this.$emit(\"value\", val);\n      }\n    }\n  };\n  onLoad() {}\n  methods = {\n    handleInput(e) {\n      if (e.detail.value.length <= 6) {\n        this.currentValue = e.detail.value;\n      }\n    }\n  };\n  clear() {\n    this.currentValue = \"\";\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.band-pwdfield\n  position relative\n  display flex\n  flex-direction row\n  align-items center\n  margin-top 76rpx\n  .band-pwdfield-input\n    z-index: 0\n    position: absolute\n    top 0\n    left -100%\n    width 200%\n    height 100%\n    opacity 0\n    font-size 1rpx\n    color transparent\n    caret-color transparent\n    text-align left\n .band-pwdfield-item\n    flex 1\n    display flex\n    align-items center\n    justify-content center\n    border-radius 8rpx\n    margin-right 8rpx\n    border 1rpx solid #999ca0\n    color inherit\n    width 90rpx\n    height 90rpx\n  .band-pwdfield-item:last-child\n    margin-right 0\n</style>\n\n"
  },
  {
    "path": "src/campus-card-page/components/wxcharts-min.js",
    "content": "\"use strict\";function assign(t,e){if(null==t)throw new TypeError(\"Cannot convert undefined or null to object\");for(var i=Object(t),a=1;a<arguments.length;a++){var n=arguments[a];if(null!=n)for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(i[o]=n[o])}return i}function findRange(t,e,i){if(isNaN(t))throw new Error(\"[wxCharts] unvalid series data!\");i=i||10,e=e||\"upper\";for(var a=1;i<1;)i*=10,a*=10;for(t=\"upper\"===e?Math.ceil(t*a):Math.floor(t*a);t%i!=0;)\"upper\"===e?t++:t--;return t/a}function calValidDistance(t,e,i,a){var n=a.width-i.padding-e.xAxisPoints[0],o=e.eachSpacing*a.categories.length,r=t;return t>=0?r=0:Math.abs(t)>=o-n&&(r=n-o),r}function isInAngleRange(t,e,i){function a(t){for(;t<0;)t+=2*Math.PI;for(;t>2*Math.PI;)t-=2*Math.PI;return t}return t=a(t),e=a(e),i=a(i),e>i&&(i+=2*Math.PI,t<e&&(t+=2*Math.PI)),t>=e&&t<=i}function calRotateTranslate(t,e,i){var a=t,n=i-e,o=a+(i-n-a)/Math.sqrt(2);return o*=-1,{transX:o,transY:(i-n)*(Math.sqrt(2)-1)-(i-n-a)/Math.sqrt(2)}}function createCurveControlPoints(t,e){function i(t,e){return!(!t[e-1]||!t[e+1])&&(t[e].y>=Math.max(t[e-1].y,t[e+1].y)||t[e].y<=Math.min(t[e-1].y,t[e+1].y))}var a=null,n=null,o=null,r=null;if(e<1?(a=t[0].x+.2*(t[1].x-t[0].x),n=t[0].y+.2*(t[1].y-t[0].y)):(a=t[e].x+.2*(t[e+1].x-t[e-1].x),n=t[e].y+.2*(t[e+1].y-t[e-1].y)),e>t.length-3){var s=t.length-1;o=t[s].x-.2*(t[s].x-t[s-1].x),r=t[s].y-.2*(t[s].y-t[s-1].y)}else o=t[e+1].x-.2*(t[e+2].x-t[e].x),r=t[e+1].y-.2*(t[e+2].y-t[e].y);return i(t,e+1)&&(r=t[e+1].y),i(t,e)&&(n=t[e].y),{ctrA:{x:a,y:n},ctrB:{x:o,y:r}}}function convertCoordinateOrigin(t,e,i){return{x:i.x+t,y:i.y-e}}function avoidCollision(t,e){if(e)for(;util.isCollision(t,e);)t.start.x>0?t.start.y--:t.start.x<0?t.start.y++:t.start.y>0?t.start.y++:t.start.y--;return t}function fillSeriesColor(t,e){var i=0;return t.map(function(t){return t.color||(t.color=e.colors[i],i=(i+1)%e.colors.length),t})}function getDataRange(t,e){var i=0,a=e-t;return i=a>=1e4?1e3:a>=1e3?100:a>=100?10:a>=10?5:a>=1?1:a>=.1?.1:.01,{minRange:findRange(t,\"lower\",i),maxRange:findRange(e,\"upper\",i)}}function measureText(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;t=String(t);var t=t.split(\"\"),i=0;return t.forEach(function(t){/[a-zA-Z]/.test(t)?i+=7:/[0-9]/.test(t)?i+=5.5:/\\./.test(t)?i+=2.7:/-/.test(t)?i+=3.25:/[\\u4e00-\\u9fa5]/.test(t)?i+=10:/\\(|\\)/.test(t)?i+=3.73:/\\s/.test(t)?i+=2.5:/%/.test(t)?i+=8:i+=10}),i*e/10}function dataCombine(t){return t.reduce(function(t,e){return(t.data?t.data:t).concat(e.data)},[])}function getSeriesDataItem(t,e){var i=[];return t.forEach(function(t){if(null!==t.data[e]&&void 0!==t.data[e]){var a={};a.color=t.color,a.name=t.name,a.data=t.format?t.format(t.data[e]):t.data[e],i.push(a)}}),i}function getMaxTextListLength(t){var e=t.map(function(t){return measureText(t)});return Math.max.apply(null,e)}function getRadarCoordinateSeries(t){for(var e=2*Math.PI/t,i=[],a=0;a<t;a++)i.push(e*a);return i.map(function(t){return-1*t+Math.PI/2})}function getToolTipData(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{},o=t.map(function(t){return{text:n.format?n.format(t,a[i]):t.name+\": \"+t.data,color:t.color}}),r=[],s={x:0,y:0};return e.forEach(function(t){void 0!==t[i]&&null!==t[i]&&r.push(t[i])}),r.forEach(function(t){s.x=Math.round(t.x),s.y+=t.y}),s.y/=r.length,{textList:o,offset:s}}function findCurrentIndex(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,o=-1;return isInExactChartArea(t,i,a)&&e.forEach(function(e,i){t.x+n>e&&(o=i)}),o}function isInExactChartArea(t,e,i){return t.x<e.width-i.padding&&t.x>i.padding+i.yAxisWidth+i.yAxisTitleWidth&&t.y>i.padding&&t.y<e.height-i.legendHeight-i.xAxisHeight-i.padding}function findRadarChartCurrentIndex(t,e,i){var a=2*Math.PI/i,n=-1;if(isInExactPieChartArea(t,e.center,e.radius)){var o=function(t){return t<0&&(t+=2*Math.PI),t>2*Math.PI&&(t-=2*Math.PI),t},r=Math.atan2(e.center.y-t.y,t.x-e.center.x);r*=-1,r<0&&(r+=2*Math.PI);e.angleList.map(function(t){return t=o(-1*t)}).forEach(function(t,e){var i=o(t-a/2),s=o(t+a/2);s<i&&(s+=2*Math.PI),(r>=i&&r<=s||r+2*Math.PI>=i&&r+2*Math.PI<=s)&&(n=e)})}return n}function findPieChartCurrentIndex(t,e){var i=-1;if(isInExactPieChartArea(t,e.center,e.radius)){var a=Math.atan2(e.center.y-t.y,t.x-e.center.x);a=-a;for(var n=0,o=e.series.length;n<o;n++){var r=e.series[n];if(isInAngleRange(a,r._start_,r._start_+2*r._proportion_*Math.PI)){i=n;break}}}return i}function isInExactPieChartArea(t,e,i){return Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2)<=Math.pow(i,2)}function splitPoints(t){var e=[],i=[];return t.forEach(function(t,a){null!==t?i.push(t):(i.length&&e.push(i),i=[])}),i.length&&e.push(i),e}function calLegendData(t,e,i){if(!1===e.legend)return{legendList:[],legendHeight:0};var a=[],n=0,o=[];return t.forEach(function(t){var i=30+measureText(t.name||\"undefined\");n+i>e.width?(a.push(o),n=i,o=[t]):(n+=i,o.push(t))}),o.length&&a.push(o),{legendList:a,legendHeight:a.length*(i.fontSize+8)+5}}function calCategoriesData(t,e,i){var a={angle:0,xAxisHeight:i.xAxisHeight},n=getXAxisPoints(t,e,i),o=n.eachSpacing,r=t.map(function(t){return measureText(t)}),s=Math.max.apply(this,r);return s+2*i.xAxisTextPadding>o&&(a.angle=45*Math.PI/180,a.xAxisHeight=2*i.xAxisTextPadding+s*Math.sin(a.angle)),a}function getRadarDataPoints(t,e,i,a,n){var o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1,r=n.extra.radar||{};r.max=r.max||0;var s=Math.max(r.max,Math.max.apply(null,dataCombine(a))),l=[];return a.forEach(function(a){var n={};n.color=a.color,n.data=[],a.data.forEach(function(a,r){var l={};l.angle=t[r],l.proportion=a/s,l.position=convertCoordinateOrigin(i*l.proportion*o*Math.cos(l.angle),i*l.proportion*o*Math.sin(l.angle),e),n.data.push(l)}),l.push(n)}),l}function getPieDataPoints(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,i=0,a=0;return t.forEach(function(t){t.data=null===t.data?0:t.data,i+=t.data}),t.forEach(function(t){t.data=null===t.data?0:t.data,t._proportion_=t.data/i*e}),t.forEach(function(t){t._start_=a,a+=2*t._proportion_*Math.PI}),t}function getPieTextMaxLength(t){t=getPieDataPoints(t);var e=0;return t.forEach(function(t){var i=t.format?t.format(+t._proportion_.toFixed(2)):util.toFixed(100*t._proportion_)+\"%\";e=Math.max(e,measureText(i))}),e}function fixColumeData(t,e,i,a,n,o){return t.map(function(t){return null===t?null:(t.width=(e-2*n.columePadding)/i,o.extra.column&&o.extra.column.width&&+o.extra.column.width>0?t.width=Math.min(t.width,+o.extra.column.width):t.width=Math.min(t.width,25),t.x+=(a+.5-i/2)*t.width,t)})}function getXAxisPoints(t,e,i){var a=i.yAxisWidth+i.yAxisTitleWidth,n=e.width-2*i.padding-a,o=e.enableScroll?Math.min(5,t.length):t.length,r=n/o,s=[],l=i.padding+a,h=e.width-i.padding;return t.forEach(function(t,e){s.push(l+e*r)}),!0===e.enableScroll?s.push(l+t.length*r):s.push(h),{xAxisPoints:s,startX:l,endX:h,eachSpacing:r}}function getDataPoints(t,e,i,a,n,o,r){var s=arguments.length>7&&void 0!==arguments[7]?arguments[7]:1,l=[],h=o.height-2*r.padding-r.xAxisHeight-r.legendHeight;return t.forEach(function(t,c){if(null===t)l.push(null);else{var d={};d.x=a[c]+Math.round(n/2);var x=h*(t-e)/(i-e);x*=s,d.y=o.height-r.xAxisHeight-r.legendHeight-Math.round(x)-r.padding,l.push(d)}}),l}function getYAxisTextList(t,e,i){var a=dataCombine(t);a=a.filter(function(t){return null!==t});var n=Math.min.apply(this,a),o=Math.max.apply(this,a);if(\"number\"==typeof e.yAxis.min&&(n=Math.min(e.yAxis.min,n)),\"number\"==typeof e.yAxis.max&&(o=Math.max(e.yAxis.max,o)),n===o){var r=o||1;n-=r,o+=r}for(var s=getDataRange(n,o),l=s.minRange,h=s.maxRange,c=[],d=(h-l)/i.yAxisSplit,x=0;x<=i.yAxisSplit;x++)c.push(l+d*x);return c.reverse()}function calYAxisData(t,e,i){var a=getYAxisTextList(t,e,i),n=i.yAxisWidth,o=a.map(function(t){return t=util.toFixed(t,2),t=e.yAxis.format?e.yAxis.format(Number(t)):t,n=Math.max(n,measureText(t)+5),t});return!0===e.yAxis.disabled&&(n=0),{rangesFormat:o,ranges:a,yAxisWidth:n}}function drawPointShape(t,e,i,a){a.beginPath(),a.setStrokeStyle(\"#ffffff\"),a.setLineWidth(1),a.setFillStyle(e),\"diamond\"===i?t.forEach(function(t,e){null!==t&&(a.moveTo(t.x,t.y-4.5),a.lineTo(t.x-4.5,t.y),a.lineTo(t.x,t.y+4.5),a.lineTo(t.x+4.5,t.y),a.lineTo(t.x,t.y-4.5))}):\"circle\"===i?t.forEach(function(t,e){null!==t&&(a.moveTo(t.x+3.5,t.y),a.setLineWidth(1),a.setStrokeStyle(\"rgb(102,209,255)\"),a.arc(t.x,t.y,3,0,2*Math.PI,!1),a.stroke())}):\"rect\"===i?t.forEach(function(t,e){null!==t&&(a.moveTo(t.x-3.5,t.y-3.5),a.rect(t.x-3.5,t.y-3.5,7,7))}):\"triangle\"===i&&t.forEach(function(t,e){null!==t&&(a.moveTo(t.x,t.y-4.5),a.lineTo(t.x-4.5,t.y+4.5),a.lineTo(t.x+4.5,t.y+4.5),a.lineTo(t.x,t.y-4.5))}),a.closePath(),a.setFillStyle(\"white\"),a.fill(),a.setFillStyle(\"rgba(223,249,255,1)\"),a.stroke()}function drawRingTitle(t,e,i){var a=t.title.fontSize||e.titleFontSize,n=t.subtitle.fontSize||e.subtitleFontSize,o=t.title.name||\"\",r=t.subtitle.name||\"\",s=t.title.color||e.titleColor,l=t.subtitle.color||e.subtitleColor,h=o?a:0,c=r?n:0;if(r){var d=measureText(r,n),x=(t.width-d)/2+(t.subtitle.offsetX||0),f=(t.height-e.legendHeight+n)/2;o&&(f-=(h+5)/2),i.beginPath(),i.setFontSize(n),i.setFillStyle(l),i.fillText(r,x,f),i.stroke(),i.closePath()}if(o){var g=measureText(o,a),u=(t.width-g)/2+(t.title.offsetX||0),p=(t.height-e.legendHeight+a)/2;r&&(p+=(c+5)/2),i.beginPath(),i.setFontSize(a),i.setFillStyle(s),i.fillText(o,u,p),i.stroke(),i.closePath()}}function drawPointText(t,e,i,a){var n=e.data;a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(\"#666666\"),t.forEach(function(t,i){if(null!==t){var o=e.format?e.format(n[i]):n[i];a.fillText(o,t.x-measureText(o)/2,t.y-2)}}),a.closePath(),a.stroke()}function drawRadarLabel(t,e,i,a,n,o){var r=a.extra.radar||{};e+=n.radarLabelTextMargin,o.beginPath(),o.setFontSize(n.fontSize),o.setFillStyle(r.labelColor||\"#666666\"),t.forEach(function(t,r){var s={x:e*Math.cos(t),y:e*Math.sin(t)},l=convertCoordinateOrigin(s.x,s.y,i),h=l.x,c=l.y;util.approximatelyEqual(s.x,0)?h-=measureText(a.categories[r]||\"\")/2:s.x<0&&(h-=measureText(a.categories[r]||\"\")),o.fillText(a.categories[r]||\"\",h,c+n.fontSize/2)}),o.stroke(),o.closePath()}function drawPieText(t,e,i,a,n,o){var r=n+i.pieChartLinePadding,s=(i.pieChartTextPadding,[]),l=null;t.map(function(t){return{arc:2*Math.PI-(t._start_+2*Math.PI*t._proportion_/2),text:t.format?t.format(+t._proportion_.toFixed(2)):util.toFixed(100*t._proportion_)+\"%\",color:t.color}}).forEach(function(t){var e=Math.cos(t.arc)*r,a=Math.sin(t.arc)*r,o=Math.cos(t.arc)*n,h=Math.sin(t.arc)*n,c=e>=0?e+i.pieChartTextPadding:e-i.pieChartTextPadding,d=a,x=measureText(t.text),f=d;l&&util.isSameXCoordinateArea(l.start,{x:c})&&(f=c>0?Math.min(d,l.start.y):e<0?Math.max(d,l.start.y):d>0?Math.max(d,l.start.y):Math.min(d,l.start.y)),c<0&&(c-=x);var g={lineStart:{x:o,y:h},lineEnd:{x:e,y:a},start:{x:c,y:f},width:x,height:i.fontSize,text:t.text,color:t.color};l=avoidCollision(g,l),s.push(l)}),s.forEach(function(t){var e=convertCoordinateOrigin(t.lineStart.x,t.lineStart.y,o),n=convertCoordinateOrigin(t.lineEnd.x,t.lineEnd.y,o),r=convertCoordinateOrigin(t.start.x,t.start.y,o);a.setLineWidth(1),a.setFontSize(i.fontSize),a.beginPath(),a.setStrokeStyle(t.color),a.setFillStyle(t.color),a.moveTo(e.x,e.y);var s=t.start.x<0?r.x+t.width:r.x,l=t.start.x<0?r.x-5:r.x+5;a.quadraticCurveTo(n.x,n.y,s,r.y),a.moveTo(e.x,e.y),a.stroke(),a.closePath(),a.beginPath(),a.moveTo(r.x+t.width,r.y),a.arc(s,r.y,2,0,2*Math.PI),a.closePath(),a.fill(),a.beginPath(),a.setFillStyle(\"#666666\"),a.fillText(t.text,l,r.y+3),a.closePath(),a.stroke(),a.closePath()})}function drawToolTipSplitLine(t,e,i,a){var n=i.padding,o=e.height-i.padding-i.xAxisHeight-i.legendHeight;a.beginPath(),a.setStrokeStyle(\"#cccccc\"),a.setLineWidth(1),a.moveTo(t,n),a.lineTo(t,o),a.stroke(),a.closePath()}function drawToolTip(t,e,i,a,n){var o=!1;e=assign({x:0,y:0},e),e.y-=8;var r=t.map(function(t){return measureText(t.text)}),s=9+4*a.toolTipPadding+Math.max.apply(null,r),l=2*a.toolTipPadding+t.length*a.toolTipLineHeight;e.x-Math.abs(i._scrollDistance_)+8+s>i.width&&(o=!0),n.beginPath(),n.setFillStyle(i.tooltip.option.background||a.toolTipBackground),n.setGlobalAlpha(a.toolTipOpacity),o?(n.moveTo(e.x,e.y+10),n.lineTo(e.x-8,e.y+10-5),n.lineTo(e.x-8,e.y+10+5),n.moveTo(e.x,e.y+10),n.fillRect(e.x-s-8,e.y,s,l)):(n.moveTo(e.x,e.y+10),n.lineTo(e.x+8,e.y+10-5),n.lineTo(e.x+8,e.y+10+5),n.moveTo(e.x,e.y+10),n.fillRect(e.x+8,e.y,s,l)),n.closePath(),n.fill(),n.setGlobalAlpha(1),t.forEach(function(t,i){n.beginPath(),n.setFillStyle(t.color);var r=e.x+8+2*a.toolTipPadding,l=e.y+(a.toolTipLineHeight-a.fontSize)/2+a.toolTipLineHeight*i+a.toolTipPadding;o&&(r=e.x-s-8+2*a.toolTipPadding),n.fillRect(r,l,4,a.fontSize),n.closePath()}),n.beginPath(),n.setFontSize(a.fontSize),n.setFillStyle(\"#ffffff\"),t.forEach(function(t,i){var r=e.x+8+2*a.toolTipPadding+4+5;o&&(r=e.x-s-8+2*a.toolTipPadding+4+5);var l=e.y+(a.toolTipLineHeight-a.fontSize)/2+a.toolTipLineHeight*i+a.toolTipPadding;n.fillText(t.text,r,l+a.fontSize)}),n.stroke(),n.closePath()}function drawYAxisTitle(t,e,i,a){var n=i.xAxisHeight+(e.height-i.xAxisHeight-measureText(t))/2;a.save(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.yAxis.titleFontColor||\"#333333\"),a.translate(0,e.height),a.rotate(-90*Math.PI/180),a.fillText(t,n,i.padding+.5*i.fontSize),a.stroke(),a.closePath(),a.restore()}function drawColumnDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=calYAxisData(t,e,i),r=o.ranges,s=getXAxisPoints(e.categories,e,i),l=s.xAxisPoints,h=s.eachSpacing,c=r.pop(),d=r.shift();e.height,i.padding,i.xAxisHeight,i.legendHeight;return a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&!0===e.enableScroll&&a.translate(e._scrollDistance_,0),t.forEach(function(o,r){var s=o.data,x=getDataPoints(s,c,d,l,h,e,i,n);x=fixColumeData(x,h,t.length,r,i,e),a.beginPath(),a.setFillStyle(o.color),x.forEach(function(t,n){if(null!==t){var o=t.x-t.width/2+1,r=e.height-t.y-i.padding-i.xAxisHeight-i.legendHeight;a.moveTo(o,t.y),a.rect(o,t.y,t.width-2,r)}}),a.closePath(),a.fill()}),t.forEach(function(o,r){var s=o.data,x=getDataPoints(s,c,d,l,h,e,i,n);x=fixColumeData(x,h,t.length,r,i,e),!1!==e.dataLabel&&1===n&&drawPointText(x,o,i,a)}),a.restore(),{xAxisPoints:l,eachSpacing:h}}function drawAreaDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=calYAxisData(t,e,i),r=o.ranges,s=getXAxisPoints(e.categories,e,i),l=s.xAxisPoints,h=s.eachSpacing,c=r.pop(),d=r.shift(),x=e.height-i.padding-i.xAxisHeight-i.legendHeight,f=[];return a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&!0===e.enableScroll&&a.translate(e._scrollDistance_,0),e.tooltip&&e.tooltip.textList&&e.tooltip.textList.length&&1===n&&drawToolTipSplitLine(e.tooltip.offset.x,e,i,a),t.forEach(function(t,o){var r=t.data,s=getDataPoints(r,c,d,l,h,e,i,n);(f.push(s),splitPoints(s).forEach(function(t){if(a.beginPath(),a.setStrokeStyle(\"rgb(102,209,255)\"),a.setFillStyle(\"rgba(223,249,255,1)\"),a.setLineWidth(2),t.length>1){var i=t[0],n=t[t.length-1];a.moveTo(i.x,i.y),\"curve\"===e.extra.lineStyle?t.forEach(function(e,i){if(i>0){var n=createCurveControlPoints(t,i-1);a.bezierCurveTo(n.ctrA.x,n.ctrA.y,n.ctrB.x,n.ctrB.y,e.x,e.y)}}):t.forEach(function(t,e){e>0&&a.lineTo(t.x,t.y)}),a.stroke(),a.lineTo(n.x,x),a.lineTo(i.x,x),a.lineTo(i.x,i.y)}else{var o=t[0];a.moveTo(o.x-h/2,o.y),a.lineTo(o.x+h/2,o.y),a.lineTo(o.x+h/2,x),a.lineTo(o.x-h/2,x),a.moveTo(o.x-h/2,o.y)}a.closePath(),a.fill(),a.setGlobalAlpha(1)}),!1!==e.dataPointShape)&&(i.dataPointShape[o%i.dataPointShape.length],drawPointShape(s,t.color,\"circle\",a))}),!1!==e.dataLabel&&1===n&&t.forEach(function(t,o){drawPointText(getDataPoints(t.data,c,d,l,h,e,i,n),t,i,a)}),a.restore(),{xAxisPoints:l,calPoints:f,eachSpacing:h}}function drawLineDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=calYAxisData(t,e,i),r=o.ranges,s=getXAxisPoints(e.categories,e,i),l=s.xAxisPoints,h=s.eachSpacing,c=r.pop(),d=r.shift(),x=[];return a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&!0===e.enableScroll&&a.translate(e._scrollDistance_,0),e.tooltip&&e.tooltip.textList&&e.tooltip.textList.length&&1===n&&drawToolTipSplitLine(e.tooltip.offset.x,e,i,a),t.forEach(function(t,o){var r=t.data,s=getDataPoints(r,c,d,l,h,e,i,n);if(x.push(s),splitPoints(s).forEach(function(i,n){a.beginPath(),a.setStrokeStyle(t.color),a.setLineWidth(2),1===i.length?(a.moveTo(i[0].x,i[0].y),a.arc(i[0].x,i[0].y,1,0,2*Math.PI)):(a.moveTo(i[0].x,i[0].y),\"curve\"===e.extra.lineStyle?i.forEach(function(t,e){if(e>0){var n=createCurveControlPoints(i,e-1);a.bezierCurveTo(n.ctrA.x,n.ctrA.y,n.ctrB.x,n.ctrB.y,t.x,t.y)}}):i.forEach(function(t,e){e>0&&a.lineTo(t.x,t.y)}),a.moveTo(i[0].x,i[0].y)),a.closePath(),a.stroke()}),!1!==e.dataPointShape){var f=i.dataPointShape[o%i.dataPointShape.length];drawPointShape(s,t.color,f,a)}}),!1!==e.dataLabel&&1===n&&t.forEach(function(t,o){drawPointText(getDataPoints(t.data,c,d,l,h,e,i,n),t,i,a)}),a.restore(),{xAxisPoints:l,calPoints:x,eachSpacing:h}}function drawToolTipBridge(t,e,i,a){i.save(),t._scrollDistance_&&0!==t._scrollDistance_&&!0===t.enableScroll&&i.translate(t._scrollDistance_,0),t.tooltip&&t.tooltip.textList&&t.tooltip.textList.length&&1===a&&drawToolTip(t.tooltip.textList,t.tooltip.offset,t,e,i),i.restore()}function drawXAxis(t,e,i,a){var n=getXAxisPoints(t,e,i),o=n.xAxisPoints,r=n.eachSpacing,s=e.height-i.padding-i.xAxisHeight-i.legendHeight;i.xAxisLineHeight;a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&a.translate(e._scrollDistance_,0),a.beginPath(),a.setStrokeStyle(e.xAxis.gridColor||\"#cccccc\"),!0!==e.xAxis.disableGrid&&(e.xAxis.type,o.forEach(function(t,e){})),a.closePath(),a.stroke();var l=e.width-2*i.padding-i.yAxisWidth-i.yAxisTitleWidth,h=Math.min(t.length,Math.ceil(l/i.fontSize/1.5)),c=Math.ceil(t.length/h);t=t.map(function(t,e){return e%c!=0?\"\":t}),0===i._xAxisTextAngle_?(a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.xAxis.fontColor||\"#666666\"),t.forEach(function(t,e){var n=r/2-measureText(t)/2;a.fillText(t,o[e]+n,s+i.fontSize+5)}),a.closePath(),a.stroke()):t.forEach(function(t,n){a.save(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.xAxis.fontColor||\"#666666\");var l=measureText(t),h=r/2-l,c=calRotateTranslate(o[n]+r/2,s+i.fontSize/2+5,e.height),d=c.transX,x=c.transY;a.rotate(-1*i._xAxisTextAngle_),a.translate(d,x),a.fillText(t,o[n]+h,s+i.fontSize+5),a.closePath(),a.stroke(),a.restore()}),a.restore()}function drawYAxisGrid(t,e,i){for(var a=t.height-2*e.padding-e.xAxisHeight-e.legendHeight,n=Math.floor(a/e.yAxisSplit),o=e.yAxisWidth+e.yAxisTitleWidth,r=e.padding+o,s=t.width-e.padding,l=[],h=0;h<e.yAxisSplit;h++)l.push(e.padding+n*h);l.push(e.padding+n*e.yAxisSplit+2),i.beginPath(),i.setStrokeStyle(t.yAxis.gridColor||\"#cccccc\"),i.setLineWidth(1),l.forEach(function(t,e){i.moveTo(r,t),i.lineTo(s,t)}),i.closePath(),i.stroke()}function drawYAxis(t,e,i,a){if(!0!==e.yAxis.disabled){var n=calYAxisData(t,e,i),o=n.rangesFormat,r=i.yAxisWidth+i.yAxisTitleWidth,s=e.height-2*i.padding-i.xAxisHeight-i.legendHeight,l=Math.floor(s/i.yAxisSplit),h=i.padding+r,c=e.width-i.padding,d=(i.padding,e.height-i.padding-i.xAxisHeight-i.legendHeight);a.setFillStyle(e.background||\"#ffffff\"),e._scrollDistance_<0&&a.fillRect(0,0,h,d+i.xAxisHeight+5),a.fillRect(c,0,e.width,d+i.xAxisHeight+5);for(var x=[],f=0;f<=i.yAxisSplit;f++)x.push(i.padding+l*f);a.stroke(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.yAxis.fontColor||\"#666666\"),o.forEach(function(t,e){var n=x[e]?x[e]:d;a.fillText(t,i.padding+i.yAxisTitleWidth,n+i.fontSize/2)}),a.closePath(),a.stroke(),e.yAxis.title&&drawYAxisTitle(e.yAxis.title,e,i,a)}}function drawLegend(t,e,i,a){if(e.legend){var n=calLegendData(t,e,i),o=n.legendList;o.forEach(function(t,n){var o=0;t.forEach(function(t){t.name=t.name||\"undefined\",o+=15+measureText(t.name)+15});var r=(e.width-o)/2+5,s=e.height-i.padding-i.legendHeight+n*(i.fontSize+8)+5+8;a.setFontSize(i.fontSize),t.forEach(function(t){switch(e.type){case\"line\":a.beginPath(),a.setLineWidth(1),a.setStrokeStyle(t.color),a.moveTo(r-2,s+5),a.lineTo(r+17,s+5),a.stroke(),a.closePath(),a.beginPath(),a.setLineWidth(1),a.setStrokeStyle(\"#ffffff\"),a.setFillStyle(t.color),a.moveTo(r+7.5,s+5),a.arc(r+7.5,s+5,4,0,2*Math.PI),a.fill(),a.stroke(),a.closePath();break;case\"pie\":case\"ring\":a.beginPath(),a.setFillStyle(t.color),a.moveTo(r+7.5,s+5),a.arc(r+7.5,s+5,7,0,2*Math.PI),a.closePath(),a.fill();break;default:a.beginPath(),a.setFillStyle(t.color),a.moveTo(r,s),a.rect(r,s,15,10),a.closePath(),a.fill()}r+=20,a.beginPath(),a.setFillStyle(e.extra.legendTextColor||\"#333333\"),a.fillText(t.name,r,s+9),a.closePath(),a.stroke(),r+=measureText(t.name)+10})})}}function drawPieDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=e.extra.pie||{};t=getPieDataPoints(t,n);var r={x:e.width/2,y:(e.height-i.legendHeight)/2},s=Math.min(r.x-i.pieChartLinePadding-i.pieChartTextPadding-i._pieTextMaxLength_,r.y-i.pieChartLinePadding-i.pieChartTextPadding);if(e.dataLabel?s-=10:s-=2*i.padding,t=t.map(function(t){return t._start_+=(o.offsetAngle||0)*Math.PI/180,t}),t.forEach(function(t){a.beginPath(),a.setLineWidth(2),a.setStrokeStyle(\"#ffffff\"),a.setFillStyle(t.color),a.moveTo(r.x,r.y),a.arc(r.x,r.y,s,t._start_,t._start_+2*t._proportion_*Math.PI),a.closePath(),a.fill(),!0!==e.disablePieStroke&&a.stroke()}),\"ring\"===e.type){var l=.6*s;\"number\"==typeof e.extra.ringWidth&&e.extra.ringWidth>0&&(l=Math.max(0,s-e.extra.ringWidth)),a.beginPath(),a.setFillStyle(e.background||\"#ffffff\"),a.moveTo(r.x,r.y),a.arc(r.x,r.y,l,0,2*Math.PI),a.closePath(),a.fill()}if(!1!==e.dataLabel&&1===n){for(var h=!1,c=0,d=t.length;c<d;c++)if(t[c].data>0){h=!0;break}h&&drawPieText(t,e,i,a,s,r)}return 1===n&&\"ring\"===e.type&&drawRingTitle(e,i,a),{center:r,radius:s,series:t}}function drawRadarDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=e.extra.radar||{},r=getRadarCoordinateSeries(e.categories.length),s={x:e.width/2,y:(e.height-i.legendHeight)/2},l=Math.min(s.x-(getMaxTextListLength(e.categories)+i.radarLabelTextMargin),s.y-i.radarLabelTextMargin);l-=i.padding,a.beginPath(),a.setLineWidth(1),a.setStrokeStyle(o.gridColor||\"#cccccc\"),r.forEach(function(t){var e=convertCoordinateOrigin(l*Math.cos(t),l*Math.sin(t),s);a.moveTo(s.x,s.y),a.lineTo(e.x,e.y)}),a.stroke(),a.closePath();for(var h=1;h<=i.radarGridCount;h++)!function(t){var e={};a.beginPath(),a.setLineWidth(1),a.setStrokeStyle(o.gridColor||\"#cccccc\"),r.forEach(function(n,o){var r=convertCoordinateOrigin(l/i.radarGridCount*t*Math.cos(n),l/i.radarGridCount*t*Math.sin(n),s);0===o?(e=r,a.moveTo(r.x,r.y)):a.lineTo(r.x,r.y)}),a.lineTo(e.x,e.y),a.stroke(),a.closePath()}(h);return getRadarDataPoints(r,s,l,t,e,n).forEach(function(t,n){if(a.beginPath(),a.setFillStyle(t.color),a.setGlobalAlpha(.6),t.data.forEach(function(t,e){0===e?a.moveTo(t.position.x,t.position.y):a.lineTo(t.position.x,t.position.y)}),a.closePath(),a.fill(),a.setGlobalAlpha(1),!1!==e.dataPointShape){var o=i.dataPointShape[n%i.dataPointShape.length];drawPointShape(t.data.map(function(t){return t.position}),t.color,o,a)}}),drawRadarLabel(r,l,s,e,i,a),{center:s,radius:l,angleList:r}}function drawCanvas(t,e){e.draw()}function Animation(t){this.isStop=!1,t.duration=void 0===t.duration?1e3:t.duration,t.timing=t.timing||\"linear\";var e=function(){return\"undefined\"!=typeof requestAnimationFrame?requestAnimationFrame:\"undefined\"!=typeof setTimeout?function(t,e){setTimeout(function(){var e=+new Date;t(e)},e)}:function(t){t(null)}}(),i=null,a=function(n){if(null===n||!0===this.isStop)return t.onProcess&&t.onProcess(1),void(t.onAnimationFinish&&t.onAnimationFinish());if(null===i&&(i=n),n-i<t.duration){var o=(n-i)/t.duration;o=(0,Timing[t.timing])(o),t.onProcess&&t.onProcess(o),e(a,17)}else t.onProcess&&t.onProcess(1),t.onAnimationFinish&&t.onAnimationFinish()};a=a.bind(this),e(a,17)}function drawCharts(t,e,i,a){var n=this,o=e.series,r=e.categories;o=fillSeriesColor(o,i);var s=calLegendData(o,e,i),l=s.legendHeight;i.legendHeight=l;var h=calYAxisData(o,e,i),c=h.yAxisWidth;if(i.yAxisWidth=c,r&&r.length){var d=calCategoriesData(r,e,i),x=d.xAxisHeight,f=d.angle;i.xAxisHeight=x,i._xAxisTextAngle_=f}\"pie\"!==t&&\"ring\"!==t||(i._pieTextMaxLength_=!1===e.dataLabel?0:getPieTextMaxLength(o));var g=e.animation?1e3:0;switch(this.animationInstance&&this.animationInstance.stop(),t){case\"line\":this.animationInstance=new Animation({timing:\"easeIn\",duration:g,onProcess:function(t){drawYAxisGrid(e,i,a);var s=drawLineDataPoints(o,e,i,a,t),l=s.xAxisPoints,h=s.calPoints,c=s.eachSpacing;n.chartData.xAxisPoints=l,n.chartData.calPoints=h,n.chartData.eachSpacing=c,drawXAxis(r,e,i,a),drawLegend(e.series,e,i,a),drawYAxis(o,e,i,a),drawToolTipBridge(e,i,a,t),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger(\"renderComplete\")}});break;case\"column\":this.animationInstance=new Animation({timing:\"easeIn\",duration:g,onProcess:function(t){drawYAxisGrid(e,i,a);var s=drawColumnDataPoints(o,e,i,a,t),l=s.xAxisPoints,h=s.eachSpacing;n.chartData.xAxisPoints=l,n.chartData.eachSpacing=h,drawXAxis(r,e,i,a),drawLegend(e.series,e,i,a),drawYAxis(o,e,i,a),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger(\"renderComplete\")}});break;case\"area\":this.animationInstance=new Animation({timing:\"easeIn\",duration:g,onProcess:function(t){drawYAxisGrid(e,i,a);var s=drawAreaDataPoints(o,e,i,a,t),l=s.xAxisPoints,h=s.calPoints,c=s.eachSpacing;n.chartData.xAxisPoints=l,n.chartData.calPoints=h,n.chartData.eachSpacing=c,drawXAxis(r,e,i,a),drawLegend(e.series,e,i,a),drawYAxis(o,e,i,a),drawToolTipBridge(e,i,a,t),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger(\"renderComplete\")}});break;case\"ring\":case\"pie\":this.animationInstance=new Animation({timing:\"easeInOut\",duration:g,onProcess:function(t){n.chartData.pieData=drawPieDataPoints(o,e,i,a,t),drawLegend(e.series,e,i,a),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger(\"renderComplete\")}});break;case\"radar\":this.animationInstance=new Animation({timing:\"easeInOut\",duration:g,onProcess:function(t){n.chartData.radarData=drawRadarDataPoints(o,e,i,a,t),drawLegend(e.series,e,i,a),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger(\"renderComplete\")}})}}function Event(){this.events={}}var config={yAxisWidth:15,yAxisSplit:5,xAxisHeight:15,xAxisLineHeight:15,legendHeight:15,yAxisTitleWidth:15,padding:12,columePadding:3,fontSize:10,dataPointShape:[\"diamond\",\"circle\",\"triangle\",\"rect\"],colors:[\"rgba(109,209,255,1)\",\"#f7a35c\",\"#434348\",\"#90ed7d\",\"#f15c80\",\"#8085e9\"],pieChartLinePadding:25,pieChartTextPadding:15,xAxisTextPadding:3,titleColor:\"#333333\",titleFontSize:20,subtitleColor:\"#999999\",subtitleFontSize:15,toolTipPadding:3,toolTipBackground:\"#000000\",toolTipOpacity:.7,toolTipLineHeight:14,radarGridCount:3,radarLabelTextMargin:15},util={toFixed:function(t,e){return e=e||2,this.isFloat(t)&&(t=t.toFixed(e)),t},isFloat:function(t){return t%1!=0},approximatelyEqual:function(t,e){return Math.abs(t-e)<1e-10},isSameSign:function(t,e){return Math.abs(t)===t&&Math.abs(e)===e||Math.abs(t)!==t&&Math.abs(e)!==e},isSameXCoordinateArea:function(t,e){return this.isSameSign(t.x,e.x)},isCollision:function(t,e){return t.end={},t.end.x=t.start.x+t.width,t.end.y=t.start.y-t.height,e.end={},e.end.x=e.start.x+e.width,e.end.y=e.start.y-e.height,!(e.start.x>t.end.x||e.end.x<t.start.x||e.end.y>t.start.y||e.start.y<t.end.y)}},Timing={easeIn:function(t){return Math.pow(t,3)},easeOut:function(t){return Math.pow(t-1,3)+1},easeInOut:function(t){return(t/=.5)<1?.5*Math.pow(t,3):.5*(Math.pow(t-2,3)+2)},linear:function(t){return t}};Animation.prototype.stop=function(){this.isStop=!0},Event.prototype.addEventListener=function(t,e){this.events[t]=this.events[t]||[],this.events[t].push(e)},Event.prototype.trigger=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];var a=e[0],n=e.slice(1);this.events[a]&&this.events[a].forEach(function(t){try{t.apply(null,n)}catch(t){console.error(t)}})};var Charts=function(t){t.title=t.title||{},t.subtitle=t.subtitle||{},t.yAxis=t.yAxis||{},t.xAxis=t.xAxis||{},t.extra=t.extra||{},t.legend=!1!==t.legend,t.animation=!1!==t.animation;var e=assign({},config);e.yAxisTitleWidth=!0!==t.yAxis.disabled&&t.yAxis.title?e.yAxisTitleWidth:0,e.pieChartLinePadding=!1===t.dataLabel?0:e.pieChartLinePadding,e.pieChartTextPadding=!1===t.dataLabel?0:e.pieChartTextPadding,this.opts=t,this.config=e,this.context=wx.createCanvasContext(t.canvasId),this.chartData={},this.event=new Event,this.scrollOption={currentOffset:0,startTouchX:0,distance:0},drawCharts.call(this,t.type,t,e,this.context)};Charts.prototype.updateData=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.opts.series=t.series||this.opts.series,this.opts.categories=t.categories||this.opts.categories,this.opts.title=assign({},this.opts.title,t.title||{}),this.opts.subtitle=assign({},this.opts.subtitle,t.subtitle||{}),drawCharts.call(this,this.opts.type,this.opts,this.config,this.context)},Charts.prototype.stopAnimation=function(){this.animationInstance&&this.animationInstance.stop()},Charts.prototype.addEventListener=function(t,e){this.event.addEventListener(t,e)},Charts.prototype.getCurrentDataIndex=function(t){var e=t.touches&&t.touches.length?t.touches:t.changedTouches;if(e&&e.length){var i=e[0],a=i.x,n=i.y;return\"pie\"===this.opts.type||\"ring\"===this.opts.type?findPieChartCurrentIndex({x:a,y:n},this.chartData.pieData):\"radar\"===this.opts.type?findRadarChartCurrentIndex({x:a,y:n},this.chartData.radarData,this.opts.categories.length):findCurrentIndex({x:a,y:n},this.chartData.xAxisPoints,this.opts,this.config,Math.abs(this.scrollOption.currentOffset))}return-1},Charts.prototype.showToolTip=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(\"line\"===this.opts.type||\"area\"===this.opts.type){var i=this.getCurrentDataIndex(t),a=this.scrollOption.currentOffset,n=assign({},this.opts,{_scrollDistance_:a,animation:!1});if(i>-1){var o=getSeriesDataItem(this.opts.series,i);if(0!==o.length){var r=getToolTipData(o,this.chartData.calPoints,i,this.opts.categories,e),s=r.textList,l=r.offset;n.tooltip={textList:s,offset:l,option:e}}}drawCharts.call(this,n.type,n,this.config,this.context)}},Charts.prototype.scrollStart=function(t){t.touches[0]&&!0===this.opts.enableScroll&&(this.scrollOption.startTouchX=t.touches[0].x)},Charts.prototype.scroll=function(t){if(t.touches[0]&&!0===this.opts.enableScroll){var e=t.touches[0].x-this.scrollOption.startTouchX,i=this.scrollOption.currentOffset,a=calValidDistance(i+e,this.chartData,this.config,this.opts);this.scrollOption.distance=e=a-i;var n=assign({},this.opts,{_scrollDistance_:i+e,animation:!1});drawCharts.call(this,n.type,n,this.config,this.context)}},Charts.prototype.scrollEnd=function(t){if(!0===this.opts.enableScroll){var e=this.scrollOption,i=e.currentOffset,a=e.distance;this.scrollOption.currentOffset=i+a,this.scrollOption.distance=0}},module.exports=Charts;\r\n"
  },
  {
    "path": "src/campus-card-page/pages/add-room.wpy",
    "content": "<template>\n  <BaseContainer :navTitle.sync=\"navigationBarTitleText\">\n    <view slot=\"qy-content\">\n      <view>\n        <qy-tip :content.sync=\"tipContent\" :on.sync=\"tipOn\"/>\n        <view class=\"container\">\n          <picker range=\"{{campusArray}}\"  @change=\"changeCampus\">\n            <view class=\"room-information\">\n              <view class=\"arrow\"></view>\n              <view class=\"information-name\">校区</view>\n                <view class=\"information-item\">{{campusArray[campusIndex]}}</view>\n            </view>\n          </picker>\n          <picker range=\"{{buildingArray[campusIndex]}}\" value=\"{{areaIndex}}\" @change=\"changeArea\">\n            <view class=\"room-information\">\n              <view class=\"arrow\"></view>\n              <view class=\"information-name\">苑区</view>\n              <view class=\"information-item\">{{buildingArray[campusIndex][areaIndex]}}</view>\n            </view>\n          </picker>\n          <picker range=\"{{campusIndex == 1 ? roomArray[0] : roomArray[areaIndex]}}\" value=\"{{buildingIndex}}\" @change=\"changeBuilding\">\n            <view class=\"room-information\">\n              <view class=\"arrow\"></view>\n              <view class=\"information-name\">楼栋</view>\n              <view class=\"information-item\">{{campusIndex == 1 ? roomArray[0][buildingIndex] : roomArray[areaIndex][buildingIndex]}}栋</view>\n            </view>\n          </picker>\n          <view class=\"room-information\">\n            <view class=\"information-name\">大寝号</view>\n            <input placeholder=\"请输入大寝号，格式如101\" value=\"{{bigRoom}}\" @input=\"getBigRoom\"/>\n          </view>\n          <view class=\"room-information\">\n            <view class=\"information-name\">小寝号</view>\n            <input placeholder=\"{{!queryElec ? '请输入小寝号，格式如1（三牌楼不填）' : '请输入小寝号，格式如1（查大寝不填）'}}\" value=\"{{smallRoom}}\" @input=\"getSmallRoom\"/>\n          </view>\n          <view class=\"save {{(campusIndex == 0 && bigRoom !== '' && (queryElec || (!queryElec && smallRoom !== ''))) || (campusIndex == 1 && bigRoom !== '') ? 'active' : ''}}\" @tap=\"queryRoom\">\n            {{queryElec ? '查询' : '保存'}}\n          </view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport QyTip from \"@/components/qy-tip\";\nimport { changeDefaultDorm } from \"@/api/common\";\nimport { getDorm, getRemainEle } from \"@/api/campusCard\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class addRoom extends wepy.page {\n  data = {\n    campusArray: [\"仙林\", \"三牌楼\"],\n    queryElec: false,\n    buildingArray: [\n      [\n        \"梅苑\",\n        \"兰苑\",\n        \"竹苑\",\n        \"菊苑\",\n        \"桃苑\",\n        \"李苑\",\n        \"柳苑\",\n        \"桂苑\",\n        \"荷苑\",\n        \"青教\"\n      ],\n      [\"学一楼\", \"学二楼\", \"学三楼\", \"学四楼\", \"学五楼\", \"学六楼\"]\n    ],\n    roomArray: [\n      [1, 2, 3, 4, 5, 6],\n      [7, 8, 9, 10, 11, 12],\n      [13, 14, 15],\n      [16, 17, 18, 19, 20, 21],\n      [22, 23, 24, 25, 26, 27],\n      [28, 29, 30, 31, 32, 33],\n      [34, 35, 36, 37, 38, 39],\n      [40, 41, 42, 43, 44, 45],\n      [46, 47, 48, 49],\n      [7, 8, 9, 10, 11, 12]\n    ],\n    campusIndex: 0,\n    areaIndex: 0,\n    buildingIndex: 0,\n    youngTeacher: false,\n    bigRoom: \"\",\n    smallRoom: \"\",\n    tipOn: false,\n    tipContent: \"\",\n    storageIndex: -1,\n    visitorModeStatus: false,\n    navigationBarTitleText: \"新增宿舍地址\"\n  };\n  components = {\n    \"qy-tip\": QyTip,\n    BaseContainer\n  };\n  methods = {\n    changeCampus(e) {\n      this.campusIndex = e.detail.value;\n    },\n    changeArea(e) {\n      this.areaIndex = e.detail.value;\n      if (this.campusIndex == 1) {\n        this.buildingIndex = e.detail.value;\n      }\n    },\n    changeBuilding(e) {\n      this.buildingIndex = e.detail.value;\n      if (this.campusIndex == 1) {\n        this.areaIndex = e.detail.value;\n      }\n    },\n    getBigRoom(e) {\n      this.bigRoom = e.detail.value;\n    },\n    getSmallRoom(e) {\n      this.smallRoom = e.detail.value;\n    },\n    async queryRoom() {\n      if (this.visitorModeStatus) {\n        return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n      }\n      const roomIndex = this.campusIndex == 1 ? 0 : this.areaIndex;\n      const roomId =\n        this.campusIndex === 1 || this.campusIndex === \"1\"\n          ? \"0\" + this.bigRoom\n          : this.bigRoom + this.smallRoom;\n      const building =\n        this.areaIndex === 9 || this.areaIndex === \"9\"\n          ? Number(\n              this.roomArray[roomIndex][this.buildingIndex] + 48\n            ).toString()\n          : this.roomArray[roomIndex][this.buildingIndex].toString();\n      const buildingId =\n        new Array(Number(4 - building.length)).fill(0).join(\"\") + building;\n      if (this.queryElec) {\n        if (this.campusIndex === \"1\" || this.campusIndex === 1) {\n          return wepy.showModal({\n            title: \"无法查询\",\n            content: \"三牌楼电费暂时无法查询，请耐心等待一段时间哟~\",\n            confirmColor: \"#47CFF5\",\n            showCancel: false,\n            confirmText: \"知道了\"\n          });\n        }\n        const newRoomId =\n          this.smallRoom === \"\"\n            ? this.bigRoom + \"0\"\n            : this.bigRoom + this.smallRoom;\n        const {\n          data: { data }\n        } = await getRemainEle(buildingId, newRoomId);\n        wepy.hideLoading();\n        return wepy.showModal({\n          title: data.bdName + \"\" + data.rmName,\n          content:\n            data.remain + \"度\\r\\n\" + \"(电费充值成功后查询会有五分钟延迟哟~)\",\n          confirmColor: \"#47CFF5\",\n          showCancel: false,\n          confirmText: \"知道了\"\n        });\n      }\n      if (\n        ((this.campusIndex === 0 || this.campusIndex === \"0\") &&\n          this.bigRoom !== \"\" &&\n          this.smallRoom !== \"\") ||\n        ((this.campusIndex === 1 || this.campusIndex === \"1\") &&\n          this.bigRoom !== \"\")\n      ) {\n        wepy.showLoading();\n        const res = await getDorm(this.campusIndex, roomId, buildingId);\n        if (\n          JSON.parse(res.data.data).query_elec_roominfo.retcode === 0 ||\n          JSON.parse(res.data.data).query_elec_roominfo.retcode === \"0\"\n        ) {\n          let item = {\n            campus: this.campusIndex,\n            roomId: roomId,\n            buildingId: buildingId,\n            campusName: this.campusArray[this.campusIndex],\n            areaName: this.buildingArray[this.campusIndex][this.areaIndex],\n            buildingName: this.roomArray[roomIndex][this.buildingIndex],\n            bigRoom: this.bigRoom,\n            smallRoom: this.smallRoom,\n            buildingIndex: this.buildingIndex,\n            default: false,\n            thisTime: false\n          };\n          if (this.storageIndex !== -1) {\n            let storage = wepy.getStorageSync(\"selectRoom\");\n            if (storage[this.storageIndex].default) {\n              item.default = true;\n              let changeRoom = {};\n              const rowDefaultRoom = storage.find(room => room.default);\n              Object.entries(rowDefaultRoom).forEach(([key, value]) => {\n                if (\n                  [\n                    \"campus\",\n                    \"areaName\",\n                    \"buildingId\",\n                    \"bigRoom\",\n                    \"smallRoom\"\n                  ].includes(key)\n                ) {\n                  if (rowDefaultRoom[key] !== item[key]) {\n                    changeRoom[key] = item[key];\n                  }\n                }\n              });\n              if (Object.keys(changeRoom).length) {\n                console.log(changeRoom);\n                const { studentId } =\n                  wepy.getStorageSync(\"userInfo\") ||\n                  wepy.getStorageSync(\"User\");\n                const {\n                  data: { data, success }\n                } = await changeDefaultDorm(changeRoom, studentId);\n                if (!success || !data) {\n                  return wepy.showToast({\n                    title: \"不知道为什么失败了呢~\",\n                    icon: \"none\",\n                    duration: 2000\n                  });\n                }\n              }\n            }\n            storage[this.storageIndex] = item;\n            wepy.setStorageSync(\"selectRoom\", storage);\n            this.backToPrePage();\n          } else {\n            if (!wepy.getStorageSync(\"selectRoom\")) {\n              wepy.setStorageSync(\"selectRoom\", [item]);\n            } else {\n              let rooms = wepy.getStorageSync(\"selectRoom\");\n              rooms.push(item);\n              wepy.setStorageSync(\"selectRoom\", rooms);\n            }\n            this.backToPrePage();\n          }\n        } else {\n          this.tipOn = true;\n          this.tipContent = JSON.parse(\n            res.data.data\n          ).query_elec_roominfo.errmsg;\n          wepy.hideLoading();\n          this.$apply();\n        }\n      } else {\n        this.tipOn = true;\n        this.tipContent = \"信息未填全哦！\";\n      }\n    }\n  };\n  backToPrePage() {\n    wepy.showToast({\n      title: \"成功\",\n      icon: \"success\",\n      duration: 2000\n    });\n    setTimeout(() => {\n      wepy.hideLoading();\n      wepy.navigateBack({\n        delta: 1\n      });\n    }, 2000);\n  }\n  onLoad(e) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    if (e.method === \"query-elec\") {\n      this.navigationBarTitleText = \"电费查询\";\n      this.queryElec = true;\n    }\n    if (e.item) {\n      e.item = JSON.parse(e.item);\n      this.campusIndex = e.item.campus;\n      let area = this.buildingArray[this.campusIndex]\n        .map(\n          (item, index) =>\n            (item = {\n              name: item,\n              index: index\n            })\n        )\n        .filter((item, index) => item.name === e.item.areaName);\n      // if (this.campusIndex === 1 || this.campusIndex === \"1\") {\n      //   area = [\n      //     {\n      //       name: \"三牌楼\",\n      //       index: 0\n      //     }\n      //   ];\n      // }\n      this.areaIndex = area[0].index;\n      this.buildingIndex = e.item.buildingIndex\n        ? e.item.buildingIndex\n        : this.roomArray[this.areaIndex].indexOf(e.item.buildingName);\n      this.bigRoom = e.item.bigRoom;\n      this.smallRoom = e.item.smallRoom;\n      this.storageIndex = Number(e.index);\n    }\n  }\n}\n</script>\n<style lang=\"stylus\" scoped>\n.container\n  width 680rpx\n  margin 0 auto\n  min-height 100vh\n  font-family PingFangSC-Regular\n  font-size 30rpx\n  color #353535\n  .room-information\n    position relative\n    display flex\n    align-items center\n    height 102rpx\n    line-height 102rpx\n    border-bottom 1rpx solid #e3e3e3\n    .information-name\n      width 177rpx\n    input\n      width 500rpx\n      height 30rpx\n      line-height 30rpx\n    .arrow\n      position absolute\n      right 0\n      background-image url('https://static.airbob.org/under-graduate/button_right.png')\n      background-size contain\n      background-repeat no-repeat\n      background-position center\n      width 30rpx\n      height 30rpx\n  .save\n    height 85rpx\n    line-height 85rpx\n    text-align center\n    color #ffffff\n    border-radius 50rpx\n    background-image linear-gradient(45deg, #abdcff 0%, #6ae4ff 100%)\n    margin-top 60rpx\n    &.active\n      background #47cff5\n</style>\n"
  },
  {
    "path": "src/campus-card-page/pages/campus-card-charge.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"校园卡充值\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"head-bg\">\n          <view class=\"head-bg-title\">账户余额（元）</view>\n          <view class=\"head-bg-remain\">{{accountBalance}}</view>\n        </view>\n        <view class=\"main-container\">\n          <view class=\"pay-account\">充值账号：{{sno}}</view>\n          <view class=\"pay-way\">支付方式：银行卡绑定校园卡</view>\n          <view class=\"quick-pay-container\">\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"50\">50元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"100\">100元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"200\">200元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"300\">300元</view>\n          </view>\n          <view class=\"list\">\n            <view class=\"list-item-quick\">\n              <view class=\"list-item-text item\">充值金额</view>\n              <input\n                class=\"list-item-text input\"\n                type=\"digit\"\n                @input=\"put\"\n                value=\"{{charge}}\"\n                placeholder=\"可输入1-300元整数金额\"\n                placeholder-style=\"font-size:30rpx;color:#888888\"\n                cursor-spacing=\"130\"\n              >\n            </view>\n          </view>\n          <button\n            @tap.stop=\"openPayModal\"\n            class=\"enter-button {{(charge==='' || charge === 'NAN' || charge === NAN || !charge) ? 'button-click' : ''}}\"\n            hover-class=\"button-click\"\n            disabled=\"{{(charge==='' || charge === 'NAN' || charge === NAN || !charge)?true:false}}\"\n          >确认充值{{(charge && charge !== '') ? ' ¥' + charge : ''}}</button>\n        </view>\n        <PayFlow\n          :open.sync=\"isPayModalOpen\"\n          :charge.sync=\"charge\"\n          type=\"card\"\n          payWay=\"银行卡绑定校园卡\"\n          operateContent=\"校园卡/银行卡转账\"\n        />\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport PayFlow from \"../components/pay-flow\";\nimport { campusCardRequestInfo } from \"@/api/campusCard\";\nimport { mockCampusCardRequestInfo } from \"@/mock/campusCard\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport { connect } from \"wepy-redux\";\n\n@connect({\n  graduateIdentity(state) {\n    return state.graduateReducer.graduateIdentity;\n  }\n})\nexport default class CampusCardCharge extends wepy.page {\n  data = {\n    accountBalance: 0, // 账户余额\n    cardBalance: 0, //  卡内余额\n    transitionBalance: 0, //  过度余额\n    charge: \"\",\n    // isPageUp: false, // 控制输入时按钮不被遮挡\n    isPayModalOpen: false,\n    sno: \"\",\n    visitorModeStatus: false\n  };\n  components = {\n    PayFlow,\n    BaseContainer\n  };\n  mixins = [JudgeStatus];\n  config = {\n    navigationBarTitleText: \"校园卡充值\",\n    enablePullDownRefresh: true\n  };\n  onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name).then(() => {\n      if (!this.visitorModeStatus) {\n        const moduleStatus = wepy.getStorageSync(\"moduleStatus\")[0].open;\n        if (!moduleStatus) {\n          // 一卡通维护中\n          wepy.redirectTo({\n            url: \"../../others-page/pages/close\"\n          });\n        }\n      }\n      this.getRemain();\n    });\n  }\n  async getRemain() {\n    let yktInfoCache = wepy.getStorageSync(\"yktInfo\");\n    const fromYktIndex =\n      getCurrentPages().findIndex(\n        page => page.route === \"campus-card-page/pages/campus-card-index\"\n      ) !== -1;\n    if (!fromYktIndex || !yktInfoCache || !yktInfoCache.data) {\n      const { data: balance } = !this.visitorModeStatus\n        ? await campusCardRequestInfo(this.graduateIdentity)\n        : await mockCampusCardRequestInfo();\n      yktInfoCache = { data: balance.data, time: new Date() };\n      wepy.setStorageSync(\"yktInfo\", yktInfoCache);\n    }\n    const { data: balance } = yktInfoCache;\n    this.accountBalance = this.graduateIdentity\n      ? (Number(balance.db_balance) + Number(balance.unset_balance)) / 100\n      : (Number(balance.db_balance) + Number(balance.unsettle_amount)) / 100;\n    this.cardBalance = balance.db_balance / 100;\n    this.sno = balance.sno;\n    this.$apply();\n  }\n  async onPullDownRefresh() {\n    await this.getRemain();\n    wepy.stopPullDownRefresh();\n    wepy.showToast({\n      title: \"刷新成功\",\n      icon: \"success\",\n      duration: 1000\n    });\n  }\n  methods = {\n    showWhy() {\n      wepy.showModal({\n        content: \"过度余额多度余额xxxxxx\",\n        confirmText: \"知道了\",\n        showCancel: false,\n        confirmColor: \"#47CFF5\"\n      });\n    },\n    closePayModal() {\n      this.isPayModalOpen = false;\n    },\n    pageUp() {\n      this.isPageUp = true;\n    },\n    noPageUp() {\n      this.isPageUp = false;\n    },\n    put(e) {\n      const value = Number(e.detail.value);\n      this.putCharge(value);\n    },\n    fastPay(e) {\n      const value = Number(e.target.dataset.charge);\n      this.putCharge(value);\n      this.openPayModal();\n    },\n    openPayModal() {\n      // 校验\n      if (this.visitorModeStatus) {\n        this.charge = \"\";\n        return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n      }\n      if (!isNaN(this.charge) && this.charge > 0) {\n        this.isPayModalOpen = true; // 输入密码\n      } else {\n        wepy\n          .showModal({\n            content: \"金额错误\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          })\n          .then(res => {\n            this.charge = \"\";\n          });\n      }\n    }\n  };\n  openPayModal() {\n    // 校验\n    if (this.visitorModeStatus) {\n      this.charge = \"\";\n      return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n    }\n    if (!isNaN(this.charge) && this.charge > 0) {\n      this.isPayModalOpen = true; // 输入密码\n    } else {\n      wepy\n        .showModal({\n          content: \"金额错误\",\n          confirmText: \"知道了\",\n          showCancel: false,\n          confirmColor: \"#353535\"\n        })\n        .then(res => {\n          this.charge = \"\";\n        });\n    }\n  }\n  events = {\n    closePayModal: () => {\n      this.isPayModalOpen = false;\n      this.$apply();\n    }\n  };\n  putCharge(number) {\n    this.charge = number;\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  margin-top 38rpx\n  .head-bg\n    background-image url('https://static.airbob.org/under-graduate/campus-card/card.png')\n    width 100%\n    height 243rpx\n    background-size cover\n    margin 0 auto\n    display flex\n    flex-direction column\n    text-align center\n    color #fff\n    .head-bg-title\n      margin-top 45rpx\n      height 40rpx\n      line-height 40rpx\n      font-size 28rpx\n      font-family PingFangSC-Regular\n    .head-bg-remain\n      font-size 80rpx\n      font-family PingFangSC-Medium\n      height 112rpx\n      line-height 112rpx\n  .main-container\n    margin 50rpx 35rpx 0 35rpx\n    font-family PingFangSC-Regular\n    .pay-account\n      font-family PingFangSC-Medium\n      color #353535\n      height 45rpx\n      line-height 45rpx\n      font-size 32rpx\n    .pay-way\n      font-size 24rpx\n      margin-top 9rpx\n      height 33rpx\n      line-height 33rpx\n      color #888888\n    .quick-pay-container\n      display flex\n      justify-content space-between\n      margin-top 50rpx\n      .quick-pay-item\n        height 100rpx\n        width 150rpx\n        border-radius 10rpx\n        border 1rpx solid #47cff5\n        color #47cff5\n        font-family PingFangSC-Medium\n        font-size 36rpx\n        line-height 100rpx\n        text-align center\n        &:hover\n          background-color #47cff5\n          color #fff\n    .list\n      margin-top 60rpx\n      font-size 30rpx\n      color #353535\n      font-family PingFangSC-Regular\n      .list-item\n        display flex\n        align-items center\n        position relative\n        .why\n          position absolute\n          width 30rpx\n          border-radius 50%\n          top 21rpx\n          left 167rpx\n        & + .list-item\n          border-top 2rpx solid #E3E3E3\n        .list-item-text\n          margin 0rpx 0 15rpx 0\n          &:first-of-type\n            margin-left 34rpx\n            margin-right 100rpx\n      .list-item-quick\n        display flex\n        align-items center\n        border-bottom 2rpx solid #E3E3E3\n        .money-list\n          display flex\n          align-items center\n          .money-item\n            border-radius 60rpx\n            width 93rpx\n            height 45rpx\n            line-height 45rpx\n            color #47CFF5\n            text-align center\n            border 2rpx solid #47CFF5\n            margin-right 30rpx\n        .input\n          z-index auto\n        .list-item-text\n          display flex\n          margin 15rpx 0\n          &.item\n            width 177rpx\n          &.input\n            width 500rpx\n          &:first-of-type\n            color #353535\n  .enter-button\n    background #47cff5\n    border-radius 100rpx\n    width 100%\n    height 85rpx\n    line-height 85rpx\n    color rgb(255, 255, 255)\n    margin-top 60rpx\n    &:after\n      border 0\n  .button-click\n    background-image none\n    background-color #D0F5FF\n</style>\n\n"
  },
  {
    "path": "src/campus-card-page/pages/campus-card-index.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"一卡通\" placeholder=\"6位校园卡密码\" :passwordModelOptions.sync=\"passwordModelOptions\">\n    <view slot=\"qy-content\">\n      <YktBindModal :maskClosable=\"maskClosable\" width=\"500rpx\" :visible.sync=\"yktBindModalVisible\">\n        <view slot=\"content\" class=\"bind-container\">\n          <input\n            class=\"bind-input\"\n            placeholder=\"请输入一卡通卡号\"\n            password=\"{{false}}\"\n            @input=\"bindCardID\"\n            placeholder-style=\"color: #999CA0\"\n          >\n          <input\n            class=\"bind-input\"\n            placeholder=\"请输入一卡通查询密码\"\n            password=\"{{true}}\"\n            @input=\"bindCardPassword\"\n            placeholder-style=\"color: #999CA0\"\n          >\n          <button class=\"bind-button\" @tap.stop=\"goBindCard\" hover-class=\"button-click\">立即绑定</button>\n        </view>\n      </YktBindModal>\n      <view class=\"container\">\n        <view class=\"bg\"/>\n        <view class=\"head\">\n          <view class=\"tip\">余额（元）</view>\n          <view class=\"balance\">{{balance}}</view>\n          <view class=\"tip\">截止时间：{{time}}</view>\n          <view class=\"card-text\">卡号：{{cardNumber}}</view>\n        </view>\n        <view class=\"list\">\n          <block wx:for=\"{{listitems1}}\" wx:key=\"index\">\n            <view\n              class=\"item-container\"\n              @tap.stop=\"navigate\"\n              data-path=\"{{item.navigateURL}}\"\n              data-name=\"{{item.text}}\"\n            >\n              <image class=\"iconx\" src=\"{{item.thumb}}\" mode=\"widthFix\">\n              <view class=\"content\" style=\"justify-content:space-between;\">\n                <text>{{item.text}}</text>\n                <view class=\"iconright\"></view>\n              </view>\n            </view>\n          </block>\n        </view>\n        <view class=\"list\">\n          <block wx:for=\"{{listitems2}}\" wx:key=\"index\">\n            <view\n              class=\"item-container\"\n              @tap.stop=\"navigate\"\n              data-path=\"{{item.navigateURL}}\"\n              data-name=\"{{item.text}}\"\n            >\n              <image class=\"iconx\" src=\"{{item.thumb}}\" mode=\"widthFix\">\n              <view class=\"content\" style=\"justify-content:space-between;\">\n                <text>{{item.text}}</text>\n                <view class=\"iconright\"></view>\n              </view>\n            </view>\n          </block>\n        </view>\n        <view class=\"chart-container\" style=\"height:{{chartContainerHeight}}\">\n          <text class=\"title\">消费水平</text>\n          <view class=\"tab-list\">\n            <view class=\"tab {{chartTab==='week'?'active':'unactive'}}\" @tap.stop=\"changeToWeek\">近7天</view>\n            <view\n              class=\"tab {{chartTab==='halfYear'?'active':'unactive'}}\"\n              @tap.stop=\"changeToYear\"\n            >近半年</view>\n          </view>\n          <canvas\n            class=\"canvas\"\n            disable-scroll=\"true\"\n            canvas-id=\"chartCanvas\"\n            style=\"width:{{width}}px;height:{{height}}px\"\n          ></canvas>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport Chart from \"../components/wxcharts-min.js\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport JudgeStatus from \"@/mixins/module\";\nimport {\n  campusCardRequestInfo,\n  sevenDayTurnOver,\n  yearTurnOver,\n  yktBind\n} from \"@/api/campusCard\";\nimport {\n  mockCampusCardRequestInfo,\n  mockSevenDayTurnOver,\n  mockYearTurnOver\n} from \"@/mock/campusCard\";\nimport { changeSecretCode } from \"@/api/common\";\nimport { connect } from \"wepy-redux\";\nimport QyModal from \"@/components/qy-modal\";\n\n@connect({\n  graduateIdentity(state) {\n    return state.graduateReducer.graduateIdentity;\n  }\n})\nexport default class CampusCard extends wepy.page {\n  components = {\n    BaseContainer,\n    YktBindModal: QyModal\n  };\n  mixins = [JudgeStatus];\n  config = {\n    navigationBarTitleText: \"一卡通\",\n    enablePullDownRefresh: true\n  };\n  data = {\n    navTitle: \"一卡通\",\n    balance: 0,\n    cardNumber: 0,\n    time: \"\",\n    listitems1: [\n      {\n        text: \"校园卡充值\",\n        thumb:\n          \"https://static.airbob.org/under-graduate/card_icon_bank%20transfer.png\",\n        navigateURL: \"./campus-card-charge\"\n      },\n      {\n        text: \"电费充值\",\n        thumb:\n          \"https://static.airbob.org/under-graduate/card_icon_electricity.png\",\n        navigateURL: \"./electric-charge\"\n      },\n      {\n        text: \"校园网充值\",\n        thumb: \"https://static.airbob.org/under-graduate/card_icon_net.png\",\n        navigateURL: \"./net-charge\"\n      }\n    ],\n    listitems2: [\n      {\n        text: \"消费明细\",\n        thumb: \"https://static.airbob.org/under-graduate/card_icon_detail.png\",\n        navigateURL: \"./consumption-detail\"\n      },\n      {\n        text: \"校园卡挂失\",\n        thumb: \"https://static.airbob.org/under-graduate/card_icon_lost.png\",\n        navigateURL: \"./campus-card-loss\"\n      },\n      {\n        text: \"金额操作记录\",\n        thumb:\n          \"https://static.airbob.org/under-graduate/campus-card/jiao-yi-ming-xi@2x.png\",\n        navigateURL: \"./money-log\"\n      }\n    ],\n    chartCanvasStyle: {},\n    canvasConfig: {},\n    chartdata1: [],\n    labels1: [],\n    chartdata2: [],\n    labels2: [],\n    chartTab: \"week\", // or halfYear\n    height: 400,\n    width: 750,\n    chartInstance: {},\n    maskClosable: false,\n    bindInputPassword: \"\",\n    chartContainerHeight: \"auto\",\n    yktStatus: true,\n    placeholder: \"\",\n    passwordModelOptions: {\n      placeholder: \"6位校园卡密码\",\n      passwordModelProps: false,\n      bindInfo: { username: \"\", domainType: \"7\" },\n      checkPassword: function(pwd) {\n        return /^[0-9]*$/.test(pwd) && pwd.length === 6;\n      },\n      checkErrMsg: \"一卡通密码必须6位数字\",\n      refreshData: function() {\n        return null;\n      }\n    },\n    visitorModeStatus: false,\n    yktBindModalVisible: false,\n    yktBindModalCardID: \"\",\n    yktBindModalPassword: \"\"\n  };\n  watch = {\n    chartTab(val) {\n      if (Object.keys(this.chartInstance).length !== 0) {\n        if (val === \"week\") {\n          this.chartInstance.updateData({\n            series: [\n              {\n                data: this.chartdata1\n              }\n            ],\n            categories: this.labels1\n          });\n        } else {\n          this.chartInstance.updateData({\n            series: [\n              {\n                data: this.chartdata2\n              }\n            ],\n            categories: this.labels2\n          });\n        }\n      }\n    },\n    maskClosable(next) {\n      if (next) {\n        this.chartContainerHeight = 0;\n      } else {\n        this.chartContainerHeight = \"auto\";\n      }\n      this.$apply();\n    }\n  };\n  async onPullDownRefresh() {\n    if (this.yktStatus) {\n      await this.init();\n      wepy.stopPullDownRefresh();\n      wepy.showToast({\n        title: \"刷新成功\",\n        icon: \"success\",\n        duration: 1000\n      });\n    }\n  }\n  onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name).then(async () => {\n      wepy.showLoading({\n        title: \"正在加载\"\n      });\n      this.passwordModelOptions.refreshData = this.init.bind(this);\n      await this.init();\n      wepy.hideLoading();\n    });\n  }\n  methods = {\n    changeToWeek() {\n      if (this.chartTab !== \"week\") {\n        this.chartTab = \"week\";\n      }\n    },\n    changeToYear() {\n      if (this.chartTab !== \"halfYear\") {\n        this.chartTab = \"halfYear\";\n      }\n    },\n    bindCardID(e) {\n      this.yktBindModalCardID = e.detail.value;\n    },\n    bindCardPassword(e) {\n      this.yktBindModalPassword = e.detail.value;\n    },\n    navigate(e) {\n      const name = e.currentTarget.dataset.name;\n      wepy.navigateTo({\n        url: `${e.currentTarget.dataset.path}?name=${name}`\n      });\n    },\n    async goBindCard() {\n      wepy.showLoading({\n        title: \"绑定中...\", //提示的内容,\n        mask: true //显示透明蒙层，防止触摸穿透,\n      });\n      const { data: response } = await yktBind(\n        this.yktBindModalCardID,\n        this.yktBindModalPassword\n      );\n      wepy.hideLoading();\n      if (response) {\n        if (response.data) {\n          wepy.showToast({\n            title: \"成功绑定一卡通\",\n            icon: \"success\",\n            duration: 2000\n          });\n          this.yktBindModalVisible = false;\n          this.$apply();\n          this.init();\n        } else {\n          this.$parent.showTip(\"绑定失败，请重试\");\n        }\n      }\n    }\n  };\n  async init() {\n    // 初始化页面\n    const systemInfo = await wepy.getSystemInfo();\n    this.width = Math.floor(systemInfo.windowWidth);\n    this.height = Math.floor(this.width / 1.6);\n    this.chartContainerHeight = \"auto\";\n    const tempDate = new Date();\n    const formatTimeString = raw =>\n      raw.toString().length < 2 ? \"0\" + raw.toString() : raw.toString();\n    this.time = this.graduateIdentity\n      ? `2019-6-20 毕业典礼`\n      : `${tempDate.getFullYear()}-${tempDate.getMonth() +\n          1}-${tempDate.getDate()} ${formatTimeString(\n          tempDate.getHours()\n        )}:${formatTimeString(tempDate.getMinutes())}:${formatTimeString(\n          tempDate.getSeconds()\n        )}`;\n    const { data: response } = !this.visitorModeStatus\n      ? await campusCardRequestInfo(this.graduateIdentity)\n      : await mockCampusCardRequestInfo();\n    if (response) {\n      if (response.data) {\n        const yktInfoCache = { data: response.data, time: new Date() };\n        wepy.setStorageSync(\"yktInfo\", yktInfoCache);\n        this.balance =\n          (Number(response.data.db_balance) +\n            Number(response.data.unsettle_amount)) /\n            100 ||\n          (Number(response.data.db_balance) +\n            Number(response.data.unset_balance)) /\n            100;\n        this.cardNumber = response.data.sno;\n        this.getWeek();\n        this.getYear();\n        this.$apply();\n      } else if (response.errCode === 24) {\n        this.chartContainerHeight = 0;\n        this.placeholder = \"6位校园卡密码\";\n        this.passwordModelOptions.passwordModelProps = true;\n        this.$apply();\n      } else if (response.errCode === 34) {\n        this.yktBindModalVisible = true;\n        this.$apply();\n      }\n    }\n  }\n  async getWeek() {\n    // 获取6天流水\n    this.labels1 = [];\n    const now = Date.now();\n    for (let i = 6; i >= 0; i--) {\n      this.labels1.push(new Date(now - i * 1000 * 3600 * 24).getDate());\n    }\n    const { data: week } = this.visitorModeStatus\n      ? await mockSevenDayTurnOver()\n      : await sevenDayTurnOver();\n    if (week.data && week.data.slice) {\n      this.chartdata1 = week.data.slice().reverse();\n      if (Object.keys(this.chartInstance).length === 0) {\n        // 初始化\n        this.chartInstance = new Chart({\n          canvasId: \"chartCanvas\",\n          type: \"area\",\n          categories: this.labels1,\n          series: [\n            {\n              data: this.chartdata1\n            }\n          ],\n          yAxis: {\n            min: 0,\n            gridColor: \"rgba(255,255,255,0)\"\n          },\n          xAxis: {},\n          legend: false,\n          width: this.width,\n          height: this.height\n        });\n      } else {\n        this.chartInstance.updateData({\n          series: [\n            {\n              data: this.chartdata1\n            }\n          ],\n          categories: this.labels1\n        });\n      }\n    }\n  }\n  async getYear() {\n    // 获取月流水\n    const { data: now_month } = !this.visitorModeStatus\n      ? await yearTurnOver()\n      : await mockYearTurnOver();\n    if (now_month.data) {\n      this.labels2 = [];\n      this.labels2 = now_month.data.resmonth.slice(-6);\n      this.chartdata2 = now_month.data.amt.slice(-6).map(_ => Number(_));\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  align-items center\n  .bg\n    position fixed\n    width 100vw\n    height 100vh\n    background-color rgb(245, 245, 245)\n    z-index -1000\n  .head\n    background-image url('https://static.airbob.org/under-graduate/card_pic.png')\n    width 100%\n    background-repeat no-repeat\n    background-size contain\n    height 400rpx\n    display flex\n    flex-direction column\n    align-items center\n    color #353535\n    background-color rgb(255, 255, 255)\n    .tip\n      font-size 24rpx\n      &:first-child\n        margin-top 49rpx\n    .balance\n      font-size 90rpx\n      font-weight bold\n    .card-text\n      font-size 30rpx\n      font-weight bold\n      margin-top 50rpx\n  .list\n    width 100%\n    margin 20rpx 0\n  .chart-container\n    background-color white\n    overflow hidden\n    padding-top 26rpx\n    width 100%\n    .title\n      font-size 32rpx\n      color #353535\n      font-weight bold\n      margin 30rpx 0 0 20rpx\n    .tab-list\n      display flex\n      margin 15rpx 0 0 20rpx\n      .tab\n        border-radius 60rpx\n        font-size 24rpx\n        padding 4rpx 16rpx\n        &+.tab\n          margin-left 30rpx\n      .active\n        color #fff\n        background-color #47CFF5\n      .unactive\n        color #999CA0\n        border 2rpx solid #999CA0\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 785rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n.button-click\n  background-image none\n  background-color #D0F5FF\n.item-container\n  display flex\n  height 98rpx\n  background-color rgb(255, 255, 255)\n  position relative\n  align-items center\n  margin-right 16rpx\n  &:last-child > .content\n    border-style none !important\n  .iconx\n    width 38rpx\n    margin 0 45rpx 0 25rpx\n  .iconright\n    width 35rpx\n    height 35rpx\n    background-image url('https://static.airbob.org/under-graduate/%E5%8F%B3%E7%AE%AD%E5%A4%B4.png')\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n  .content\n    width 100%\n    height 96rpx\n    display flex\n    align-items center\n    margin-right 20rpx\n    border-bottom 2rpx solid #E3E3E3\n.text\n  font-size 32rpx\n  color #353535\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 285rpx\n  border-radius 30rpx\n  background-size cover\n  padding-top 200rpx;\n  .bind-input\n    font-size 26rpx\n    margin 21rpx 0\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n"
  },
  {
    "path": "src/campus-card-page/pages/campus-card-loss.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"校园卡挂失\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <image class=\"loss-bg\" mode=\"aspectFill\" src=\"https://static.airbob.org/loss/loss.png\"/>\n        <view class=\"loss-list\">\n          <repeat for=\"{{items}}\" key=\"index\">\n            <view class=\"list-item\" @tap=\"toLossPage\" data-index=\"{{index}}\">\n              <image class=\"card-pic\" mode=\"aspectFit\" src=\"https://static.airbob.org/loss/card{{index+1}}.png\"/>\n              <view class=\"card-detail-container\">\n                <view class=\"card-text\">{{item}}</view>\n                <image class=\"card-arrow\" mode=\"aspectFit\" src=\"https://static.airbob.org/loss/arrow.png\"/>\n              </view>\n            </view>\n          </repeat>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\nexport default class CampusCardLoss extends wepy.page {\n  components = {\n    BaseContainer\n  };\n  config = {\n    navigationBarTitleText: \"校园卡挂失\"\n  };\n  mixins = [JudgeStatus];\n  data = {\n    items: [\"校园卡丢失\", \"拾到校园卡\", \"挂失信息\", \"失物招领\", \"挂失解除\"]\n  };\n  methods = {\n    toLossPage(e) {\n      let index = e.currentTarget.dataset.index;\n      wepy.navigateTo({\n        url: \"../../campus-card-page/pages/campus-card-lossPage?index=\" + index\n      });\n    }\n  };\n  onLoad(op) {\n    this.judgeStatus(op.name);\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  align-items center\n  margin-top 38rpx\n  width 100%\n  font-family PingFangSC-Regular\n  .loss-bg\n    width 100%\n    height 243rpx\n    margin 0 auto\n  .loss-list\n    display flex\n    flex-direction column\n    padding 0 20rpx\n    width 100%\n    margin-top 50rpx\n    .list-item\n      display flex\n      flex-direction row\n      align-items center\n      height 100rpx\n      margin 0 20rpx 0 40rpx\n      .card-pic\n        width 50rpx\n        height 50rpx\n      .card-detail-container\n        height 100%\n        width 100%\n        margin-left 50rpx\n        display flex\n        align-items center\n        flex-direction row\n        justify-content space-between\n        border-bottom solid 2rpx #e3e3e3\n        .card-text\n          font-size 32rpx\n          color #353535\n        .card-arrow\n          width 60rpx\n</style>\n"
  },
  {
    "path": "src/campus-card-page/pages/campus-card-lossPage.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"校园卡挂失\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <QyModal height=\"329rpx\" width=\"434rpx\">\n          <view slot=\"content\" class=\"info-container\">\n            <view class=\"info-title\">你可以通过下面的方式联系{{cardIndex===2?\"失主\":\"拾卡人\"}}</view>\n            <view class=\"info-content\">{{info}}</view>\n            <button class=\"info-button\" style=\"color:{{cardIndex===2?'#408175':'#e66c10'}};\" @tap.stop=\"copy\">复制信息</button>\n          </view>\n        </QyModal>\n        <view class=\"loss-header\">\n            <image class=\"card-pic\" mode=\"aspectFit\" src=\"{{cardUrl}}\"/>\n            <view class=\"card-text\">{{ items[cardIndex] }}</view>\n        </view>\n        <view class=\"loss-content\">\n          <view class=\"input-container\" wx:if=\"{{cardIndex===0||cardIndex===4}}\">\n            <view class=\"input-text\">校园卡密码</view>\n            <input placeholder=\"输入你的校园卡密码\" type=\"password\" @input=\"inputCampusPassword\" value=\"{{campusPassword}}\"/>\n          </view>\n          <view class=\"input-container\" wx:if=\"{{cardIndex===1}}\">\n            <view class=\"input-text\">校园卡卡号</view>\n            <input placeholder=\"输入你拾到的校园卡卡号\" @input=\"inputCampusNumber\" value=\"{{campusNumber}}\"/>\n          </view>\n          <view class=\"input-container\" wx:if=\"{{cardIndex===0||cardIndex===1}}\">\n            <view class=\"input-text\">备注</view>\n            <input placeholder=\"你的联系方式\" @input=\"inputCampusDescription\" value=\"{{description}}\"/>\n          </view>\n          <scroll-view class=\"table-container\" wx:if=\"{{cardIndex===2}}\" scroll-y @scrolltolower=\"loadMoreLossInfoList\">\n            <view class=\"tr\" style=\"background:#6bdec9;\">\n              <view class=\"th\">挂失时间</view>\n              <view class=\"th\">姓名</view>\n              <view class=\"th\">卡号后四位</view>\n              <view class=\"th\">备注</view>\n            </view>\n            <repeat for=\"{{ lossInfoData }}\" index=\"index\" key=\"key\" item=\"item\">\n              <view class=\"tr\">\n                <view class=\"td\">{{ item.times }}</view>\n                <view class=\"td\">{{ item.name }}</view>\n                <view class=\"td\">{{ item.card }}</view>\n                <view class=\"td\" style=\"color:#408175;\" @tap.stop=\"showModal\" data-tips=\"{{item.remark?item.remark:'无'}}\">详情</view>\n              </view>\n            </repeat>\n          </scroll-view>\n          <scroll-view class=\"table-container\" wx:if=\"{{cardIndex===3}}\" scroll-y @scrolltolower=\"loadMoreLossObjectList\">\n            <view class=\"tr\" style=\"background:#fc9d57;\">\n              <view class=\"th\">挂失时间</view>\n              <view class=\"th\">姓名</view>\n              <view class=\"th\">卡号后四位</view>\n              <view class=\"th\">备注</view>\n            </view>\n            <repeat for=\"{{ lossObjectData }}\" index=\"index\" key=\"key\" item=\"item\">\n              <view class=\"tr\">\n                <view class=\"td\">{{ item.times }}</view>\n                <view class=\"td\">{{ item.name }}</view>\n                <view class=\"td\">{{ item.card }}</view>\n                <view class=\"td\" style=\"color:#e66c10;\" @tap.stop=\"showModal\" data-tips=\"{{item.remark?item.remark:'无'}}\">详情</view>\n              </view>\n            </repeat>\n          </scroll-view>\n        </view>\n        <button class=\"submitBtn\" style=\"background:{{colors[cardIndex]}};\" wx:if=\"{{cardIndex===0||cardIndex===1||cardIndex===4}}\" @tap=\"submitInformation\">提交</button>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport QyModal from \"@/components/qy-modal\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport {\n  campusLostCard,\n  campusFindCard,\n  campusUnlostCard,\n  getLossInfo,\n  getLossObject\n} from \"@/api/campusCard\";\n\nexport default class CampusCardLoss extends wepy.page {\n  components = {\n    QyModal,\n    BaseContainer\n  };\n  config = {\n    navigationBarTitleText: \"校园卡挂失\"\n  };\n  data = {\n    // 页面\n    items: [\"校园卡丢失\", \"拾到校园卡\", \"挂失信息\", \"失物招领\", \"挂失解除\"],\n    colors: [\"#3891ff\", \"#ed53e3\", \"\", \"\", \"#26c4ef\"],\n    cardUrl: \"\",\n    cardIndex: 0,\n    campusPassword: \"\",\n    campusDescription: \"\",\n    campusNumber: \"\",\n    // 挂失信息\n    lossInfoPage: 1,\n    lossInfoData: [],\n    lossInfoLoading: false,\n    // 失物招领\n    lossObjectPage: 1,\n    lossObjectData: [],\n    lossObjectLoading: false,\n    // modal\n    info: \"\",\n    card: 0\n  };\n  methods = {\n    inputCampusPassword(e) {\n      this.campusPassword = e.detail.value;\n    },\n    inputCampusNumber(e) {\n      this.campusNumber = e.detail.value;\n    },\n    inputCampusDescription(e) {\n      this.campusDescription = e.detail.value;\n    },\n    showModal(e) {\n      this.info = e.target.dataset.tips === null ? \"无\" : e.target.dataset.tips;\n      this.card = e.target.dataset.card;\n      this.$invoke(\"QyModal\", \"open\");\n    },\n    async submitInformation() {\n      if (this.visitorModeStatus) {\n        return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n      }\n      if (this.cardIndex === 0) {\n        let psd = this.campusPassword;\n        let des = this.campusDescription;\n        const res = await campusLostCard(psd, des);\n        if (res.data) {\n          await wepy.showModal({\n            content: res.data.data,\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          });\n        }\n        this.campusPassword = \"\";\n        this.campusDescription = \"\";\n        this.campusNumber = \"\";\n      } else if (this.cardIndex === 1) {\n        let num = this.campusNumber;\n        let des = this.campusDescription;\n        const res = await campusFindCard(num, des);\n        this.campusPassword = \"\";\n        this.campusDescription = \"\";\n        this.campusNumber = \"\";\n        if (res.data) {\n          await wepy.showToast({\n            title: \"提交成功\",\n            icon: \"success\",\n            duration: 1500\n          });\n        } else {\n          switch (res.data.errCode) {\n            case 29:\n              await wepy.showToast({\n                title: \"单个用户一天最多找到4张卡\",\n                icon: \"none\",\n                duration: 1500\n              });\n              break;\n            case 30:\n              await wepy.showToast({\n                title: \"非常遗憾，您输入的卡号没有使用小程序\",\n                icon: \"none\",\n                duration: 1500\n              });\n              break;\n            default:\n              await wepy.showToast({\n                title: \"未知错误\",\n                icon: \"none\",\n                duration: 1500\n              });\n          }\n        }\n        this.$invoke(\"UpLoadModal\", \"close\");\n      } else if (this.cardIndex === 4) {\n        let psd = this.campusPassword;\n        const res = await campusUnlostCard(psd);\n        if (res.data) {\n          await wepy.showModal({\n            content: res.data.data,\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          });\n        }\n        this.campusPassword = \"\";\n        this.campusDescription = \"\";\n        this.campusNumber = \"\";\n      }\n    }\n  };\n  async getLossInfoList(page) {\n    // 获取挂失信息\n    page = page || this.lossInfoPage;\n    wepy.showLoading({\n      title: \"正在加载\"\n    });\n    if (page === 1) {\n      this.lossInfoData = [];\n      // 初次请求的时候请求20条\n      const resArr = [\"1\", \"2\"].map(page => getLossInfo(page));\n      await Promise.all(resArr).then(resDatas => {\n        for (let res of resDatas) {\n          if (res.data && res.data.data.length > 0) {\n            this.lossInfoData = [...this.lossInfoData, ...res.data.data];\n          }\n        }\n      });\n      this.lossInfoPage = 3;\n      wepy.hideLoading();\n    } else {\n      // 非初始状态\n      const res = await getLossInfo(page);\n      if (res.data && res.data.data.length > 0) {\n        this.lossInfoData = [...this.lossInfoData, ...res.data.data];\n        this.lossInfoPage = this.lossInfoPage + 1;\n        wepy.hideLoading();\n      } else {\n        wepy.hideLoading();\n        wepy.showToast({\n          title: \"无更多数据\",\n          icon: \"success\",\n          duration: 1000\n        });\n      }\n    }\n    this.lossInfoLoading = false;\n    this.$apply();\n  }\n  async getLossObjectList(page) {\n    // 获取失物招领列表\n    page = page || this.lossObjectPage;\n    wepy.showLoading({\n      title: \"正在加载\"\n    });\n    if (page === 1) {\n      this.lossObjectData = [];\n      const resArr = [\"1\", \"2\"].map(page => getLossObject(page));\n      await Promise.all(resArr).then(resDatas => {\n        for (let res of resDatas) {\n          if (res.data && res.data.data.length > 0) {\n            this.lossObjectData = [\n              ...this.lossObjectData,\n              ...res.data.data.map(_ => {\n                return _.card\n                  ? {\n                      ..._,\n                      card: _.card.slice(-4)\n                    }\n                  : _;\n              })\n            ];\n          }\n        }\n      });\n      this.lossObjectPage = 3;\n      wepy.hideLoading();\n    } else {\n      const res = await getLossObject(page);\n      if (res.data && res.data.data.length > 0) {\n        this.lossObjectData = [\n          ...this.lossObjectData,\n          ...res.data.data.map(_ => {\n            return _.card\n              ? {\n                  ..._,\n                  card: _.card.slice(-4)\n                }\n              : _;\n          })\n        ];\n        this.lossObjectPage = this.lossObjectPage + 1;\n        wepy.hideLoading();\n      } else {\n        wepy.hideLoading();\n        wepy.showToast({\n          title: \"无更多数据\",\n          icon: \"success\",\n          duration: 1000\n        });\n      }\n    }\n    this.lossObjectLoading = false;\n    this.$apply();\n  }\n  loadMoreLossInfoList() {\n    if (!this.lossInfoLoading) {\n      this.lossInfoLoading = true;\n      this.getLossInfoList();\n    }\n  }\n  loadMoreLossObjectList() {\n    if (!this.lossObjectLoading) {\n      this.lossObjectLoading = true;\n      this.getLossObjectList();\n    }\n  }\n  onLoad(options) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    let cardIndex = Number(options.index);\n    this.cardUrl =\n      \"https://static.airbob.org/loss/card\" + Number(cardIndex + 1) + \".png\";\n    this.cardIndex = cardIndex;\n    if (cardIndex === 2) {\n      this.getLossInfoList(1);\n    } else if (cardIndex === 3) {\n      this.getLossObjectList(1);\n    }\n\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  font-family PingFangSC-Regular\n  font-size 32rpx\n  color #353535\n  .loss-header\n    display flex\n    flex-direction row\n    align-items center\n    height 100rpx\n    margin 30rpx 0 40rpx 0\n    .card-pic\n      width 50rpx\n      height 50rpx\n      margin 0 56rpx 0 40rpx\n    .card-text\n      font-family PingFangSC-Medium\n  .loss-content\n    display flex\n    flex-direction column\n    align-items center\n    margin 0 34rpx\n    .input-container\n      width 100%\n      display flex\n      flex-direction row\n      align-items center\n      height 100rpx\n      border-bottom solid 2rpx #e3e3e3\n      .input-text\n        white-space nowrap\n        width 240rpx\n      input\n        width 100%\n    .table-container\n      display flex\n      flex-direction column\n      width 100%\n      height calc(100vh - 100rpx)\n      .tr\n        min-height 76rpx\n        padding 10rpx 0\n        display flex\n        flex-direction row\n        align-items center\n        border-bottom solid 2rpx #e0e0e0\n        color #353535\n        .th, .td\n          display inline-block\n          font-family PingFangSC-Medium\n          line-height 32rpx\n          min-width 128rpx\n          max-width 164rpx\n          margin 0 30rpx\n      .tr:first-child\n        color #fff\n        border none\n        border-radius 6rpx\n        white-space nowrap\n      .tr:last-child\n        margin-bottom 30rpx\n  .submitBtn\n    position absolute\n    bottom 64rpx\n    right 0\n    left 0\n    color #fff\n    border-radius 50rpx\n    margin 0 34rpx\nbutton:after\n  border none\n.info-container\n  display flex\n  flex-direction column\n  align-items center\n  justify-content space-around\n  height 329rpx\n  .info-title\n    font-size 24rpx\n    color rgb(156, 153, 153)\n  .info-content\n    font-size 36rpx\n    margin 0 30rpx\n  .info-button\n    width 204rpx\n    height 51rpx\n    border-radius 10rpx\n    text-align center\n    line-height 51rpx\n    border 2rpx solid black\n    font-size 26rpx\n</style>\n"
  },
  {
    "path": "src/campus-card-page/pages/consumption-detail.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"bg\"/>\n        <view class=\"head-container\">\n          <view class=\"head-item\">地点</view>\n          <view class=\"head-item\">交易方式</view>\n          <view class=\"head-item\">收支</view>\n        </view>\n        <scroll-view class=\"scroll-container\" scroll-y @scrolltolower=\"loadMore\">\n          <repeat for=\"{{detailsKeys}}\" key=\"index\">\n            <ConsumptionDetailCard :occTime=\"item\" :list=\"details[item]\"/>\n          </repeat>\n        </scroll-view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport ConsumptionDetailCard from \"../components/consumption-detail-card\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport { oneDayTurnOver } from \"@/api/campusCard\";\nimport { mockOneDayTurnOver } from \"@/mock/campusCard\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class ConsumptionDetail extends wepy.page {\n  components = {\n    ConsumptionDetailCard,\n    BaseContainer\n  };\n  data = {\n    navTitle: \"消费明细\",\n    details: {},\n    detailsKeys: [],\n    page: 1,\n    loadingStatus: false, // 当前是否在加载数据\n    visitorModeStatus: false\n  };\n  config = {\n    navigationBarTitleText: \"消费明细\",\n    enablePullDownRefresh: true\n  };\n  async onLoad() {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    // 默认获取15条\n    this.getDetails();\n  }\n  // onPullDownRefresh(){\n  //   this.page =1;\n  //   this.getDetails();\n  //   wepy.stopPullDownRefresh();\n  // };\n  async getDetails() {\n    wepy.showLoading({\n      title: \"正在加载\"\n    });\n    if (this.page === 1) {\n      this.detailsKeys = [];\n      this.details = {};\n    }\n    const res = !this.visitorModeStatus\n      ? await oneDayTurnOver(this.page)\n      : await mockOneDayTurnOver();\n    if (res.data) {\n      res.data.data.forEach(item => {\n        if (this.details[item.occtime.slice(0, 10)]) {\n          this.details[item.occtime.slice(0, 10)] = [\n            ...this.details[item.occtime.slice(0, 10)],\n            item\n          ];\n        } else {\n          this.details[item.occtime.slice(0, 10)] = [item];\n        }\n      });\n      this.detailsKeys = Object.keys(this.details);\n      wepy.hideLoading();\n      this.loadingStatus = false;\n      this.page = this.page + 1;\n      this.$apply();\n    }\n    // this.$apply();\n  }\n  methods = {\n    loadMore() {\n      if (!this.loadingStatus) {\n        this.loadingStatus = true;\n        this.getDetails();\n      }\n    }\n  };\n}\n</script>\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  .bg\n    width 100vw\n    height 100vh\n    position fixed\n    background-color #F5F5F5\n    z-index -1000\n.scroll-container\n  height 100vh\n.head-container\n  background-color white\n  height 89rpx\n  width 100%\n  background-size contain\n  display flex\n  background-image url('https://static.airbob.org/under-graduate/card_list_detail_bg.png')\n  justify-content space-around\n  font-size 32rpx\n  font-weight bold\n  color #353535\n  align-items center\n  .head-item\n    width 33%\n    height 67rpx\n    line-height 67rpx\n    text-align center\n    & + .head-item\n      border-left 2rpx solid #e3e3e3\n</style>\n\n"
  },
  {
    "path": "src/campus-card-page/pages/electric-charge.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"电费充值\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"header-tip\">\n          <view class=\"image-container\"></view>\n          <view class=\"tip-font\">肖辰旭提示你：剩余电量数据可能存在5min的延迟，请耐心等待哦~</view>\n        </view>\n        <view class=\"head-bg\">\n          <view class=\"head-bg-container\" @tap=\"goSelectRoom\">\n            <view class=\"image\" wx:if=\"{{dorm === '点击添加宿舍地址'}}\"></view>\n            <view class=\"dorm\" wx:if=\"{{dorm === '点击添加宿舍地址'}}\">{{dorm}}</view>\n            <view class=\"remain-electricity\" wx:if=\"{{dorm !== '点击添加宿舍地址'}}\">\n              <view class=\"title\">{{dorm}}剩余电量（度）</view>\n              <view class=\"remains\">{{remainEle}}</view>\n            </view>\n            <view class=\"arrow\"></view>\n          </view>\n        </view>\n        <view class=\"main-container\">\n          <view class=\"pay-account\">本次充值宿舍：{{dormRoom}}</view>\n          <view class=\"pay-way\">支付方式：银行卡绑定校园卡</view>\n          <picker range=\"{{modeArray}}\" value=\"0\" @change=\"changeMode\" wx:if=\"{{dormItem.campus === 0}}\">\n            <view class=\"list\">\n              <view class=\"arrow\"></view>\n              <view class=\"list-item-quick\">\n                <view class=\"list-item-text item\">充值类型</view>\n                <view class=\"list-item-text\">{{modeArray[modeIndex]}}</view>\n              </view>\n            </view>\n          </picker>\n          <view class=\"quick-pay-container\">\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"10\">10元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"20\">20元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"30\">30元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"50\">50元</view>\n          </view>\n          <view class=\"list\">\n            <view class=\"list-item-quick\">\n              <view class=\"list-item-text item\">充值金额</view>\n              <input\n                class=\"list-item-text input\"\n                type=\"digit\"\n                @input=\"putMoney\"\n                value=\"{{charge}}\"\n                placeholder=\"可输入1-300元整数金额\"\n                placeholder-style=\"font-size:30rpx;color:#888888\"\n                cursor-spacing=\"130\"\n              >\n            </view>\n          </view>\n          <view class=\"button-container\">\n            <button\n              @tap.stop=\"openPayModal\"\n              class=\"enter-button {{(charge === '' || charge === 'NAN' || charge === NAN || !charge) ? 'button-click' : ''}}\"\n              hover-class=\"button-click\"\n              disabled=\"{{(charge==='' || charge === 'NAN' || charge === NAN || !charge)?true:false}}\"\n            >确认充值{{(charge && charge !== '') ? ' ¥' + charge : ''}}</button>\n            <button @tap.stop=\"getQueryElec\" class=\"get-query-elec\">电费查询</button>\n          </view>\n        </view>\n        <PayFlow\n          :electricURL.sync=\"electricURL\"\n          :open.sync=\"isPayModalOpen\"\n          type=\"electric\"\n          :charge.sync=\"charge\"\n          payWay=\"校园卡电费转账\"\n          :operateContent=\"modeArray[modeIndex]\"\n        />\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport PayFlow from \"../components/pay-flow\";\nimport JudgeStatus from \"@/mixins/module\";\nimport { getRemainEle } from \"@/api/campusCard\";\nimport { getDefaultDorm } from \"@/api/common\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class ElectricCharge extends wepy.page {\n  data = {\n    charge: \"\",\n    remainEle: 0,\n    isPayModalOpen: false,\n    isPageUp: false,\n    modeArray: [\"小寝电费充值\", \"大寝电费充值\"],\n    modeIndex: \"0\", // 0 大寝室、 1 小寝室\n    electricURL: \"\",\n    useOnce: -1,\n    dorm: \"点击添加宿舍地址\",\n    dormRoom: \"请先添加宿舍\",\n    dormItem: {},\n    visitorModeStatus: false\n  };\n  components = {\n    PayFlow,\n    BaseContainer\n  };\n  mixins = [JudgeStatus];\n  config = {\n    navigationBarTitleText: \"电费充值\"\n  };\n  computed = {\n    downButtonClick() {\n      return (\n        this.charge === \"\" ||\n        this.bigNumber === \"\" ||\n        (this.modeIndex === 1 && this.smallNumber === \"\")\n      );\n    }\n  };\n  watch = {\n    modeIndex(newValue, oldValue) {\n      if (this.selectRoom !== \"\" && this.selectRoom) {\n        this.dormRoom =\n          this.dormItem.campusName +\n          \"校区 \" +\n          this.dormItem.areaName +\n          \" \" +\n          this.dormItem.buildingName +\n          \"栋 \" +\n          this.dormItem.bigRoom;\n        if (newValue === 0 || newValue === \"0\") {\n          this.dormRoom +=\n            this.dormItem.campus === 1 || this.dormItem.campus === \"1\"\n              ? \"\"\n              : \"-\" + this.dormItem.smallRoom;\n        }\n      }\n    }\n  };\n  methods = {\n    getQueryElec() {\n      this.$navigate({\n        url: \"./add-room?method=query-elec\"\n      });\n    },\n    closePayModal() {\n      this.isPayModalOpen = false;\n    },\n    putMode(e) {\n      this.modeIndex = e.detail.value;\n    },\n    goSelectRoom() {\n      this.$navigate({\n        url: \"./select-room\"\n      });\n    },\n    putMoney(e) {\n      // 校验金额\n      const value = Number(e.detail.value);\n      this.putCharge(value);\n    },\n    fastPay(e) {\n      const value = Number(e.target.dataset.charge);\n      this.putCharge(value);\n      this.openPayModal();\n    },\n    async changeMode(e) {\n      this.modeIndex = e.detail.value;\n      if (this.modeIndex === \"1\" || this.modeIndex === 1) {\n        const publicEle = this.dormItem.roomId.substr(0, 3) + \"0\";\n        const data = await this.queryEleRemain(\n          this.dormItem.buildingId,\n          publicEle\n        );\n        this.dorm =\n          this.dormItem.campusName + \"校区 \" + data.bdName + \" \" + data.rmName;\n        this.$apply();\n      } else if (this.modeIndex === \"0\" || this.modeIndex === 0) {\n        const data = await this.queryEleRemain(\n          this.dormItem.buildingId,\n          this.dormItem.roomId\n        );\n        this.dorm =\n          this.dormItem.campusName + \"校区 \" + data.bdName + \" \" + data.rmName;\n        this.$apply();\n      }\n    }\n  };\n  events = {\n    closePayModal: () => {\n      this.isPayModalOpen = false;\n      this.$apply();\n    }\n  };\n  async queryEleRemain(buildingId, roomId) {\n    if (this.dormItem.campus === \"1\" || this.dormItem.campus === 1) {\n      this.remainEle = \"无法查询\";\n      this.$apply();\n    } else {\n      const {\n        data: { data: remainEle }\n      } = await getRemainEle(buildingId, roomId);\n      this.remainEle = remainEle.remain || \"\";\n      this.$apply();\n      return remainEle;\n    }\n  }\n  openCheckModal() {\n    return wepy.showModal({\n      title: \"金额确认\",\n      content: `确定充值 ￥${this.charge} 到电费中吗？`,\n      showCancel: true,\n      cancelText: \"否\",\n      cancelColor: \"#FF0000\",\n      confirmText: \"是\",\n      confirmColor: \"#3CC51F\"\n    });\n  }\n  async openPayModal() {\n    if (this.visitorModeStatus) {\n      this.charge = \"\";\n      return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n    }\n    const roomId =\n      (this.dormItem.campus === 1 || this.dormItem.campus === \"1\" ? \"0\" : \"\") +\n      this.dormItem.bigRoom +\n      (this.dormItem.campus === 1 || this.dormItem.campus === \"1\"\n        ? \"\"\n        : this.modeIndex === \"0\" || this.modeIndex === 0\n        ? this.dormItem.smallRoom\n        : \"0\");\n    // const buildingId =\n    //   this.dormItem.areaName === \"青教\"\n    //     ? Number(this.dormItem.buildingName + 48).toString()\n    //     : this.dormItem.buildingName.toString();\n    if (\n      this.dormItem &&\n      roomId &&\n      this.dormItem.buildingId &&\n      (this.dormItem.campus == 0 || this.dormItem.campus == 1)\n    ) {\n      this.electricURL = `campus=${\n        this.dormItem.campus\n      }&roomId=${roomId}&buildingId=${this.dormItem.buildingId}`; // 用来在PayFlow中拼接 金额和密码\n      if (this.charge > 0) {\n        if (this.charge > 50) {\n          const res = await this.openCheckModal();\n          if (res.confirm) {\n            this.isPayModalOpen = true;\n            this.$apply();\n          }\n        } else {\n          this.isPayModalOpen = true;\n        }\n      } else {\n        wepy\n          .showModal({\n            content: \"金额错误\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          })\n          .then(res => {\n            this.charge = \"\";\n          });\n      }\n    } else {\n      wepy.showModal({\n        content: \"请先添加宿舍\",\n        confirmText: \"知道了\",\n        showCancel: false,\n        confirmColor: \"#353535\"\n      });\n    }\n  }\n  putCharge(number) {\n    this.charge = number;\n  }\n  setDormText() {\n    this.dorm =\n      this.dormItem.campusName +\n      \"校区 \" +\n      this.dormItem.areaName +\n      \" \" +\n      this.dormItem.buildingName +\n      \"栋 \" +\n      this.dormItem.bigRoom +\n      (this.dormItem.campus === 1 || this.dormItem.campus === \"1\"\n        ? \"\"\n        : \"-\" + this.dormItem.smallRoom);\n    this.dormRoom = this.dorm;\n  }\n  async init() {\n    const page = getCurrentPages();\n    const nowPage = page[page.length - 1];\n    this.useOnce = nowPage.data.useOnce;\n    this.selectRoom = wepy.getStorageSync(\"selectRoom\");\n    if (this.selectRoom !== \"\" && this.selectRoom) {\n      if (this.useOnce !== -1 && this.useOnce !== \"-1\") {\n        this.dormItem = this.selectRoom[this.useOnce];\n      } else {\n        this.dormItem = this.selectRoom.find(item => item.default);\n      }\n      this.setDormText();\n      await this.queryEleRemain(this.dormItem.buildingId, this.dormItem.roomId);\n    } else {\n      const {\n        data: { data, success }\n      } = await getDefaultDorm();\n      if (success && data) {\n        const {\n          area: campus,\n          yuanqu: areaName,\n          louhao: buildingId,\n          fanghao: bigRoom,\n          shihao: smallRoom\n        } = data;\n        const tempObj = {\n          areaName,\n          buildingId,\n          buildingName: parseInt(buildingId),\n          bigRoom,\n          smallRoom,\n          default: true,\n          thisTime: false\n        };\n        this.dormItem =\n          campus === \"XL\"\n            ? {\n                campusName: \"仙林\",\n                campus: 0,\n                roomId: bigRoom + smallRoom,\n                ...tempObj\n              }\n            : {\n                campusName: \"三牌楼\",\n                campus: 1,\n                roomId: \"0\" + bigRoom,\n                ...tempObj\n              };\n        wepy.setStorageSync(\"selectRoom\", [this.dormItem]);\n        this.setDormText();\n        await this.queryEleRemain(\n          this.dormItem.buildingId,\n          this.dormItem.roomId\n        );\n      }\n    }\n  }\n  onShow() {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.init();\n    if (!this.visitorModeStatus) {\n      const moduleStatus = wepy.getStorageSync(\"moduleStatus\")[0].open;\n      if (!moduleStatus) {\n        // 一卡通维护中\n        wepy.redirectTo({\n          url: \"../../others-page/pages/close\"\n        });\n      }\n    }\n  }\n  onLoad(op) {\n    this.judgeStatus(op.name);\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  margin-top 38rpx\n  .header-tip\n    display flex\n    font-family PingFangSC-Regular\n    font-size 24rpx\n    color #888888\n    margin 0 35rpx 16rpx 35rpx\n    .image-container\n      width 46rpx\n      height 46rpx\n      background-size contain\n      background-repeat no-repeat\n      background-image url('https://static.airbob.org/under-graduate/campus-card/notice%21@2x.png')\n  .head-bg\n    background-image url('https://static.airbob.org/under-graduate/campus-card/elec.png')\n    width 100%\n    height 243rpx\n    background-size cover\n    margin 0 auto\n    display flex\n    text-align center\n    align-items center\n    justify-content center\n    color #fff\n    .head-bg-container\n      display flex\n      justify-content center\n      align-items center\n      .image\n        background-image url('https://static.airbob.org/under-graduate/campus-card/position.png')\n        background-size contain\n        background-repeat no-repeat\n        background-position center\n        width 50rpx\n        height 50rpx\n        margin-right 30rpx\n      .arrow\n        margin-left 10rpx\n        background-image url('https://static.airbob.org/under-graduate/campus-card/arrow-right.png')\n        background-size contain\n        background-repeat no-repeat\n        background-position center\n        width 25rpx\n        height 25rpx\n      .dorm\n        height 50rpx\n        line-height 50rpx\n        color #fff\n        font-size 34rpx\n        font-family PingFangSC-Medium\n      .remain-electricity\n        display flex\n        flex-direction column\n        justify-content space-between\n        align-items center\n        color #fff\n        height 152rpx\n        .title\n          font-family PingFangSC-Regular\n          font-size 28rpx\n        .remains\n          font-family PingFangSC-Medium\n          font-size 80rpx\n  .main-container\n    margin 50rpx 35rpx 0 35rpx\n    font-family PingFangSC-Regular\n    .pay-account\n      font-family PingFangSC-Medium\n      color #353535\n      height 45rpx\n      line-height 45rpx\n      font-size 32rpx\n    .pay-way\n      font-size 24rpx\n      margin-top 9rpx\n      height 33rpx\n      line-height 33rpx\n      color #888888\n    .quick-pay-container\n      display flex\n      justify-content space-between\n      margin-top 50rpx\n      .quick-pay-item\n        height 100rpx\n        width 150rpx\n        border-radius 10rpx\n        border 1rpx solid #47cff5\n        color #47cff5\n        font-family PingFangSC-Medium\n        font-size 36rpx\n        line-height 100rpx\n        text-align center\n        &:hover\n          background-color #47cff5\n          color #fff\n    .list\n      margin-top 60rpx\n      font-size 30rpx\n      color #353535\n      font-family PingFangSC-Regular\n      position relative\n      .arrow\n        position absolute\n        right 0\n        top 21rpx\n        background-image url('https://static.airbob.org/under-graduate/button_right.png')\n        background-size contain\n        background-repeat no-repeat\n        background-position center\n        width 30rpx\n        height 30rpx\n      .list-item\n        display flex\n        align-items center\n        position relative\n        .why\n          position absolute\n          width 30rpx\n          border-radius 50%\n          top 21rpx\n          left 167rpx\n        & + .list-item\n          border-top 2rpx solid #E3E3E3\n        .list-item-text\n          margin 0rpx 0 15rpx 0\n          &:first-of-type\n            margin-left 34rpx\n            margin-right 100rpx\n      .list-item-quick\n        display flex\n        align-items center\n        border-bottom 2rpx solid #E3E3E3\n        .money-list\n          display flex\n          align-items center\n          .money-item\n            border-radius 60rpx\n            width 93rpx\n            height 45rpx\n            line-height 45rpx\n            color #47CFF5\n            text-align center\n            border 2rpx solid #47CFF5\n            margin-right 30rpx\n        .input\n          z-index auto\n        .list-item-text\n          display flex\n          margin 15rpx 0\n          &.item\n            width 177rpx\n          &.input\n            width 500rpx\n          &:first-of-type\n            color #353535\n  .button-container\n    display flex\n    justify-content space-between\n    .get-query-elec\n      background #F3A930\n      border-radius 100rpx\n      width 32%\n      height 85rpx\n      line-height 85rpx\n      color rgb(255, 255, 255)\n      margin-top 60rpx\n    .enter-button\n      background #47cff5\n      border-radius 100rpx\n      width 62%\n      height 85rpx\n      line-height 85rpx\n      color rgb(255, 255, 255)\n      margin-top 60rpx\n      &:after\n        border 0\n    .button-click\n      background-image none\n      background-color #D0F5FF\n</style>\n"
  },
  {
    "path": "src/campus-card-page/pages/money-log.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"金额操作记录\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"header-tip\">\n          <view class=\"image-container\"></view>\n          <view class=\"tip-font\">\n            肖辰旭提示你：此表格只代表在小程序端的操作记录，不一定表示交易成功哦～\n          </view>\n        </view>\n        <scroll-view scroll-x style=\"position:relative;width:750rpx;\">\n          <view class=\"main-container\">\n            <view class=\"main-container-header\">\n              <view class=\"header-item\">项目</view>\n              <view class=\"header-item\">金额</view>\n              <view class=\"header-item\">时间</view>\n              <view class=\"header-item\">备注</view>\n            </view>\n            <view class=\"main-container-item\" wx:for=\"{{records}}\" wx:key=\"index\" wx:index=\"index\">\n              <view class=\"main-item\">{{item.type}}</view>\n              <view class=\"main-item\">{{item.money / 100}} 元</view>\n              <view class=\"main-item\">{{item.time}}</view>\n              <view class=\"main-item longer\">{{item.extra || '无'}}</view>\n            </view>\n          </view>\n        </scroll-view>\n        <view class=\"rectangle\"></view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport { getMoneyLog } from \"@/api/campusCard\";\nimport { mockGetMoneyLog } from \"@/mock/campusCard\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class MoneyLog extends wepy.page {\n  data = {\n    records: [],\n    pageNumber: 1,\n    visitorModeStatus: false\n  };\n  components = {\n    BaseContainer\n  };\n  config = {\n    navigationBarTitleText: \"金额操作记录\"\n  };\n  async getData(pageNum) {\n    const { data } = !this.visitorModeStatus\n      ? await getMoneyLog(pageNum, 30)\n      : await mockGetMoneyLog();\n    const result = data.data;\n    result.map(item => {\n      const time = new Date(item.createTime);\n      return (item.time =\n        time.getFullYear() +\n        \".\" +\n        Number(time.getMonth() + 1) +\n        \".\" +\n        time.getDate());\n    });\n    this.records.push(...result);\n    this.$apply();\n  }\n  async onLoad() {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    await this.getData(1);\n  }\n  async onReachBottom() {\n    if (!this.visitorModeStatus) {\n      await this.getData(++this.pageNumber);\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  min-height 100vh\n  margin 0 0 0 26rpx\n  width 724rpx\n  position absolute\n  .rectangle\n    position absolute\n    top 186rpx\n    width 108rpx\n    right 0\n    height calc(100% - 170rpx)\n    background-image linear-gradient(90deg, rgba(255, 255, 255, 0.11) 0%, rgba(255, 255, 255, 0.98) 100%)\n  .header-tip\n    display flex\n    font-family PingFangSC-Regular\n    font-size 24rpx\n    color #888888\n    margin-bottom 16rpx\n    width calc(100% - 52rpx)\n    .image-container\n      width 46rpx\n      height 46rpx\n      background-size contain\n      background-repeat no-repeat\n      background-image url('https://static.airbob.org/under-graduate/campus-card/notice%21@2x.png')\n  .main-container\n    min-width 1000rpx\n    .main-container-header\n      background #6BDEC9\n      display flex\n      align-items center\n      height 96rpx\n      border-radius 6rpx\n      .header-item\n        font-family PingFangSC-Medium\n        font-size 32rpx\n        padding-left 23rpx\n        width 185rpx\n        color #ffffff\n    .main-container-item\n      position relative\n      display flex\n      font-family PingFangSC-Regular\n      font-size 32rpx\n      height 98rpx\n      align-items center\n      color #353535\n      border-bottom 1px solid #D7D7D7\n      .main-item\n        overflow hidden\n        padding-left 23rpx\n        width 185rpx\n      .longer\n        flex 1\n        width 100%\n</style>\n"
  },
  {
    "path": "src/campus-card-page/pages/net-charge.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"校园网充值\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"head-bg\">\n          <view class=\"head-bg-title\">账户余额（元）</view>\n          <view class=\"head-bg-remain\">{{balance}}</view>\n        </view>\n        <view class=\"main-container\">\n          <view class=\"pay-account\">充值账号：{{sno}}</view>\n          <view class=\"pay-way\">支付方式：银行卡绑定校园卡</view>\n          <view class=\"quick-pay-container\">\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"5\">5元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"10\">10元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"20\">20元</view>\n            <view class=\"quick-pay-item\" @tap.stop=\"fastPay\" data-charge=\"30\">30元</view>\n          </view>\n          <view class=\"list\">\n            <view class=\"list-item-quick\">\n              <view class=\"list-item-text item\">充值金额</view>\n              <input\n                class=\"list-item-text input\"\n                type=\"digit\"\n                @input=\"put\"\n                value=\"{{charge}}\"\n                placeholder=\"可输入1-300元整数金额\"\n                placeholder-style=\"font-size:30rpx;color:#888888\"\n                cursor-spacing=\"130\"\n              />\n            </view>\n          </view>\n          <button\n            @tap.stop=\"openPayModal\"\n            class=\"enter-button {{(charge==='' || charge === 'NAN' || charge === NAN || !charge) ? 'button-click' : ''}}\"\n            hover-class=\"button-click\"\n            disabled=\"{{(charge==='' || charge === 'NAN' || charge === NAN || !charge)?true:false}}\"\n          >确认充值{{(charge && charge !== '') ? ' ¥' + charge : ''}}</button>\n        </view>\n        <PayFlow\n          :open.sync=\"isPayModalOpen\"\n          :charge.sync=\"charge\"\n          type=\"net\"\n          payWay=\"银行卡绑定校园卡\"\n          operateContent=\"校园卡/银行卡转账\"\n        />\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport PayFlow from \"../components/pay-flow\";\nimport JudgeStatus from \"@/mixins/module\";\nimport { internetRemain } from \"@/api/campusCard\";\nimport { mockInternetRemain } from \"@/mock/campusCard\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class NetCharge extends wepy.page {\n  data = {\n    balance: \"0.00\",\n    charge: \"\",\n    isPayModalOpen: false,\n    sno: \"\",\n    visitorModeStatus: false\n  };\n  config = {\n    navigationBarTitleText: \"校园网充值\",\n    enablePullDownRefresh: true\n  };\n  components = {\n    PayFlow,\n    BaseContainer\n  };\n  mixins = [JudgeStatus];\n  onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    if (this.visitorModeStatus) {\n      this.getRemain();\n    } else {\n      const moduleStatus = wepy.getStorageSync(\"moduleStatus\")[0].open;\n      if (!moduleStatus) {\n        // 一卡通维护中\n        wepy.redirectTo({\n          url: \"../../others-page/pages/close\"\n        });\n      }\n      this.judgeStatus(op.name).then(() => {\n        this.getRemain();\n      });\n    }\n  }\n  onShow() {\n    this.getRemain();\n  }\n  onPullDownRefresh() {\n    this.getRemain();\n    wepy.stopPullDownRefresh();\n    wepy.showToast({\n      title: \"刷新成功\",\n      icon: \"success\",\n      duration: 1000\n    });\n  }\n  judgeRemain() {\n    return this.visitorModeStatus ? mockInternetRemain() : internetRemain();\n  }\n  getRemain() {\n    this.judgeRemain().then(res => {\n      if (res.data) {\n        this.balance = res.data.data / 100;\n        this.sno = wepy.getStorageSync(\"sno\");\n        this.$apply();\n      }\n    });\n  }\n  openCheckModal() {\n    return wepy.showModal({\n      title: \"金额确认\",\n      content: `确定充值 ￥${this.charge} 到网费中吗？`,\n      showCancel: true,\n      cancelText: \"否\",\n      cancelColor: \"#FF0000\",\n      confirmText: \"是\",\n      confirmColor: \"#3CC51F\"\n    });\n  }\n  methods = {\n    closePayModal() {\n      this.isPayModalOpen = false;\n    },\n    put(e) {\n      const value = Number(e.detail.value);\n      this.putCharge(value);\n    },\n    fastPay(e) {\n      const value = Number(e.target.dataset.charge);\n      this.putCharge(value);\n      this.openPayModal();\n    },\n    async openPayModal() {\n      if (this.visitorModeStatus) {\n        this.charge = \"\";\n        return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n      }\n      if (this.charge > 0) {\n        if (this.charge > 30) {\n          const res = await this.openCheckModal();\n          if (res.confirm) {\n            this.isPayModalOpen = true;\n            this.$apply();\n          }\n        } else {\n          this.isPayModalOpen = true;\n        }\n      } else {\n        wepy\n          .showModal({\n            content: \"金额错误\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          })\n          .then(res => {\n            this.charge = \"\";\n          });\n      }\n    }\n  };\n  events = {\n    closePayModal: () => {\n      this.isPayModalOpen = false;\n      this.$apply();\n    }\n  };\n  async openPayModal() {\n    if (this.visitorModeStatus) {\n      this.charge = \"\";\n      return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n    }\n    if (this.charge > 0) {\n      if (this.charge > 30) {\n        const res = await this.openCheckModal();\n        if (res.confirm) {\n          this.isPayModalOpen = true;\n          this.$apply();\n        }\n      } else {\n        this.isPayModalOpen = true;\n      }\n    } else {\n      wepy\n        .showModal({\n          content: \"金额错误\",\n          confirmText: \"知道了\",\n          showCancel: false,\n          confirmColor: \"#353535\"\n        })\n        .then(res => {\n          this.charge = \"\";\n        });\n    }\n  }\n  putCharge(number) {\n    this.charge = number;\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  margin-top 38rpx\n  .head-bg\n    background-image url('https://static.airbob.org/under-graduate/campus-card/net.png')\n    width 100%\n    height 243rpx\n    background-size cover\n    margin 0 auto\n    display flex\n    flex-direction column\n    text-align center\n    color #fff\n    .head-bg-title\n      margin-top 45rpx\n      height 40rpx\n      line-height 40rpx\n      font-size 28rpx\n      font-family PingFangSC-Regular\n    .head-bg-remain\n      font-size 80rpx\n      font-family PingFangSC-Medium\n      height 112rpx\n      line-height 112rpx\n  .main-container\n    margin 50rpx 35rpx 0 35rpx\n    font-family PingFangSC-Regular\n    .pay-account\n      font-family PingFangSC-Medium\n      color #353535\n      height 45rpx\n      line-height 45rpx\n      font-size 32rpx\n    .pay-way\n      font-size 24rpx\n      margin-top 9rpx\n      height 33rpx\n      line-height 33rpx\n      color #888888\n    .quick-pay-container\n      display flex\n      justify-content space-between\n      margin-top 50rpx\n      .quick-pay-item\n        height 100rpx\n        width 150rpx\n        border-radius 10rpx\n        border 1rpx solid #47cff5\n        color #47cff5\n        font-family PingFangSC-Medium\n        font-size 36rpx\n        line-height 100rpx\n        text-align center\n        &:hover\n          background-color #47cff5\n          color #fff\n    .list\n      margin-top 60rpx\n      font-size 30rpx\n      color #353535\n      font-family PingFangSC-Regular\n      .list-item\n        display flex\n        align-items center\n        position relative\n        .why\n          position absolute\n          width 30rpx\n          border-radius 50%\n          top 21rpx\n          left 167rpx\n        & + .list-item\n          border-top 2rpx solid #E3E3E3\n        .list-item-text\n          margin 0rpx 0 15rpx 0\n          &:first-of-type\n            margin-left 34rpx\n            margin-right 100rpx\n      .list-item-quick\n        display flex\n        align-items center\n        border-bottom 2rpx solid #E3E3E3\n        .money-list\n          display flex\n          align-items center\n          .money-item\n            border-radius 60rpx\n            width 93rpx\n            height 45rpx\n            line-height 45rpx\n            color #47CFF5\n            text-align center\n            border 2rpx solid #47CFF5\n            margin-right 30rpx\n        .input\n          z-index auto\n        .list-item-text\n          display flex\n          margin 15rpx 0\n          &.item\n            width 177rpx\n          &.input\n            width 500rpx\n          &:first-of-type\n            color #353535\n  .enter-button\n    background #47cff5\n    border-radius 100rpx\n    width 100%\n    height 85rpx\n    line-height 85rpx\n    color rgb(255, 255, 255)\n    margin-top 60rpx\n    &:after\n      border 0\n  .button-click\n    background-image none\n    background-color #D0F5FF\n</style>\n\n\n\n"
  },
  {
    "path": "src/campus-card-page/pages/select-room.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"管理宿舍地址\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view wx:if=\"{{rooms.length === 0}}\" class=\"not-used\">你还没充过电费呢～</view>\n        <view wx:else class=\"room-container\">\n          <view class=\"room-item-container\" wx:for=\"{{rooms}}\" index=\"index\" item=\"item\" wx:key=\"index\">\n            <view class=\"room-item\">\n              <view class=\"room-name-container\">\n                <view\n                  class=\"room-name\"\n                >{{item.campusName}}校区 {{item.areaName}} {{item.buildingName}} {{item.bigRoom}}{{item.smallRoom ? '-' + item.smallRoom : ''}}</view>\n                <view class=\"use-once\" @tap=\"useOnce({{index}})\">本次使用</view>\n              </view>\n              <view class=\"opera-container\">\n                <view class=\"opera-default-container\" @tap=\"changeDefult({{index}})\">\n                  <view\n                    class=\"opera-default\"\n                    style=\"background-image:url({{item.default ? 'https://static.airbob.org/under-graduate/btn_circle_hightlight.png' : 'https://static.airbob.org/under-graduate/btn_circle_disable.png'}})\"\n                  ></view>\n                  <span>设为默认</span>\n                </view>\n                <view class=\"opera\">\n                  <view\n                    class=\"opera-item\"\n                    @tap=\"edit({{item}},{{index}})\"\n                    style=\"background-image:url('https://static.airbob.org/under-graduate/edit.png');\"\n                  ></view>\n                  <view\n                    class=\"opera-item\"\n                    @tap=\"Delete({{index}})\"\n                    style=\"background-image:url('https://static.airbob.org/under-graduate/campus-card/delete.png');\"\n                  ></view>\n                </view>\n              </view>\n            </view>\n            <view class=\"divide\"></view>\n          </view>\n        </view>\n        <view class=\"rectangle\" @tap=\"addNewAddress\">+ 添加新地址</view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport { changeDefaultDorm } from \"@/api/common\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class selectRoom extends wepy.page {\n  data = {\n    rooms: []\n  };\n  components = {\n    BaseContainer\n  };\n  onShow() {\n    this.rooms = wepy.getStorageSync(\"selectRoom\")\n      ? wepy.getStorageSync(\"selectRoom\")\n      : [];\n    if (this.rooms.length === 1) {\n      this.rooms[0].default = true;\n      wepy.setStorageSync(\"selectRoom\", this.rooms);\n    }\n  }\n  methods = {\n    addNewAddress() {\n      this.$navigate({\n        url: \"./add-room\"\n      });\n    },\n    async changeDefult(index) {\n      wepy.showLoading();\n      let changeRoom = {};\n      const rowDefaultRoom = this.rooms.find(room => room.default);\n      Object.entries(rowDefaultRoom).forEach(([key, value]) => {\n        if (\n          [\"campus\", \"areaName\", \"buildingId\", \"bigRoom\", \"smallRoom\"].includes(\n            key\n          )\n        ) {\n          if (rowDefaultRoom[key] !== this.rooms[index][key]) {\n            if (key === \"campus\") {\n              changeRoom[key] = this.rooms[index][key] === 0 ? \"XL\" : \"SPL\";\n            } else {\n              changeRoom[key] = this.rooms[index][key];\n            }\n          }\n        }\n      });\n      if (Object.keys(changeRoom).length) {\n        const { studentId } =\n          wepy.getStorageSync(\"userInfo\") || wepy.getStorageSync(\"User\");\n        console.log(changeRoom);\n        const {\n          data: { data, success }\n        } = await changeDefaultDorm(changeRoom, studentId);\n        wepy.hideLoading();\n        if (success && data) {\n          this.rooms.forEach(item => {\n            item.default = false;\n          });\n          this.rooms[index].default = true;\n          wepy.setStorageSync(\"selectRoom\", this.rooms);\n          this.methods.useOnce(index);\n        } else {\n          wepy.showToast({\n            title: \"不知道为什么失败了呢~\",\n            icon: \"none\",\n            duration: 2000\n          });\n        }\n      } else {\n        this.methods.useOnce(index);\n      }\n    },\n    Delete(index) {\n      this.rooms.splice(index, 1);\n      wepy.setStorageSync(\"selectRoom\", this.rooms);\n    },\n    useOnce(index) {\n      const page = getCurrentPages();\n      const prevPage = page[page.length - 2];\n      prevPage.data.useOnce = index;\n      wepy.navigateBack({\n        delta: 1\n      });\n    },\n    edit(item, index) {\n      this.$navigate({\n        url: `./add-room?item=${JSON.stringify(item)}&&index=${index}`\n      });\n    }\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  // position relative\n  // min-height 100vh\n  font-family PingFangSC-Regular\n  font-size 32rpx\n  .room-container\n    .room-item-container\n      padding 20rpx 0 0 0\n      height 170rpx\n      font-family PingFangSC-Regular\n      color #353535\n      .room-item\n        padding 0 0 20rpx 0\n        margin 0 20rpx 0 20rpx\n        .room-name-container\n          display flex\n          height 97rpx\n          font-size 30rpx\n          .room-name\n            width 550rpx\n          .use-once\n            color #47cff5\n            border-radius 50rpx\n            width 150rpx\n            height 50rpx\n            line-height 50rpx\n            text-align center\n            font-size 28rpx\n            border 1rpx solid #47cff5\n        .opera-container\n          font-size 24rpx\n          height 33rpx\n          line-height 33rpx\n          display flex\n          .opera-default-container\n            width 550rpx\n            display flex\n            .opera-default\n              height 33rpx\n              width 33rpx\n              margin-right 10rpx\n              background-repeat no-repeat\n              background-size contain\n              background-position center\n          .opera\n            width 110rpx\n            margin 0 20rpx\n            display flex\n            justify-content space-between\n            .opera-item\n              height 33rpx\n              width 33rpx\n              background-repeat no-repeat\n              background-size contain\n              background-position center\n  .not-used\n    position fixed\n    color #9b9b9b\n    height 100vh\n    width 100vw\n    line-height 100vh\n    text-align center\n  .rectangle\n    position absolute\n    bottom 24rpx\n    width 90%\n    left 5%\n    height 85rpx\n    line-height 85rpx\n    text-align center\n    color #fff\n    background-color #47cff5\n    border-radius 50rpx\n.divide\n  width 750rpx\n  height 20rpx\n  background-color #f5f5f5\n</style>\n\n\n\n"
  },
  {
    "path": "src/components/baseContainer.wpy",
    "content": "<template>\n  <view>\n    <view wx:if=\"{{navStatus}}\">\n      <QyNavigation :title.sync=\"navTitle\" :background.sync=\"background\"></QyNavigation>\n    </view>\n    <QyModal :maskClosable=\"maskClosable\" width=\"500rpx\" :visible.sync=\"passwordModelStatus\">\n      <view slot=\"content\" class=\"bind-container\">\n        <input\n          class=\"bind-input\"\n          placeholder=\"{{passwordModelOptions.passwordModelProps ? placeholder:''}}\"\n          password=\"true\"\n          @input=\"passwordInput\"\n          placeholder-style=\"color: #999CA0\"\n        >\n        <button class=\"bind-button\" @tap.stop=\"bindPassword\" hover-class=\"button-click\">立即绑定</button>\n      </view>\n    </QyModal>\n    <QyModalGraduate width=\"500rpx\" :visible.sync=\"graduateModalStatus\">\n      <view slot=\"content\" class=\"bind-graduate-container\">\n        <view class=\"graduate-content\">\n          <view class=\"content-detail\">\n            <view>亲爱的{{name}}，</view>\n            <view>你已经离开南邮{{leaveDate}}天，</view>\n            <view>你所请求的数据</view>\n            <view>已经无法再次被刷新。</view>\n          </view>\n          <view class=\"content-detail\">\n            <view>记忆可以保留，</view>\n            <view>青春无法再来。</view>\n          </view>\n          <view>祝好。</view>\n        </view>\n        <button class=\"bind-button\" @tap.stop=\"closeGraduateModel\" hover-class=\"button-click\">知道了</button>\n      </view>\n    </QyModalGraduate>\n\n    <view>\n      <slot name=\"qy-content\"></slot>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport QyNavigation from \"./qy-navigation\";\nimport QyModal from \"./qy-modal\";\nimport QyModalGraduate from \"./qy-modal\";\nimport { changeSecretCode, changeSecretCodeLower } from \"@/api/common\";\nimport { getGraduateTime } from \"@/api/graduateMode\";\nimport { connect } from \"wepy-redux\";\n\n@connect({\n  graduateModalStatus(state) {\n    return state.graduateReducer.graduateModalStatus;\n  },\n  visitorModeStatus(state) {\n    return state.visitorReducer.visitorModeStatus;\n  }\n})\nexport default class BaseContainer extends wepy.component {\n  components = {\n    QyNavigation,\n    QyModal,\n    QyModalGraduate\n  };\n  data = {\n    password: \"\",\n    name: \"\",\n    graduateModelStatus: false,\n    passwordModelStatus: false,\n    placeholder: \"\",\n    navStatus: true,\n    leaveDate: parseInt((Date.now() - 1560960000000) / 86400000)\n  };\n  props = {\n    navTitle: {\n      type: String,\n      default: \"NJUPT\"\n    },\n    openPage: {\n      type: Boolean,\n      default: true\n    },\n    background: {\n      type: String,\n      default: \"#fff\"\n    },\n    passwordModelOptions: {\n      type: Object,\n      twoWay: true,\n      default: {\n        passwordModelProps: false,\n        placeholder: \"\",\n        bindInfo: { username: \"\", domainType: \"\" },\n        checkPassword: function() {\n          return null;\n        },\n        checkErrMsg: \"\",\n        refreshData: function() {\n          return null;\n        }\n      }\n    }\n  };\n  watch = {\n    passwordModelOptions(next) {\n      const { passwordModelProps } = next;\n      this.passwordModelStatus = passwordModelProps;\n      this.$apply();\n    },\n    openPage(next) {\n      this.navStatus = !next;\n      this.$apply();\n    },\n    // modal 显示的时候再接数据\n    graduateModalStatus(next) {\n      if (next) {\n        this.calcGraduateTime();\n      }\n    }\n  };\n  methods = {\n    passwordInput({ detail: { value } }) {\n      this.password = value;\n    },\n    closeGraduateModel() {\n      wepy.$store.dispatch({ type: `HIDE_GRADUATE_MODAL` });\n      wepy.navigateBack();\n      this.graduateModelStatus = false;\n    },\n    bindPassword() {\n      const {\n        bindInfo: { username, domainType },\n        checkPassword,\n        checkErrMsg\n      } = this.passwordModelOptions;\n      const bindPasswordInfo = [username, this.password, domainType];\n      if (checkPassword) {\n        if (checkPassword(this.password)) {\n          this.updatePasswordRequest(bindPasswordInfo);\n        } else {\n          wepy.showModal({\n            content: checkErrMsg,\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          });\n        }\n      } else {\n        this.updatePasswordRequest(bindPasswordInfo);\n      }\n    }\n  };\n  async updatePasswordRequest(bindPasswordInfo) {\n    wepy.showLoading({\n      title: \"正在更新密码\",\n      mask: true,\n      success: res => {}\n    });\n    const secretInfo = await changeSecretCode.apply(this, bindPasswordInfo);\n    wepy.hideLoading();\n    if (secretInfo.data && secretInfo.data.data) {\n      this.closePasswordModel();\n    } else {\n      wepy.showModal({\n        content: \"密码错误\",\n        confirmText: \"知道了\",\n        showCancel: false,\n        confirmColor: \"#353535\"\n      });\n    }\n  }\n  closePasswordModel() {\n    this.passwordModelStatus = false;\n    this.placeholder = \"\";\n    this.passwordModelOptions.refreshData();\n    this.$apply();\n  }\n  getCurrentPage() {\n    const pages = getCurrentPages();\n    const pageLength = pages.length;\n    return pageLength ? pages[pageLength - 1].route : null;\n  }\n  goBack() {\n    // 离开页面的打点\n    wepy.navigateBack();\n  }\n  async calcGraduateTime() {\n    const {\n      data: { data }\n    } = await getGraduateTime();\n    const date = new Date(data);\n    this.leaveDate = `${date.getFullYear()}-${date.getMonth() +\n      1}-${date.getDate()}`;\n  }\n  showVisitorTips() {\n    return wepy.showModal({\n      title: \"小贴士\",\n      content: \"游客模式下无法使用哦~\",\n      confirmColor: \"#47CFF5\",\n      showCancel: false,\n      confirmText: \"知道了\"\n    });\n  }\n  onLoad() {\n    const { placeholder } = this.passwordModelOptions;\n    this.placeholder = placeholder;\n    this.name =\n      wepy.getStorageSync(\"User\").name || wepy.getStorageSync(\"userInfo\").name;\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.bind-graduate-container\n  display flex\n  flex-direction column\n  background-image url('https://static.airbob.org/under-graduate/memory/modal.png')\n  background-repeat no-repeat\n  height 630rpx\n  border-radius 30rpx\n  background-size cover\n  .graduate-content\n    color #925800\n    font-size 26rpx\n    margin-bottom 130rpx\n    margin-top 72rpx\n    margin-left 81rpx\n    .content-detail\n      margin-bottom 33rpx\n  .bind-button\n    background-image linear-gradient(82deg, #dcbf86 0%, #be8d43 100%),linear-gradient(#f2f2f2, #f2f2f2)\n    text-align center\n    width 320rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 485rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n"
  },
  {
    "path": "src/components/qy-container.wpy",
    "content": "<!--\n下拉刷新函数形如：\nonPullRefresh(stop) {\n  return function() {\n    setTimeout(() => {\n      stop();\n    }, 1000);\n  };\n}\n原因是 wepy 传递 props 假如 不传递 会报错\n-->\n<template>\n  <view id=\"qy-container\">\n    <view @touchstart=\"touchStart\" @touchmove=\"touchMove\" @touchend=\"touchEnd\">\n      <view style=\"transform: translateY({{shift}}px); transition: all {{isFirst ? 0 : .3}}s\">\n        <view class=\"loading\" style=\"opacity: {{hasRefresh ? 1 : 0}}\">\n          <i class=\"weui-loading\"></i>\n        </view>\n        <view>\n          <slot name=\"qy-content\"></slot>\n        </view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\n\nexport default class extends wepy.component {\n  data = {\n    touchY: 0,\n    shift: -24,\n    ajaxEnd: true,\n    moved: false,\n    isTop: false,\n    canRefresh: true,\n    isFirst: true\n  };\n  props = {\n    refreshFunction: {\n      type: Function,\n      default: function() {\n        return null;\n      }\n    }\n  };\n  methods = {\n    touchMove(e) {\n      if (this.canRefresh && this.hasRefresh && this.ajaxEnd) {\n        const currentTouchY = e.changedTouches[0]\n          ? e.changedTouches[0].clientY\n          : this.touchY;\n        const differTouchY = currentTouchY - this.touchY;\n        if (differTouchY > 10) {\n          this.ajaxEnd = false;\n          // 注册下拉事件\n          this.moved = true;\n          if (differTouchY < 100) {\n            this.shift = differTouchY - 24;\n          }\n          this.refreshFunction(() => {\n            this.ajaxEnd = true;\n            this.shift = -24;\n            this.$apply();\n          });\n        }\n      }\n    },\n    touchStart(e) {\n      this.isFirst = false;\n      if (this.canRefresh && this.hasRefresh && this.ajaxEnd) {\n        this.touchY = e.touches[0].clientY;\n      }\n    },\n    touchEnd() {\n      if (this.ajaxEnd) {\n        this.closeLoading();\n      } else {\n        this.shift = 0;\n      }\n    },\n    whenScroll(e) {\n      this.canRefresh = e.detail.scrollTop === 0;\n    }\n  };\n  computed = {\n    hasRefresh() {\n      return typeof this.refreshFunction === \"function\";\n    }\n  };\n  closeLoading() {\n    this.shift = -24;\n  }\n  onPageScroll(e) {}\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n#qy-container\n  position relative\n  top 66px\n  left 0\n  height calc(100vh - 42px)\n  box-sizing border-box\n.loading\n  overflow hidden\n  text-align center\n  max-height 24px\n.weui-loading\n  margin 0 5px\n  width 20px\n  height 20px\n  display inline-block\n  vertical-align middle\n  animation spin 1s steps(12) infinite\n  background transparent url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=') no-repeat\n  background-size 100%\n  @keyframes spin\n    0%\n      transform rotate(0deg)\n    to\n      transform rotate(1turn)\n</style>\n"
  },
  {
    "path": "src/components/qy-datetime-select.wpy",
    "content": "<template>\n\t<view class=\"picker-container input\" style=\"{{style}}\">\n\t\t<picker class=\"item\" mode=\"date\" value=\"{{date}}\" start=\"{{startDate}}\" end=\"{{endDate}}\" @change.stop=\"dateChange\">\n\t\t\t<text class=\"show-text\">{{date}}</text>\n\t\t</picker>\n\t\t<picker class=\"item\" mode=\"time\" value=\"{{time}}\" start=\"{{startTime}}\" end=\"{{endTime}}\" @change.stop=\"begintimeChange\">\n\t\t\t<text class=\"show-text\">{{begintime}}</text>\n\t\t</picker>\n\t\t<text class=\"show-text item\">——</text>\n\t\t<picker mode=\"time\" value=\"{{time}}\" start=\"{{startTime}}\" end=\"{{endTime}}\" @change.stop=\"endtimeChange\">\n\t\t\t<text class=\"show-text\">{{endtime}}</text>\n\t\t</picker>\n\t</view>\n</template>\n<script>\nimport wepy from \"wepy\";\nexport default class QyDatetimeSelect extends wepy.component {\n  props = {\n    startDate: {\n      type: String,\n      default: this.formateDate(new Date(), \"yyyy-MM-dd\")\n    },\n    endDate: {\n      type: String,\n      default: \"2030-01-01\"\n    },\n    startTime: {\n      type: String,\n      default: \"00:00\"\n    },\n    endTime: {\n      type: String,\n      default: \"23:59\"\n    },\n    style: {\n      type: String,\n      default: \"\"\n    }\n  };\n  data = {\n    date: this.formateDate(new Date(), \"yyyy-MM-dd\"),\n    begintime: \"00:00\",\n    endtime: \"00:00\"\n  };\n  onLoad() {\n    this.date = this.startDate;\n    this.begintime = this.startTime;\n    this.endtime = this.startTime;\n    this.$emit(\"datetimeSelect\", this.date, this.begintime, this.endtime);\n  }\n  methods = {\n    dateChange(e) {\n      this.date = e.detail.value;\n      this.$emit(\"datetimeSelect\", this.date, this.begintime, this.endtime);\n    },\n    begintimeChange(e) {\n      this.begintime = e.detail.value;\n      this.$emit(\"datetimeSelect\", this.date, this.begintime, this.endtime);\n    },\n    endtimeChange(e) {\n      // end时间如果比begin小处理下。。\n      this.endtime = e.detail.value;\n      this.$emit(\"datetimeSelect\", this.date, this.begintime, this.endtime);\n    }\n  };\n  formateDate(date, fmt) {\n    {\n      const o = {\n        \"M+\": date.getMonth() + 1,\n        \"d+\": date.getDate(),\n        \"h+\": date.getHours(),\n        \"m+\": date.getMinutes(),\n        \"s+\": date.getSeconds(),\n        \"q+\": Math.floor((date.getMonth() + 3) / 3),\n        S: date.getMilliseconds()\n      };\n      if (/(y+)/.test(fmt))\n        fmt = fmt.replace(\n          RegExp.$1,\n          (date.getFullYear() + \"\").substr(4 - RegExp.$1.length)\n        );\n      for (let k in o)\n        if (new RegExp(\"(\" + k + \")\").test(fmt))\n          fmt = fmt.replace(\n            RegExp.$1,\n            RegExp.$1.length === 1\n              ? o[k]\n              : (\"00\" + o[k]).substr((\"\" + o[k]).length)\n          );\n      return fmt;\n    }\n  }\n}\n</script>\n<style lang=\"stylus\" scoped>\n@import \"../css/normal-input\";\n.picker-container\n\tdisplay flex\n\t.item\n\t\tmargin-right 28rpx\n\t.show-text\n\t\tfont-size 30rpx\n\t\tfont-family \"SimHei\"\n\t\tcolor rgb(84, 83, 83)\n\t\tline-height 72rpx\n</style>\n\n\n"
  },
  {
    "path": "src/components/qy-input.wpy",
    "content": "<!--\n-PlaceHolder 输入框的placeholder\n-Image 输入框的靠前的图片\n-putValue 输入框的值\n-inputType 输入框的input-type，默认number\n-verification 输入框靠后的图片\n-imageHeight,imageWidth,verificationImagewidth 图片的大小,微调用\n-verificationText 靠后图片上的内容\n-TapFunc 靠后图片的点击事件，尚未完成\n-->\n<template>\n  <view class=\"type-container\">\n    <view class=\"front-image-container\" style=\"height:{{imageHeight}};width:{{imageWidth}}\">\n      <image class=\"contain-image\" src=\"{{Image}}\" mode=\"aspectFit\">\n    </view>\n    <input\n      type=\"{{inputType}}\"\n      @input=\"putValue\"\n      class=\"place-to-type\"\n      placeholder=\"{{PlaceHolder}}\"\n    >\n    <view class=\"to-verification\" wx:if=\"{{verification}}\" @tap=\"Tap\">\n      <image\n        class=\"to-verification\"\n        mode=\"aspectFit\"\n        src=\"{{verification}}\"\n        style=\"width:{{verificationImagewidth}};\"\n      >\n      <view class=\"get-verification\">{{verificationText}}</view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\n\nexport default class Input extends wepy.component {\n  data = {\n    Value: \"\"\n  };\n  props = {\n    PlaceHolder: String,\n    Image: String,\n    imageHeight: String,\n    imageWidth: String,\n    verification: String,\n    verificationImagewidth: String,\n    verificationText: String,\n    inputValue: {\n      twoWay: true\n    },\n    index: Number,\n    inputType: {\n      default: \"number\",\n      type: String\n    },\n    TapFunc: {\n      type: Object\n    }\n  };\n  methods = {\n    putValue(e) {\n      this.inputValue = e.detail.value;\n    },\n    Tap(e) {\n      this.$emit(\"TapFunc\", e);\n    }\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\ninput\n  min-height 0rpx\n.type-container\n  position relative\n  margin 0 auto\n  width 100%\n  height 50rpx\n  line-height 40rpx\n  font-size 30rpx\n  display flex\n  justify-content flex-start\n  align-items center\n  border-bottom 1rpx solid #F2F2F2\n  .front-image-container\n    position relative\n    height 40rpx\n    width 26rpx\n    display flex\n    justify-content center\n    align-items center\n    .contain-image\n      flex 1\n  .place-to-type\n    font-size 28rpx\n    min-height 0rpx\n    height 50rpx\n    line-height 40rpx\n    padding-left 25rpx\n    width 100%\n  .to-verification\n    position relative\n    width 180rpx\n    height 50rpx\n    display flex\n    font-size 28rpx\n    align-items center\n    justify-content center\n    .get-verification\n      position absolute\n      top 0rpx\n      height 50rpx\n      color #fff\n      text-align center\n      display flex\n      align-items center\n      justify-content center\n</style>\n"
  },
  {
    "path": "src/components/qy-listitem.wpy",
    "content": "<template>\n\t<view class=\"item-container\" @tap.stop=\"navigate\">\n\t\t<image class=\"iconx\" src=\"{{item.thumb}}\" mode=\"widthFix\" />\n\t\t<view class=\"content\">\n\t\t\t<text>{{item.text}}</text>\n\t\t\t<view class=\"iconright\"></view>\n\t\t</view>\n\t</view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class extends wepy.component {\n  methods = {\n    navigate() {\n      wepy.navigateTo({\n        url: this.item.navigateURL\n      });\n    }\n  };\n  props = {\n    item: Object\n  };\n  onLoad() {}\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.item-container\n\tdisplay flex\n\theight 98rpx\n\tbackground-color rgb(255,255,255)\n\tposition relative\n\talign-items center\n\t&:last-child > .content\n\t\tborder-style none!important\n\t.iconx\n\t\twidth 38rpx\n\t\tmargin 0 45rpx 0 25rpx\n\t.iconright\n\t\twidth 35rpx\n\t\theight 35rpx\n\t\tbackground-image url(\"https://static.airbob.org/under-graduate/%E5%8F%B3%E7%AE%AD%E5%A4%B4.png\")\n\t\tbackground-position center\n\t\tbackground-repeat no-repeat\n\t\tbackground-size contain\n\t\tposition absolute\n\t\tleft 685rpx\n\t.content\n\t\twidth 100%\n\t\theight 96rpx\n\t\tdisplay flex\n\t\talign-items center\n\t\tmargin-right 20rpx\n\t\tborder-bottom 2rpx solid #E3E3E3\n\t.text\n\t\tfont-size 32rpx\n\t\tcolor #353535\n</style>\n"
  },
  {
    "path": "src/components/qy-modal.wpy",
    "content": "<!-- closable 点击蒙层是否允许关闭\nwidth Modal宽度\nheight Modal高度\nzIndex\nvisible Modal是否可见。通过触发组件内的open 和 close方法切换\nbackgroundColor 蒙层背景颜色 只支持rgba\ntop Modal距离顶部的距离\ncontainerClass 应用到Modal外部的class\nslot 提供head和content，一般建议使用content -->\n<template>\n  <view class=\"mask\" style=\"position:{{position}};background-color: {{backgroundColor}};z-index:{{zIndex}};visibility:{{visible?'visible':'hidden'}}\" @touchmove.stop=\"prevent\" @tap.stop=\"clickMask\">\n    <view class=\"modal-container {{containerClass}}\" style=\"width:{{width}};height:{{height}};top:{{top}}\" @tap.stop=\"prevent\">\n      <slot name=\"head\"></slot>\n      <view class=\"cancel\" wx:if=\"{{closable}}\" @tap.stop=\"cancelEvent\" />\n      <slot name=\"content\"></slot>\n    </view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  // 有的通用性没有考虑到，之后慢慢补充\n  export default class QyModal extends wepy.component {\n    props = {\n      closable: {\n        default: false,\n        type: Boolean\n      }, // 是否有右上角的关闭按钮\n      maskClosable: {\n        type: Boolean,\n        default: true\n      }, // 点击蒙层是否允许关闭\n      // onCancel: { //关闭Modal的回调\n      //   type: Function,\n      // },\n      position: {\n        default: \"fixed\",\n        type: String\n      },\n      containerClass: {\n        type: String,\n        default: \"\"\n      },\n      width: {\n        type: String,\n        default: \"600rpx\"\n      },\n      height: {\n        type: String, // Modal内容体高度\n        default: \"auto\"\n      },\n      zIndex: {\n        type: Number,\n        default: 30000\n      },\n      visible: {\n        type: Boolean, // Modal是否可见\n        default: false,\n        twoWay: true\n      },\n      backgroundColor: {\n        type: String, // 蒙层颜色 暂时只支持rgba没做转换。。。\n        default: \"rgba(0,0,0,0.6)\"\n      },\n      top: {\n        // Modal离顶部的距离\n        type: String,\n        default: \"370rpx\"\n      }\n    };\n    data = {};\n    events = {};\n    methods = {\n      clickMask() {\n        if (this.maskClosable) {\n          this.visible = false;\n          this.$apply();\n        }\n      },\n      prevent() {},\n      cancelEvent() {\n        this.visible = false;\n      }\n    };\n    open() {\n      // 调用该方法打开modal\n      this.visible = true;\n      this.$apply();\n    }\n    close() {\n      // 关闭\n      this.visible = false;\n      this.$apply();\n    }\n    onLoad() {}\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.mask\n  position fixed\n  width 100vw\n  height 100vh\n  .modal-container\n    left 50%\n    transform translateX(-50%)\n    position absolute\n    min-height 270rpx\n    background-color rgb(255, 255, 255)\n    border-radius 30rpx\n    .cancel\n       background-image url(\"https://static.airbob.org/under-graduate/grade/%E5%88%A0%E9%99%A4.png\")\n       width 34rpx\n       height 35rpx\n       cursor pointer\n       float right\n       background-size contain\n       margin 33rpx 29rpx 0 0\n</style>\n\n"
  },
  {
    "path": "src/components/qy-navigation.wpy",
    "content": "<!--\n- background 导航栏背景色\n- showBackBtn 强制显示回退按钮（除非是产生Bug的时候，不然不建议使用）\n- backBtnColor 回退按钮的颜色\n- title ios居中，android位于左边\n- titleColor 标题的颜色\n-->\n<template>\n  <view class=\"navigation-container\">\n    <view\n      class=\"nav-container\"\n      style=\"background: {{background}}; height: {{titleBarHeight + statusBarHeight}}px;\"\n    >\n      <view\n        class=\"nav-inner-container\"\n        style=\"top: {{statusBarHeight + (titleBarHeight - 32)/2}}px;\"\n      >\n        <view class=\"back-wrapper\" @tap=\"goBack\" wx:if=\"{{showBack || showBackBtn}}\">\n          <view class=\"back-icon\" style=\"color: {{backBtnColor}};\"></view>\n        </view>\n        <view class=\"nav-content\">\n          <view\n            class=\"{{textCenter?'title-ios':'title-android'}}\"\n            style=\"color: {{titleColor}}; padding-left: {{paddingLeft}}rpx;\"\n          >{{title}}</view>\n          <view wx-if=\"{{title.length < 1}}\">\n            <slot name=\"content\"></slot>\n          </view>\n        </view>\n      </view>\n    </view>\n    <view class=\"nav-block\" style=\"height: {{titleBarHeight + statusBarHeight}}px;\"></view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class extends wepy.component {\n  data = {\n    showBack: false,\n    statusBarHeight: 0, //状态栏高度\n    textCenter: true,\n    titleBarHeight: 44, //ios默认44，android默认48\n    paddingLeft: 0 //ios默认0，android首页30rpx，子页面80rpx\n  };\n  methods = {\n    goBack() {\n      wepy.navigateBack();\n    }\n  };\n  props = {\n    showBackBtn: {\n      default: false,\n      type: Boolean\n    },\n    backBtnColor: {\n      default: \"#000\",\n      type: String\n    },\n    background: {\n      default: \"#fff\",\n      type: String\n    },\n    title: {\n      default: \"\",\n      type: String\n    },\n    titleColor: {\n      default: \"#000\",\n      type: String\n    }\n  };\n  computed = {\n    paddingLeft() {\n      if (!this.textCenter) {\n        if (this.showBack || this.showBackBtn) {\n          return 80;\n        } else {\n          return 30;\n        }\n      } else {\n        return 0;\n      }\n    }\n  };\n  setTaskStyle() {\n    this.statusBarHeight = wepy.getSystemInfoSync().statusBarHeight;\n    if (wepy.getSystemInfoSync().system.split(\" \")[0] !== \"iOS\") {\n      this.textCenter = false;\n      this.titleBarHeight = 48;\n    }\n    this.$apply();\n  }\n  onLoad() {\n    this.setTaskStyle();\n    if (getCurrentPages().length > 1) {\n      this.showBack = true;\n      this.$apply();\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.navigation-container\n  width 100%\n  display flex\n  flex-direction column\n  .nav-container\n    position fixed\n    width 100%\n    display flex\n    top 0\n    z-index 10000\n    .nav-inner-container\n      position absolute\n      width 100%\n      display flex\n      align-items center\n      height 32px\n      .back-wrapper\n        position absolute\n        width 60rpx\n        left 30rpx\n        text-align center\n        .back-icon\n          border-left 5rpx solid\n          border-bottom 5rpx solid\n          width 24rpx\n          height 24rpx\n          transform rotate(45deg)\n      .nav-content\n        width 100%\n        font-family PingFangSC-Regular\n        .title-ios\n          font-weight bold\n          text-align center\n          font-size 30rpx\n        .title-android\n          font-weight normal\n          text-align left\n          font-size 34rpx\n  .nav-block\n    width 100%\n</style>\n"
  },
  {
    "path": "src/components/qy-popup.wpy",
    "content": "<template>\n  <view\n    class=\"pop-up-container\"\n    style=\"{{ displayStatus && !openPage ? 'display:flex' : 'display:none'}}\"\n  >\n    <view class=\"pop-up-wrapper\">\n      <view class=\"close-pop-up\" @tap=\"closeThePopup\">\n        <view class=\"close-wrapper\">\n          <image src=\"https://static.airbob.org/under-graduate/popup/close.png\">\n        </view>\n      </view>\n      <view class=\"pop-up-body\" @tap=\"navToWebview\">\n        <image src=\"https://static.airbob.org/under-graduate/popup/window.png\">\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class QyPopUp extends wepy.component {\n  props = {\n    link: String,\n    openPage: Boolean\n  };\n  data = {\n    displayStatus: true\n  };\n  methods = {\n    navToWebview() {\n      wepy.navigateTo({\n        url: `../others-page/pages/display-webview?link=${this.link}`\n      });\n      this.displayStatus = false;\n      wepy.setStorageSync(\"annual\", false);\n    },\n    closeThePopup() {\n      this.displayStatus = false;\n      wepy.setStorageSync(\"annual\", false);\n      this.$emit(\"changeAnnualStatus\");\n    }\n  };\n  onLoad() {\n    this.displayStatus = wepy.getStorageSync(\"annual\") ? true : false;\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.pop-up-container\n  position absolute\n  top 0\n  bottom 0\n  right 0\n  left 0\n  z-index 500\n  display flex\n  justify-content center\n  align-items center\n  background-color rgba(0, 0, 0, 0.4)\n  overflow hidden\n  .pop-up-wrapper\n    width 100vw\n    height 100vh\n    display flex\n    flex-direction column\n    justify-content center\n    align-items center\n    .close-pop-up\n      width 460rpx\n      height 50rpx\n      display flex\n      justify-content flex-end\n      margin-bottom 10rpx\n      .close-wrapper\n        image\n          width 50rpx\n          height 50rpx\n    .pop-up-body\n      image\n        width 460rpx\n        height 700rpx\n</style>\n"
  },
  {
    "path": "src/components/qy-swiper.wpy",
    "content": "<style lang=\"stylus\" scoped>\n.swiper-wrap {\n  display: inline-block;\n  width: 100vw;\n}\n.container {\n  width: 750rpx;\n  height: 400rpx;\n  margin: 20rpx auto;\n}\n.slide-image {\n  height: 400rpx;\n  width: 750rpx\n}\n.dots {\n  display: flex;\n  flex-direction: row;\n  justify-content: space-between;\n  height: 12rpx;\n  margin: 16rpx auto;\n}\n.dot {\n  height: 12rpx;\n  width: 12rpx;\n  background-color: #353535;\n  border-radius: 100rpx;\n  margin: auto\n}\n.activeDot {\n  height: 12rpx;\n  width: 12rpx;\n  background-color: #353535;\n  border-radius: 100rpx;\n  margin: auto\n  -webkit-animation: moveDot 2s\n}\n@-webkit-keyframes moveDot {\n  0% {\n    width 12rpx\n  }\n  25% {\n    width 54rpx\n  }\n  75% {\n    width 54rpx\n  }\n  100% {\n    width 12rpx\n  }\n}\n</style>\n\n<template>\n  <view class=\"swiper-wrap\">\n    <swiper autoplay=\"true\" interval=\"2000\" duration=\"500\" class=\"container\" bindchange=\"listenChange\">\n      <block wx:for=\"{{imgUrls}}\" wx:key=\"id\">\n        <swiper-item>\n          <image src=\"{{item.url}}\" class=\"slide-image\" catchtap=\"goToAds({{ item.adId }})\"/>\n        </swiper-item>\n      </block>\n    </swiper>\n    <view class=\"dots\" style=\"width: {{ imgUrls.length * 60 + 'rpx' }}\">\n      <block wx:for=\"{{imgUrls}}\" wx:key=\"id\" wx:index=\"index\">\n        <view style=\"width: 60rpx\">\n          <view class=\"{{item.on}}\"></view>\n        </view>\n      </block>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\n\nexport default class swiper extends wepy.component {\n  data = {\n    animationDot: {}\n  };\n\n  props = {\n    imgUrls: {\n      type: Array\n    }\n  };\n\n  methods = {\n    bindChange(e) {\n      this.$emit(\"change\", 0);\n    },\n    listenChange(event) {\n      for (let item of this.imgUrls) {\n        item.on = \"dot\";\n      }\n      this.imgUrls[event.detail.current].on = \"activeDot\";\n      this.$apply();\n    },\n    goToAds(adId) {\n      wepy.navigateTo({\n        url: \"../others-page/pages/advertisement?adId=\" + adId\n      });\n    }\n  };\n}\n</script>\n"
  },
  {
    "path": "src/components/qy-tip.wpy",
    "content": "<!--\n- on 控制提示开关\n- LastTime 控制tips显示时间，单位毫秒\n-->\n<template>\n  <view class=\"tips-container\" style=\"z-index:{{showIndex}}\">\n    <view class=\"tip-content\" animation=\"{{animationData}}\" on=\"{{on}}\">{{content}}</view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\n\nexport default class QyTip extends wepy.component {\n  props = {\n    content: String,\n    on: {\n      default: false,\n      twoWay: true\n    },\n    LastTime: {\n      default: 1500\n    }\n  };\n  watch = {\n    on(curVal, oldVal) {\n      this.$apply();\n      const that = this;\n      if (curVal === true) {\n        that.showIndex = 999999;\n        let animation = wepy.createAnimation({\n          duration: 500\n        });\n        animation.opacity(1).step();\n        that.animationData = animation.export();\n        that.$apply();\n        setTimeout(() => {\n          animation.opacity(0).step();\n          that.animationData = animation.export();\n          that.$apply();\n          that.on = false;\n          that.animationData = {};\n          that.$apply();\n          // clearTimeout(TimeOut);\n        }, that.LastTime);\n        setTimeout(() => {\n          that.showIndex = -999999;\n          that.$apply();\n        }, Number(that.LastTime) * 2);\n      }\n    }\n  };\n  data = {\n    animationData: {},\n    animationOn: false,\n    showIndex: -999999\n  };\n  onLoad() {}\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.tips-container\n  position fixed\n  width 100%\n  height 100%\n  display flex\n  justify-content center\n  align-items center\n  text-align center\n  .tip-content\n    position relative\n    margin 0 auto\n    max-width 600rpx\n    padding 12rpx 40rpx\n    background #000\n    opacity 0.7\n    border-radius 15rpx\n    display flex\n    justify-content center\n    align-items center\n    font-size 28rpx\n    flex-direction column\n    color #fff\n    opacity 0\n</style>\n"
  },
  {
    "path": "src/css/global-style.styl",
    "content": ".hide-page\r\n  position fixed\r\n  width 100%\r\n  height 100%\r\n  background rgba(0, 0, 0, 0.5)\r\n  display flex\r\n  justify-content center\r\n  align-items center\r\n  .protocol-content\r\n    position relative\r\n    margin 0 auto\r\n    width 600rpx\r\n    padding 20rpx\r\n    background #fff\r\n    border-radius 30rpx\r\n    display flex\r\n    justify-content center\r\n    align-items center\r\n    font-size 28rpx\r\n    flex-direction column"
  },
  {
    "path": "src/css/loading.styl",
    "content": ".boxLoading\r\n  width 100rpx\r\n  height 100rpx\r\n  margin 0 auto\r\n  position relative\r\n  left 0\r\n  right 0\r\n  top 0\r\n  bottom 0\r\n  &:before\r\n    content ''\r\n    width 100rpx\r\n    height 10rpx\r\n    background #000\r\n    opacity 0.1\r\n    position absolute\r\n    top 108rpx\r\n    left 0\r\n    border-radius 50%\r\n    animation shadow 0.5s linear infinite\r\n    overflow hidden\r\n  &:after\r\n    content ''\r\n    width 100rpx\r\n    height 100rpx\r\n    background #47CFF5\r\n    animation animate 0.5s linear infinite\r\n    position absolute\r\n    top 0\r\n    left 0\r\n    border-radius 3px\r\n    overflow hidden\r\n\r\n@keyframes animate\r\n  17%\r\n    border-bottom-right-radius 3px\r\n  25%\r\n    transform translateY(9px) rotate(22.5deg)\r\n  50%\r\n    transform translateY(18px) scale(1, 0.9) rotate(45deg)\r\n    border-bottom-right-radius 40px\r\n  75%\r\n    transform translateY(9px) rotate(67.5deg)\r\n  100%\r\n    transform translateY(0) rotate(90deg)\r\n\r\n@keyframes shadow\r\n  0%,\r\n  100%\r\n    transform scale(1, 1)\r\n  50%\r\n    transform scale(1.2, 1)"
  },
  {
    "path": "src/css/normal-input.styl",
    "content": ".input\r\n\tborder-radius 30rpx\r\n\tbackground-color rgb(238, 238, 238)\r\n\twidth 545rpx\r\n\theight 72rpx\r\n\tpadding 0 30rpx\r\n\tbox-sizing border-box\r\n\t.placeholder\r\n\t\tfont-size 30rpx\r\n\t\tfont-family \"SimHei\"\r\n\t\tcolor rgb(84, 83, 83)"
  },
  {
    "path": "src/css/search-input.styl",
    "content": ".search-input\r\n  position relative\r\n  z-index 0\r\n  height 60rpx\r\n  box-sizing border-box\r\n  padding-left 60rpx\r\n  background #F5F5F5\r\n  width 630rpx\r\n  border-radius 100rpx\r\n  color: #353535\r\n  display inline-block\r\n"
  },
  {
    "path": "src/edu-admin-page/components/card.wpy",
    "content": "<template>\r\n  <view class=\"container\">\r\n    <view class=\"head\" style=\"background-image:url({{bg}});\">\r\n      <image class=\"paper\" src=\"{{showbg}}\" mode=\"widthFix\"/>\r\n      <view class=\"right\">\r\n        <text class=\"head-text\">{{item.courseName}}</text>\r\n        <text class=\"head-text\">指导老师：{{item.courseTeacher}}</text>\r\n      </view>\r\n    </view>\r\n    <view class=\"foot\">\r\n      <view class=\"foot-left\">\r\n        <text class=\"text\">Time</text>\r\n        <text class=\"text\">{{item.examDate}}</text>\r\n        <text class=\"text\">{{item.examTime}}</text>\r\n      </view>\r\n      <view class=\"foot-right\">\r\n        <text class=\"text\">Place</text>\r\n        <text class=\"text\">{{item.examPosition}}</text>\r\n      </view>\r\n    </view>\r\n  </view>\r\n</template>\r\n\r\n<script>\r\nimport wepy from \"wepy\";\nexport default class extends wepy.component {\n  props = {\n    item: Object,\n    bg: String,\n    showbg: String\n  };\n}\n</script>\r\n<style lang=\"stylus\" scoped>\r\n.container\r\n  width 605rpx\r\n  height 275rpx\r\n  box-shadow 0rpx 3rpx 7rpx 0rpx rgba(0, 0, 0, 0.35)\r\n  border-radius 30rpx\r\n  margin-bottom 29rpx\r\n  position relative\r\n  display flex\r\n  flex-direction column\r\n  .head\r\n    background-repeat no-repeat\r\n    background-size 605rpx\r\n    height 180rpx\r\n    width 100%\r\n    padding 28rpx 24rpx 0 24rpx\r\n    box-sizing border-box\r\n    .right\r\n      display flex\r\n      flex-direction column\r\n      align-items flex-end\r\n    .paper\r\n      width 92rpx\r\n      position absolute\r\n      top 28rpx\r\n      left 41rpx\r\n    .head-text\r\n      max-width 545rpx\r\n      font-size 34rpx\r\n      font-family 'SimHei'\r\n      color rgb(88, 88, 88)\r\n      overflow hidden\r\n      text-overflow ellipsis\r\n      white-space nowrap\r\n  .foot\r\n    display flex\r\n    flex-direction row\r\n    justify-content space-between\r\n    .text\r\n      font-size 26rpx\r\n      color rgb(88, 88, 88)\r\n      line-height 1.192\r\n    .foot-left\r\n      display flex\r\n      flex-direction column\r\n      margin-left 37rpx\r\n    .foot-right\r\n      display flex\r\n      flex-direction column\r\n      margin-right 37rpx\r\n</style>\r\n"
  },
  {
    "path": "src/edu-admin-page/components/grade-card.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <view class=\"head\" @tap.stop=\"toggleShow\">{{result.title}}</view>\n    <view class=\"list-container\" style=\"{{show?'':'display:none'}}\">\n      <view class=\"grade-item\">\n        <text class=\"grade-text\">考试年份：{{result.year}}</text>\n        <text class=\"grade-text\">考试学期：{{result.term}}</text>\n        <text class=\"grade-text\">准考证号：{{result.number}}</text>\n        <text class=\"grade-text\">考试成绩：{{result.result}}</text>\n      </view>\n    </view>\n  </view>\n</template>\n<script>\nimport wepy from \"wepy\";\nexport default class GradeCard extends wepy.component {\n  props = {\n    result: Object,\n    show: {\n      default: false,\n      type: Boolean\n    }\n  };\n  methods = {\n    toggleShow() {\n      this.$emit(\"showGradeChange\", this.$index);\n    }\n  };\n}\n</script>\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  align-items center\n  margin-top 31rpx\n  min-height auto !important\n  .head\n    font-size 30rpx\n    font-family 'SimHei'\n    color rgb(52, 177, 244)\n    line-height 1.2\n    height 100rpx\n    width 545rpx\n    box-shadow 0rpx 3rpx 13.8rpx 6.2rpx rgba(50, 203, 240, 0.35)\n    border-radius 30rpx\n    background-color rgb(255, 255, 255)\n    z-index 40\n    display flex\n    align-items center\n    justify-content center\n  .list-container\n    border-radius 30rpx\n    background-color rgb(255, 255, 255)\n    width 605rpx\n    z-index 34\n    margin -44rpx 0 0 0\n    padding 71rpx 0 31rpx\n    .grade-item\n      width 520rpx\n      height auto\n      display flex\n      flex-direction column\n      padding-left 57rpx\n      margin-bottom 6rpx\n      .grade-text\n        font-size 29rpx\n        margin-bottom 6rpx\n        font-family 'SimHei'\n        color rgb(53, 53, 53)\n        line-height 1.458\n  .none\n    margin-bottom 31rpx\n</style>\n\n"
  },
  {
    "path": "src/edu-admin-page/components/subject-card.wpy",
    "content": "<template>\n\t<view class=\"container {{isFinished ?'finished-container':''}}\" style=\"{{isFinished&&!show?'height:86rpx;':''}}\" >\n\t\t<view class=\"unfinish\" wx:if=\"{{!isFinished}}\">\n      <movable-area>\n        <movable-view damping=\"200\" x=\"{{distanceX}}\" out-of-bounds=\"true\" direction=\"horizontal\" inertia=\"{{true}}\" @change.stop=\"movableViewChange\" @touchend.stop=\"movableViewTouchEnd\">\n          <view class=\"left\">\n            <view class=\"head\">{{item.subject}}</view>\n            <view class=\"list\">\n              <view class=\"list-text\">考试时间：{{item.time}}</view>\n              <view class=\"list-text\">考试地点：{{item.place}}</view>\n              <view class=\"list-text\">任课老师：{{item.teacher}}</view>\n            </view>\n          </view>\n          <view class=\"remain\" style=\"color: {{item.remain===0 ? '#FF3939':item.remain === 1 ?'#FFB660':'#89D590'}}\">{{item.remain===0 ? \"今天\":item.remain === 1 ? \"明天\":item.remain+'天后'}}</view>\n        </movable-view>\n      </movable-area>\n      <view hidden=\"{{isFinished}}\" class=\"hidden-btn\" @tap.stop=\"down\" data-originIndex=\"{{item.originIndex}}\" data-courseCode=\"{{item.courseCode}}\" data-courseTeacher=\"{{item.teacher}}\">删除</view>\n    </view>\n    <view style=\"{{isFinished&&!show?'height:86rpx;':''}}\" class=\"finish\" @tap.stop=\"toggle\" wx:else>\n      <view class=\"left\">\n        <view class=\"head\">{{item.subject}}</view>\n        <view class=\"list\" hidden=\"{{isFinished && !show}}\">\n          <view class=\"list-text\">考试时间：{{item.time}}</view>\n          <view class=\"list-text\">考试地点：{{item.place}}</view>\n          <view class=\"list-text\">任课老师：{{item.teacher}}</view>\n        </view>\n      </view>\n      <!-- <image class=\"up\" src=\"https://static.airbob.org/under-graduate/%E5%80%92%E8%AE%A1%E6%97%B6/%E7%AE%AD%E5%A4%B4.png\" @tap.stop=\"up\" data-originIndex=\"{{item.originIndex}}\" data-courseCode=\"{{item.courseCode}}\" data-courseTeacher=\"{{item.teacher}}\"/> -->\n    </view>\n\t</view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\n// 两种状态是否已经结束\nexport default class SubjectCard extends wepy.component {\n  props = {\n    item: Object,\n    isFinished: Boolean,\n    bg: {\n      type: String,\n      default: \"\"\n    },\n    show: {\n      type: Boolean, // 已经完成的考试隐藏详情。只有isFinished为true时生效\n      default: false\n    },\n    distanceX: {\n      type: Number,\n      default: 0\n    }\n  };\n  methods = {\n    async movableViewTouchEnd(e) {\n      this.$emit(\"movableViewTouchEnd\");\n    },\n    async movableViewChange(e) {\n      const { x, source } = e.detail;\n      const alloweds = [\"touch\", \"out-of-bounds\"];\n      if (alloweds.includes(source)) {\n        this.$emit(\n          \"movableViewChange\",\n          this.$index,\n          x < -60 ? -120 + x : 10 - x\n        );\n      }\n    },\n    async toggle(e) {\n      this.$emit(\"showchange\", this.$index);\n    },\n    async up(e) {\n      const res = await wepy.showModal({\n        content: \"是否恢复该课程？\",\n        confirmColor: \"#47CFF5\"\n      });\n      if (res.confirm) {\n        this.$emit(\n          \"up\",\n          e.target.dataset.originindex,\n          e.target.dataset.coursecode,\n          e.target.dataset.courseteacher\n        );\n      }\n    },\n    async down(e) {\n      const res = await wepy.showModal({\n        content: \"是否删除该课程？\",\n        confirmColor: \"#47CFF5\"\n      });\n      if (res.confirm) {\n        // 把课程号和originIndex发到Page中\n        this.$emit(\n          \"down\",\n          e.target.dataset.originindex,\n          e.target.dataset.coursecode,\n          e.target.dataset.courseteacher\n        );\n      }\n    }\n  };\n}\n</script>\n<style lang=\"stylus\" scoped>\n.finished-container\n  padding-top 23rpx\n.container\n  width 725rpx\n  height 242rpx\n  .finish\n    display flex\n    align-items center\n    justify-content space-between\n    // height 90%\n    background-color #f5f5f5\n    border-radius 30rpx\n    width 562rpx\n    padding 0 50rpx 0 50rpx\n    margin 0 auto\n    .left\n      .list\n        .list-text\n          line-height 40rpx\n          font-size 24rpx\n          margin 10rpx 0rpx\n      .head\n        font-size 35rpx\n        line-height 50rpx\n        margin 10px auto\n    .up\n      width 39rpx\n      height 36rpx\n    .hidden-btn\n      background-color #FF3B30\n      color #ffffff\n      height 260rpx\n      width 260rpx\n      line-height 51rpx\n      text-align center\n      border none\n      font-size 40rpx\n  .unfinish\n    display flex\n    align-items center\n    justify-content space-between\n    width 100vw\n    height 100%\n    // border-radius 30rpx\n    overflow hidden\n    movable-area\n      height 242rpx\n      width 727rpx\n      movable-view\n        height 242rpx\n        width 727rpx\n        background-color #ffffff\n        display flex\n        padding-left 50rpx\n        align-items center\n        justify-content space-between\n        .list\n          .list-text\n            line-height 40rpx\n            font-size 24rpx\n            margin 10rpx 0rpx\n        .left\n          .head\n            font-size 35rpx\n            line-height 50rpx\n            margin 10px auto\n        .up\n          width 39rpx\n          height 36rpx\n        .remain\n          font-size 40rpx\n          margin-right 60rpx\n    .hidden-btn\n      background-color #FF3B30\n      color #ffffff\n      height 242rpx\n      width 243rpx\n      line-height 242rpx\n      text-align center\n      border none\n      font-size 40rpx\n</style>\n\n"
  },
  {
    "path": "src/edu-admin-page/pages/check-grade.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"等级考试\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"head\">\n          <image\n            class=\"icon\"\n            src=\"https://static.airbob.org/under-graduate/grade/%E7%AD%89%E7%BA%A7.png\"\n            mode=\"widthFix\"\n          >\n        </view>\n        <repeat for=\"{{gradeExam}}\" key=\"index\" index=\"index\" item=\"item\">\n          <GradeCard :result.sync=\"item\" :show.sync=\"shows[index]\"/>\n        </repeat>\n        <!-- <view class=\"foot\">\n          <text class=\"tips\">没有查到考试成绩？试试</text>\n          <button class=\"button-enter\" hover-class=\"button-enter-en\" @tap.stop=\"enter\">手动输入准考证号&姓名</button>\n        </view>-->\n        <QyModal1>\n          <view slot=\"content\" class=\"enter-container\">\n            <view class=\"section1\">\n              <input\n                placeholder=\"{{placeholderList[0]}}\"\n                type=\"number\"\n                class=\"input\"\n                placeholder-class=\"placeholder\"\n                @input=\"updateNumber\"\n              >\n            </view>\n            <view class=\"section2\">\n              <input\n                placeholder=\"{{placeholderList[1]}}\"\n                class=\"input\"\n                placeholder-class=\"placeholder\"\n                @input=\"updateName\"\n              >\n            </view>\n            <button class=\"result-button\" hover-class=\"result-button-enter\" @tap.stop=\"checkResult\">查询成绩</button>\n            <text class=\"tips\">目前仅支持CET46</text>\n          </view>\n        </QyModal1>\n        <QyModal2 :closable.sync=\"close\">\n          <view slot=\"head\" class=\"head-container\">\n            <image\n              class=\"shadow shadow-left\"\n              src=\"https://static.airbob.org/under-graduate/grade/%E5%B7%A6%E9%98%B4%E5%BD%B1.png\"\n              mode=\"widthFix\"\n            >\n            <view class=\"title-list\">\n              <text class=\"title-1\">{{manualSearchResult.rank}}</text>\n              <text class=\"title-2\">考 试 成 绩</text>\n            </view>\n            <image\n              class=\"shadow shadow-right\"\n              src=\"https://static.airbob.org/under-graduate/grade/%E5%8F%B3%E9%98%B4%E5%BD%B1.png\"\n              mode=\"widthFix\"\n            >\n          </view>\n          <view slot=\"content\">\n            <view class=\"result-container\">\n              <view class=\"result-list\">\n                <text>姓名:{{manualSearchResult.name}}</text>\n                <text>准考证号：{{manualSearchResult.number}}</text>\n                <text>考试级别：{{manualSearchResult.rank}}</text>\n                <text>总分：{{manualSearchResult.total}}</text>\n                <view>\n                  <text>听力：{{manualSearchResult.listen}}</text>\n                  <text>阅读：{{manualSearchResult.reading}}</text>\n                </view>\n                <text>翻译与写作：{{manualSearchResult.write}}</text>\n                <text>口试准考证号：{{manualSearchResult.speakNumber}}</text>\n                <text>口试等级：{{manualSearchResult.speakRank}}</text>\n              </view>\n            </view>\n          </view>\n        </QyModal2>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport GradeCard from \"../components/grade-card\";\nimport QyModal from \"../../components/qy-modal\";\nimport { getUserGradeTest } from \"@/api/education\";\nimport { mockGetUserGradeTest } from \"@/mock/education\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class CheckGrade extends wepy.page {\n  // todo 关闭Modal后清除data中的输入状态\n  config = {\n    backgroundColor: \"#E5F4FB\",\n    navigationBarTitleText: \"等级考试\"\n  };\n  data = {\n    gradeExam: [],\n    shows: [],\n    number: \"\",\n    name: \"\",\n    manualSearchResult: {\n      name: \"小程序\",\n      number: \"1201201201023131\",\n      rank: \"英语六级\",\n      total: 456,\n      listen: 120,\n      reading: 200,\n      write: 136,\n      speakNumber: \"--\",\n      speakRank: \"--\"\n    },\n    close: true,\n    placeholderList: [\"\", \"\"],\n    visitorModeStatus: false\n  };\n  components = {\n    GradeCard,\n    QyModal1: QyModal,\n    QyModal2: QyModal,\n    BaseContainer\n    // QyNav,\n    // QyContainer\n  };\n  mixins = [JudgeStatus];\n  events = {\n    showGradeChange: index => {\n      this.shows[index] = !this.shows[index];\n    }\n  };\n  methods = {\n    enter() {\n      this.placeholderList = [\"在此输入四六级准考证号\", \"在此输入姓名\"];\n      this.$invoke(\"QyModal1\", \"open\");\n    },\n    updateName(e) {\n      this.name = e.detail.value;\n    },\n    updateNumber(e) {\n      this.number = e.detail.value;\n    },\n    checkResult() {\n      // this.$invoke(\"QyModal1\", \"close\");\n      // this.$invoke(\"QyModal2\", \"open\");\n    }\n  };\n  onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name).then(async () => {\n      const res = !this.visitorModeStatus\n        ? await getUserGradeTest()\n        : await mockGetUserGradeTest();\n      if (res.data) {\n        const examData = res.data.data.gradeExam;\n        this.shows = new Array(examData.length).fill(false);\n        this.gradeExam = examData.map(item => {\n          return {\n            title: item.name,\n            year: item.year,\n            term: item.term,\n            number: item.certno,\n            result: item.score\n          };\n        });\n      }\n      this.$apply();\n    });\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n@import '../../css/normal-input'\n.container\n  background-color rgb(229, 244, 251)\n  display flex\n  align-items center\n  flex-direction column\n  width 100%\n  min-height calc(100vh - 66px)\n  .head\n    background-image url('https://static.airbob.org/under-graduate/grade/%E6%B3%A2%E6%B5%AA.png')\n    background-size contain\n    height 320rpx\n    width 100%\n    display flex\n    justify-content center\n    padding-left 10rpx\n    padding-right 10rpx\n    .icon\n      width 195rpx\n      margin-top 33rpx\n  .foot\n    margin-top 112rpx\n    width 520rpx\n    padding-bottom 50rpx\n    display flex\n    flex-direction column\n    align-items center\n    .tips\n      font-size 24rpx\n      font-family 'SimHei'\n      color rgb(136, 135, 139)\n    .button-enter\n      margin-top 34rpx\n      font-size 30rpx\n      font-family 'SimHei'\n      color rgb(255, 255, 255)\n      line-height 62rpx\n      text-align center\n      border-radius 30rpx\n      background-color rgb(52, 177, 244)\n      width 465rpx\n      height 62rpx\n&:after, border none\n  .button-enter-en\n    background-color rgba(52, 177, 244, 0.6)\n.head-container\n  position absolute\n  top -125rpx\n  width 605rpx\n  overflow hidden\n  .shadow\n    width 132rpx\n    z-index -10\n  .shadow-left\n    position absolute\n    top 77rpx\n  .shadow-right\n    position absolute\n    top 77rpx\n    left 470rpx\n  .title-list\n    font-family 'SimHei'\n    color rgb(255, 255, 255)\n    margin 0 auto\n    width 521rpx\n    height 127rpx\n    width 521rpx\n    background-color rgb(65, 160, 249)\n    display flex\n    flex-direction column\n    align-items center\n    justify-content space-around\n    background-color rgb(65, 160, 249)\n    .title1\n      font-size 18rpx\n    .title2\n      font-size 24rpx\n.enter-container\n  background-color rgb(255, 255, 255)\n  width 605rpx\n  height 426rpx\n  display flex\n  border-radius 30rpx\n  flex-direction column\n  align-items center\n  .section1\n    margin-top 52rpx\n  .section2\n    margin 28rpx 0 69rpx\n  .tips\n    font-size 24rpx\n    font-family 'SimHei'\n    color rgb(131, 128, 128)\n    margin-top 24rpx\n  .result-button\n    background-color rgb(134, 222, 243)\n    width 466rpx\n    height 57rpx\n    line-height 57rpx\n    text-align center\n    font-size 30rpx\n    font-family 'SimHei'\n    border-radius 45rpx\n    color rgb(255, 255, 255)\n  .result-button-enter\n    background-color rgba(134, 222, 243, 0.6)\n.result-container\n  height 515rpx\n  display flex\n  flex-direction column\n  align-items center\n  justify-content center\n  .result-list\n    font-size 30rpx\n    font-family 'SimHei'\n    color rgb(0, 0, 0)\n    display flex\n    flex-direction column\n    width 487rpx\n    margin-left 61rpx\n    height 426rpx\n    justify-content space-between\n</style>\n"
  },
  {
    "path": "src/edu-admin-page/pages/course.wpy",
    "content": "<template>\n<BaseContainer :navTitle.sync=\"navTitle\" :passwordModelOptions.sync=\"passwordModelOptions\">\n  <view slot=\"qy-content\">\n    <view class=\"course\">\n      <view class=\"hide-page\" @tap.stop=\"hideDetailCourse\" hidden=\"{{swiperHide}}\">\n        <scroll-view scroll-x=\"{{detailCourseScroll}}\">\n          <view class=\"swiper-thing\">\n            <view class=\"swiper-item\" style=\"background:{{swiperCourse[0].bgc}};\" @tap.stop=\"errorBind\" @touchstart=\"startTouching\" @touchend=\"endTouching\" animation=\"{{firstCourseAnimation}}\">\n              <view class=\"course-container\">\n                <view class=\"course-delete\" wx:if=\"{{swiperCourse[0].md5}}\" @tap=\"deleteAddCourse\" data-md5=\"{{swiperCourse[0].md5}}\">× 移除</view>\n                <view class=\"course-name\">{{swiperCourse[0].name}}</view>\n                <view class=\"course-info\">\n                  <view class=\"detail-info\"><span>教师：</span>{{swiperCourse[0].teacher}}</view>\n                  <view class=\"detail-info\"><span>教室：</span>{{swiperCourse[0].locale}}</view>\n                  <view class=\"detail-info\"><span>周数：</span>{{swiperCourse[0].week}}</view>\n                </view>\n              </view>\n            </view>\n            <repeat for=\"{{swiperCourse}}\" index=\"index\" key=\"key\" item=\"item\">\n              <view wx:if=\"{{index !== 0}}\" class=\"swiper-item swiper-behind\" @tap.stop=\"errorBind\" style=\"left:{{72 * index}}rpx;background:{{item.bgc}};z-index:{{-index}};\" @touchstart=\"startTouching\" @touchend=\"endTouching\" animation=\"{{otherCourseAnimation[index-1]}}\">\n                <view class=\"course-container\">\n                  <view class=\"course-delete\" wx:if=\"{{swiperCourse[0].md5}}\" @tap=\"deleteAddCourse\" data-md5=\"{{swiperCourse[0].md5}}\">× 移除</view>\n                  <view class=\"course-name\">{{swiperCourse[0].name}}</view>\n                  <view class=\"course-info\">\n                    <view class=\"detail-info\"><span>教师：</span>{{swiperCourse[0].teacher}}</view>\n                    <view class=\"detail-info\"><span>教室：</span>{{swiperCourse[0].locale}}</view>\n                    <view class=\"detail-info\"><span>周数：</span>{{swiperCourse[0].week}}</view>\n                  </view>\n                </view>\n              </view>\n            </repeat>\n              <repeat for=\"{{swiperCourse}}\" index=\"index\" key=\"key\" item=\"item\">\n                <view wx:if=\"{{index !== 0}}\" class=\"swiper-item swiper-behind\" @tap.stop=\"errorBind\" style=\"left:{{72 * index}}rpx;background:{{item.bgc}};z-index:{{-index}};\" @touchstart=\"startTouching\" @touchend=\"endTouching\" animation=\"{{otherCourseAnimation[index-1]}}\">\n                  <view class=\"course-container\">\n                    <view class=\"course-delete\" wx:if=\"{{item.md5}}\" @tap=\"deleteAddCourse\" data-md5=\"{{item.md5}}\" data-item=\"{{item}}\">× 移除</view>\n                    <view class=\"course-name\">{{item.name}}</view>\n                    <view class=\"course-info\">\n                      <view class=\"detail-info\"><span>教师：</span>{{item.teacher}}</view>\n                      <view class=\"detail-info\"><span>教室：</span>{{item.locale}}</view>\n                      <view class=\"detail-info\"><span>周数：</span>{{item.week}}</view>\n                    </view>\n                  </view>\n                </view>\n                <view wx:if=\"{{index === swiperCourse.length - 1}}\" class=\"swiper-behind\" style=\"opacity:0;left:{{72 * index + 72}}rpx;background:{{item.bgc}};z-index:-300;\" animation=\"{{otherCourseAnimation[index-1]}}\">\n                </view>\n              </repeat>\n            </view>\n          </scroll-view>\n        </view>\n        <view class=\"animation-button animation-icon\" @tap=\"putAway\">\n          <view class=\"animation-button-image\"></view>\n        </view>\n        <view class=\"chooseItem\" hidden=\"{{packup}}\">\n          <view class=\"choose-item-container\">\n            <view class=\"animation-button\"></view>\n            <view class=\"change-choose\">\n              <view class=\"change-container\">更改学期</view>\n            </view>\n            <scroll-view class=\"topScroll\" scroll-x=\"true\">\n              <repeat for=\"{{terms}}\" key=\"key\" index=\"index\" item=\"item\">\n                <view @tap=\"changeTerm\" class=\"course-choose course-choose-text\" data-item=\"{{item}}\" id=\"term{{index+1}}\" style=\"background: {{chosenTerm === item ? '#6ad5e1' : ''}};\">\n                  {{item}}\n                </view>\n              </repeat>\n            </scroll-view>\n          </view>\n          <view class=\"choose-item-container\">\n            <view class=\"animation-button\"></view>\n            <view class=\"change-choose\">\n              <view class=\"change-container\">更改周次</view>\n            </view>\n            <scroll-view class=\"topScroll\" scroll-x=\"true\" scroll-into-view=\"{{toView}}\">\n              <repeat for=\"{{weeks}}\" key=\"key\" index=\"index\" item=\"item\">\n                <view @tap=\"changeWeek\" data-index=\"{{index}}\" class=\"course-choose course-choose-circle\" id=\"week{{index+1}}\" style=\"background: {{chosenWeek === item ? '#6ad5e1' : ''}}\">{{index + 1}}</view>\n              </repeat>\n            </scroll-view>\n          </view>\n          <view class=\"choose-item-container\">\n            <view class=\"animation-button\"></view>\n            <view class=\"change-choose\">\n              <view class=\"change-container\">更改模式</view>\n            </view>\n            <scroll-view class=\"topScroll\">\n              <repeat for=\"{{models}}\" key=\"key\" index=\"index\" item=\"item\">\n                <view @tap=\"changeModel\" data-index=\"{{index}}\" class=\"course-choose course-choose-text\" style=\"background: {{chosenModel === item ? '#6ad5e1' : ''}}\">{{item}}</view>\n              </repeat>\n            </scroll-view>\n          </view>\n          <view class=\"choose-item-container\">\n            <view class=\"animation-button\"></view>\n            <view class=\"change-choose\">\n              <view class=\"change-container\">更改样式</view>\n            </view>\n            <scroll-view class=\"topScroll\">\n              <repeat for=\"{{styles}}\" key=\"key\" index=\"index\" item=\"item\">\n                <view @tap=\"changeStyle\" data-index=\"{{index}}\" class=\"course-choose course-choose-text\" style=\"background: {{chosenStyle === item ? '#6ad5e1' : ''}}\">{{item}}</view>\n              </repeat>\n            </scroll-view>\n          </view>\n        </view>\n        <view class=\"main\" animation=\"{{animationData}}\">\n          <view class=\"lines_1\">\n            <view class=\"row\">\n              <repeat for=\"{{days}}\" index=\"index\" key=\"key\" item=\"item\">\n                <view class=\"top-line\">\n                  <view class=\"top-line-day {{!showDetail?'top-line-full':''}}\">{{item.day}}</view>\n                  <view wx:if=\"{{showDetail}}\" class=\"top-line-date\">{{item.date}}</view>\n                </view>\n              </repeat>\n            </view>\n            <repeat for=\"{{classNumber}}\" index=\"index\" key=\"key\" item=\"item\">\n              <view class=\"lines\" style=\"border-top-style:{{index.sequence === 0 ? 'solid' : 'dotted'}}\"></view>\n            </repeat>\n          </view>\n          <view class=\"column_1\">\n            <repeat for=\"{{classNumber}}\" index=\"index\" key=\"key\" item=\"item\">\n              <view class=\"left-column\">\n                <view class=\"left-column-sequence {{!showDetail?'left-column-full':''}}\">{{item.sequence}}</view>\n                <view wx:if=\"{{showDetail}}\" class=\"left-column-time\">{{item.duration}}</view>\n              </view>\n            </repeat>\n          </view>\n          <view hidden=\"{{!isExam}}\" class=\"cover-column\" style=\"width:750rpx;left:0rpx;\">\n            <view class=\"is-exam\">\n              <image src=\"{{chooseWeek <= 20 ? 'https://static.airbob.org/under-graduate/image/course/pic_exam.png' :'https://static.airbob.org/under-graduate/image/course/pic_celebrate.png'}}\" mode=\"aspectFit\" />\n              <view class=\"is-exam-text\" wx:if=\"{{chooseWeek <= 20}}\">考试周啦，不如去看看考试倒计时</view>\n              <view class=\"is-exam-text\" wx:else>放假啦也要合理安排时间哦</view>\n              <view class=\"is-exam-nav\" wx:if=\"{{chooseWeek <= 20}}\" @tap=\"navigateToCountDownPage\">前往考试倒计时</view>\n            </view>\n          </view>\n          <view class=\"cover-column\" hidden=\"{{isExam}}\">\n            <repeat for=\"{{nowCourse}}\" index=\"index\" key=\"key\" item=\"item\">\n              <view class=\"column\">\n                <repeat for=\"{{item}}\" index=\"courseIndex\" item=\"dailyCourse\">\n                  <view class=\"course-item {{dailyCourse.name==='+'?'course-add-item':''}}\" style=\"top:{{dailyCourse.elementTop}};height:{{dailyCourse.elementHeight}};background:{{dailyCourse.name==='+'?'#b2ee76':dailyCourse.bgc}}\" @tap=\"{{dailyCourse.name==='+'?'navigateToSearchCourse':'showCourse'}}\"\n                    data-index=\"{{index}}\" data-id=\"{{courseIndex}}\">\n                    <view class=\"course-text {{dailyCourse.name==='+'?'course-add':'class-name'}}\">\n                      {{dailyCourse.name}}\n                    </view>\n                    <view class=\"course-text class-teacher\">\n                      {{dailyCourse.locale}}\n                    </view>\n                    <view wx:if=\"{{dailyCourse.withMoreCourse}}\">\n                      <view class=\"bottom-angel\" style=\"border-top:22rpx solid {{dailyCourse.bgc === '#D8D8D8' ? '#8e8e8e' : dailyCourse.borderColor}}\"></view>\n                      <view class=\"bottom-angel-2\"></view>\n                    </view>\n                  </view>\n                </repeat>\n              </view>\n            </repeat>\n          </view>\n        </view>\n    </view>\n  </view>\n</BaseContainer>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  import ClassMixin from \"../../mixins/class.js\";\n  import { changeSecretCode, commonInformation } from \"@/api/common\";\n  import { classSchedule, deleteCourse, getCourses } from \"@/api/education\";\n  import { mockClassSchedule, mockGetAddCourses } from \"@/mock/education\";\n  import JudgeStatus from \"@/mixins/module\";\n  import BaseContainer from \"@/components/baseContainer\";\n  export default class Course extends wepy.page {\n    config = {\n      navigationBarTitleText: \"课程表\",\n      enablePullDownRefresh: true\n    };\n    data = {\n      navBackground: \"#fff\",\n      isExam: false,\n      weekScorllLeft: 0,\n      swiperHide: true,\n      packup: true,\n      weeks: [],\n      models: [\"显示单双周\", \"只显示本周\"],\n      styles: [\"简洁模式\", \"详细模式\"],\n      classNumber: [\n        { sequence: 1, duration: \"8:00 8:45\" },\n        { sequence: 2, duration: \"8:50 9:35\" },\n        { sequence: 3, duration: \"9:50 10:35\" },\n        { sequence: 4, duration: \"10:40 11:25\" },\n        { sequence: 5, duration: \"11:30 12:15\" },\n        { sequence: 6, duration: \"13:45 14:30\" },\n        { sequence: 7, duration: \"14:35 15:20\" },\n        { sequence: 8, duration: \"15:35 16:20\" },\n        { sequence: 9, duration: \"16:25 17:10\" },\n        { sequence: 10, duration: \"18:30 19:15\" },\n        { sequence: 11, duration: \"19:25 20:10\" },\n        { sequence: 12, duration: \"20:20 21:05\" }\n      ],\n      nowCourse: [],\n      elseCourse: [],\n      unshowCourse: [],\n      swiperCourse: [],\n      addCourses: [],\n      chooseWeek: \"\",\n      chosenWeek: \"#\",\n      chosenTerm: \"\",\n      commonWeek: \"\",\n      commonTerm: \"\",\n      dataStart: \"\",\n      chosenModel: \"\",\n      chosenStyle: \"\",\n      days: [\n        {\n          day: \"周一\",\n          date: \"\"\n        },\n        {\n          day: \"周二\",\n          date: \"\"\n        },\n        {\n          day: \"周三\",\n          date: \"\"\n        },\n        {\n          day: \"周四\",\n          date: \"\"\n        },\n        {\n          day: \"周五\",\n          date: \"\"\n        },\n        {\n          day: \"周六\",\n          date: \"\"\n        },\n        {\n          day: \"周日\",\n          date: \"\"\n        }\n      ],\n      terms: [],\n      animationData: {},\n      firstCourseAnimation: {},\n      otherCourseAnimation: [],\n      Day: \"\",\n      detailCourseScroll: false,\n      trueCourses: [],\n      chosenRequestYear: \"\",\n      chosenRequestTerm: \"\",\n      addCourseIcon: {\n        day: 7,\n        name: \"+\",\n        locale: \"添加课程\",\n        sectionstart: 8,\n        sectionend: 9,\n        week: \"第1-18周\",\n        weekarr: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18],\n        weekend: 18,\n        weekstart: 1\n      },\n      passwordModelOptions: {\n        passwordModelProps: false,\n        placeholder: \"正方密码\",\n        refreshData: this.init,\n        bindInfo: {\n          usename: wepy.getStorageSync(\"User\").studentId,\n          domainType: \"1\"\n        }\n      },\n      visitorModeStatus: false,\n      toView: \"week0\"\n    };\n    components = {\n      BaseContainer\n    };\n    computed = {\n      navTitle() {\n        return `第${this.chooseWeek}周`;\n      },\n      showDetail() {\n        return this.chosenStyle === \"详细模式\";\n      }\n    };\n    mixins = [ClassMixin, JudgeStatus];\n    methods = {\n      navigateToCountDownPage() {\n        wepy.navigateTo({ url: \"cut-down\" });\n      },\n      bindCardPassword(e) {\n        this.bindInputPassword = e.detail.value;\n      },\n      putAway() {\n        if (!this.swiperHide) {\n          return;\n        }\n        this.chosenWeek = `第${this.chooseWeek}周`;\n        const animation = wepy.createAnimation({\n          duration: 100\n        });\n        if (this.packup) {\n          animation.translate(0, 198).step();\n          this.packup = false;\n        } else {\n          animation.translate(0, 0).step();\n          this.packup = true;\n        }\n        this.animationData = animation.export();\n        this.toView = `week${this.chooseWeek}`;\n      },\n      showCourse(e) {\n        let index = e.currentTarget.dataset.index;\n        let id = e.currentTarget.dataset.id;\n        let thisCourse = this.nowCourse[index][id];\n        // 避免一个时间段有两个同时要上的课只显示一个\n        for (let i of this.nowCourse[index]) {\n          if (\n            i.sectionstart === thisCourse.sectionstart &&\n            i.sectionend === thisCourse.sectionend\n          ) {\n            this.swiperCourse.unshift(i);\n          }\n        }\n        for (let i of this.elseCourse[index]) {\n          if (\n            i.sectionstart === thisCourse.sectionstart &&\n            i.sectionend === thisCourse.sectionend\n          ) {\n            this.swiperCourse.unshift(i);\n          }\n        }\n        this.swiperCourse.sort(x => (x.bgc === \"#D8D8D8\" ? 1 : -1));\n        this.swiperHide = false;\n        this.navBackground = \"#808080\";\n        this.detailCourseScroll = true;\n        this.$apply();\n      },\n      hideDetailCourse() {\n        this.swiperHide = true;\n        let firstCourseAnimation = wepy.createAnimation({\n          duration: 0\n        });\n        firstCourseAnimation.translate(0, 0).step();\n        this.firstCourseAnimation = firstCourseAnimation.export();\n        for (let i = 0; i < this.swiperCourse.length - 1; i++) {\n          let otherCourseAnimation = wepy.createAnimation({\n            duration: 0\n          });\n          otherCourseAnimation.translate(0, 0).step();\n          this.otherCourseAnimation[i] = otherCourseAnimation.export();\n          this.$apply();\n        }\n        this.swiperCourse = [];\n        this.detailCourseScroll = false;\n        this.navBackground = \"#fff\";\n        this.$apply();\n      },\n      async changeTerm(e) {\n        let item = e.currentTarget.dataset.item;\n        let requestYear = item.substr(0, 9);\n        let requestTerm;\n        if (item.indexOf(\"一\") === -1 || item.indexOf(\"一\") === \"-1\") {\n          requestTerm = 2;\n        } else {\n          requestTerm = 1;\n        }\n        this.chosenRequestYear = requestYear;\n        this.chosenRequestTerm = requestTerm;\n        let changedTermCourse = await classSchedule(requestYear, requestTerm);\n        if (changedTermCourse.data.success) {\n          this.trueCourses = changedTermCourse.data.data.timetable;\n          this.dataStart = changedTermCourse.data.data.dataStart;\n          this.chosenTerm = item;\n          this.setCoursesCategory(this.trueCourses, this.chooseWeek, item);\n          this.passwordModelOptions.passwordModelProps = false;\n        } else {\n          this.passwordModelOptions.passwordModelProps = true;\n        }\n        this.$apply();\n      },\n      changeWeek(e) {\n        this.isExam = false;\n        this.chosenWeek = this.weeks[e.currentTarget.dataset.index];\n        this.chooseWeek = parseInt(e.currentTarget.dataset.index + 1);\n        this.setCoursesCategory(\n          this.trueCourses,\n          this.chooseWeek,\n          this.chosenTerm\n        );\n      },\n      changeModel(e) {\n        const index = e.currentTarget.dataset.index;\n        this.chosenModel = this.models[index];\n        wepy.setStorageSync(\"chosenModel\", this.models[index]);\n        this.setCoursesCategory(\n          this.trueCourses,\n          this.chooseWeek,\n          this.chosenTerm\n        );\n        this.$apply();\n      },\n      changeStyle(e) {\n        const index = e.currentTarget.dataset.index;\n        this.chosenStyle = this.styles[index];\n        wepy.setStorageSync(\"chosenStyle\", this.chosenStyle);\n        this.$apply();\n      },\n      errorBind(e) {\n        this.detailCourseScroll = true;\n      },\n      navigateToSearchCourse() {\n        wepy.navigateTo({\n          url: `search-course`\n        });\n      },\n      deleteAddCourse(e) {\n        let course = e.currentTarget.dataset.md5;\n        let swiperCourse = this.swiperCourse;\n        let md5 = [];\n        md5.push(course);\n        wepy\n          .showModal({\n            title: \"移除此课程\",\n            content: \"将本节课程从课程表移除\",\n            confirmColor: \"#47CFF5\"\n          })\n          .then(res => {\n            if (res.confirm) {\n              deleteCourse(md5).then(res => {\n                if (res.data.data) {\n                  wepy.showToast({\n                    title: \"删除成功\",\n                    icon: \"success\",\n                    duration: 2000\n                  });\n                  for (let i in swiperCourse) {\n                    if (swiperCourse[i].md5 === course) {\n                      swiperCourse.splice(i, 1);\n                    }\n                  }\n                  this.swiperCourse = swiperCourse;\n                  if (!swiperCourse.length) {\n                    this.swiperHide = true;\n                  }\n                  this.init();\n                  this.$apply();\n                } else {\n                  wepy.showToast({\n                    title: \"删除失败\",\n                    icon: \"success\",\n                    duration: 2000\n                  });\n                }\n              });\n            }\n          });\n      }\n    };\n    startTouching(e) {\n      if (e.touches.length === 1) {\n        this.startX = e.touches[0].clientX;\n      }\n    }\n    async endTouching(e) {\n      if (e.changedTouches.length === 1) {\n        this.endX = e.changedTouches[0].clientX;\n        if (\n          parseInt(this.startX - this.endX) >= 10 &&\n          this.swiperCourse.length > 1\n        ) {\n          if (this.otherCourseAnimation.length === 0) {\n            for (let i = 0; i < this.swiperCourse.length - 1; i++) {\n              this.otherCourseAnimation.push({});\n            }\n          }\n          this.detailCourseScroll = true;\n          let screenWidth;\n          await wepy.getSystemInfo().then(res => {\n            screenWidth = parseFloat(res.screenWidth / 750);\n          });\n          this.$apply();\n          let firstCourseAnimation = wepy.createAnimation({\n            duration: 100\n          });\n          let translateLeft = screenWidth * 140;\n          firstCourseAnimation.translate(-translateLeft, 0).step();\n          this.firstCourseAnimation = firstCourseAnimation.export();\n          this.$apply();\n          for (let i = 0; i < this.swiperCourse.length - 1; i++) {\n            let otherCourseAnimation = wepy.createAnimation({\n              duration: 100\n            });\n            let translateRight =\n              (i + 1) * screenWidth * 400 -\n              screenWidth * 140 -\n              (i + 1) * 90 * screenWidth;\n            otherCourseAnimation.translate(translateRight, 0).step();\n            this.otherCourseAnimation[i] = otherCourseAnimation.export();\n            this.$apply();\n          }\n          this.$apply();\n        } else {\n          this.detailCourseScroll = false;\n          this.$apply();\n        }\n      }\n    }\n    async getTerms() {\n      /**\n       * 根据入学的年份(例如：2018)和semester（例如：202001）计算学期数组元素的个数。\n       * 如果nextTerm为true或者现在的时间超过了dataStart，则元素个数加1。\n       * 再根据元素个数生成学期数组。\n       */\n      const { dataStart, nextTerm, semester } = await this.getCommon();\n      const { studentId } = wepy.getStorageSync(\"User\");\n      const startDate = Date.parse(dataStart);\n      const parseSemester =\n        parseInt(semester.slice(0, 4)) +\n        (parseInt(semester.slice(5, 6)) === 1 ? 0 : 0.5) -\n        1;\n      const enterYear = parseInt(`20${studentId.slice(1, 3)}`);\n\n      let termsCount = (parseSemester - enterYear) / 0.5;\n      if (Date.now() > startDate) termsCount++;\n      if (nextTerm) termsCount++;\n      for (let i = 0; i < termsCount; i++) {\n        this.terms.unshift(\n          `${enterYear + Math.floor(i / 2)}-${enterYear +\n            Math.floor(i / 2) +\n            1} 第${i % 2 === 0 ? \"一\" : \"二\"}学期`\n        );\n      }\n      this.$apply();\n    }\n    async getAddCourses() {\n      let addCoursesRes = this.visitorModeStatus\n        ? await mockGetAddCourses()\n        : await getCourses();\n      let addCoursesModel = [];\n      if (addCoursesRes.data.data) {\n        let addCourses = addCoursesRes.data.data;\n        addCourses.map(item => {\n          item.courseModel.md5 = item.md5;\n          addCoursesModel.push(item.courseModel);\n        });\n      }\n      this.addCourses = addCoursesModel;\n      return addCoursesModel;\n    }\n    // 用于刷新该周的课表信息，并修改周一到周日的日期\n    async setCoursesCategory(trueCourses, week, term) {\n      if (this.dataStart) {\n        const createShortTime = unixTime => {\n          const time = new Date(unixTime);\n          return `${time.getMonth() + 1}/${time.getDate()}`;\n        };\n        const ONE_DAY = 86400000;\n        const dataStartUnixTime = new Date(this.dataStart).getTime();\n        const mondayUnixTime = (week - 1) * ONE_DAY * 7 + dataStartUnixTime;\n        for (let i = 0; i < 7; i++) {\n          this.days[i].date = createShortTime(mondayUnixTime + i * ONE_DAY);\n        }\n      }\n      if (term === this.commonTerm) {\n        let addCoursesModel = await this.getAddCourses();\n        trueCourses = trueCourses.concat(addCoursesModel);\n      }\n      trueCourses = trueCourses.concat(this.addCourseIcon);\n      if (this.chosenModel !== \"只显示本周\") {\n        const dealedCourse = this.handleCourses(trueCourses, week, false);\n        this.nowCourse = dealedCourse[0];\n        this.elseCourse = dealedCourse[1];\n        this.unshowCourse = dealedCourse[2];\n        this.$apply();\n      } else {\n        const dealedCourse = this.handleCourses(trueCourses, week, true);\n        this.nowCourse = dealedCourse[0];\n        this.elseCourse = dealedCourse[1];\n        this.unshowCourse = dealedCourse[2];\n        this.$apply();\n      }\n    }\n    async init() {\n      const chosenModel = wepy.getStorageSync(\"chosenModel\");\n      if (chosenModel) {\n        this.chosenModel = chosenModel;\n      } else {\n        wepy.setStorageSync(\"chosenModel\", \"显示单双周\");\n        this.chosenModel = \"显示单双周\";\n      }\n      const chosenStyle = wepy.getStorageSync(\"chosenStyle\");\n      if (chosenStyle) {\n        this.chosenStyle = chosenStyle;\n      } else {\n        wepy.setStorageSync(\"chosenStyle\", \"详细模式\");\n        this.chosenStyle = \"详细模式\";\n      }\n      const timetable = wepy.getStorageSync(\"timetable\");\n      if (timetable) {\n        this.trueCourses = timetable;\n        this.setCoursesCategory(timetable, this.commonWeek, this.commonTerm);\n        this.passwordModelOptions.passwordModelProps = false;\n      } else {\n        let res = await classSchedule();\n        if (!res.data.data) {\n          this.passwordModelOptions.passwordModelProps = true;\n        } else {\n          this.passwordModelOptions.passwordModelProps = false;\n          this.trueCourses = res.data.data.timetable;\n          this.setCoursesCategory(\n            this.trueCourses,\n            this.commonWeek,\n            this.commonTerm\n          );\n        }\n      }\n      this.$apply();\n    }\n    async getCommon() {\n      let common = wepy.getStorageSync(\"common\");\n      if (!common) {\n        const response = await commonInformation();\n        if (response.data.data) {\n          common = response.data.data;\n        }\n      }\n      return common;\n    }\n    async courseRefetchData() {\n      const date = new Date();\n      const day = date.getDay() === 0 ? 7 : date.getDay();\n      this.Day = parseInt(day - 1);\n      if (!this.visitorModeStatus) {\n        const common = await this.getCommon();\n        this.dataStart = common.dataStart;\n        this.chooseWeek = parseInt(common.week);\n        this.commonWeek = this.chooseWeek;\n        await this.getTerms();\n        if (wepy.getStorageSync(\"common\")) {\n          this.chosenTerm = `${wepy.getStorageSync(\"common\").year} 第${\n            wepy.getStorageSync(\"common\").semester.substr(-1) === \"1\"\n              ? \"一\"\n              : \"二\"\n          }学期`;\n        } else {\n          this.chosenTerm = `2018-2019 第一学期`;\n        }\n        this.commonTerm = this.chosenTerm;\n      } else {\n        this.chooseWeek = 1;\n        this.commonWeek = 1;\n      }\n      if (this.chooseWeek > 18 || this.chooseWeek < 1) {\n        this.isExam = true;\n      }\n      this.weeks = [];\n      for (let i = 1; i <= 18; i++) {\n        this.weeks.push(`第${i}周`);\n      }\n      this.init();\n    }\n    onLoad(op) {\n      this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n      wepy.setStorageSync(\"courseRoute\", \"cannotRefresh\");\n      this.judgeStatus(op.name);\n      this.courseRefetchData();\n    }\n    onShow() {\n      if (wepy.getStorageSync(\"courseRoute\") === \"canRefresh\") {\n        this.courseRefetchData();\n        wepy.setStorageSync(\"courseRoute\", \"cannotRefresh\");\n      }\n    }\n    async onPullDownRefresh() {\n      if (!this.visitorModeStatus) {\n        const data = {\n          type: \"coursePullRefresh\"\n        };\n        if (this.chosenRequestTerm !== \"\") {\n          data.year = this.chosenRequestYear;\n          data.term = this.chosenRequestTerm;\n        }\n        let changedTermCourse = await classSchedule(\n          data.year,\n          data.term,\n          data.type\n        );\n        if (!changedTermCourse.data.data) {\n          this.passwordModelOptions.passwordModelProps = true;\n        } else {\n          this.passwordModelOptions.passwordModelProps = false;\n          this.trueCourses = changedTermCourse.data.data.timetable;\n          this.setCoursesCategory(\n            this.trueCourses,\n            this.chooseWeek,\n            this.chosenTerm\n          );\n        }\n        wepy.showToast({\n          title: \"刷新成功\",\n          icon: \"success\",\n          duration: 1000\n        });\n      }\n      this.$apply();\n      wepy.stopPullDownRefresh();\n    }\n  }\n</script>\n\n<style lang=\"stylus\" type=\"text/stylus\" scoped>\n.lines_1\n  position absolute\n  z-index 0\n  top 0\n  width 670rpx\n  padding-left 80rpx\n  font-size 26rpx\n  color #353535\n  text-align center\n  .row\n    display flex\n    justify-content center\n    align-items center\n  .top-line\n    height 90rpx\n    width 750rpx\n    line-height 45rpx\n    .top-line-day\n      font-weight 600\n      font-size 30rpx\n    .top-line-date\n      font-size 25rpx\n    .top-line-full\n      line-height 90rpx\n  .lines\n    width 670rpx\n    height 107rpx\n    border-top 1rpx dotted #E3E3E3\n    display flex\n    align-items center\n\n.hide-page\n  position fixed\n  width 100%\n  height 100%\n  background rgba(0, 0, 0, 0.5)\n  z-index 200\n  .swiper-thing\n    position relative\n    margin 0 auto\n    width 330rpx\n    height 90vh\n    z-index 205\n    .swiper-item\n      position relative\n      margin 0 auto\n      top 27vh\n      height 420rpx\n      width 350rpx\n      margin-right 70rpx\n      border-radius 10rpx\n      box-shadow 5px 0 5px 0 rgba(0, 0, 0, 0.1)\n      // opacity 0.75\n      z-index 202\n      flex-shrink 0\n      display flex\n      justify-content center\n      .course-container\n        display flex\n        flex-direction column\n        padding 53rpx 30rpx\n        color #fff\n        .course-delete\n          position absolute\n          left 16rpx\n          top 14rpx\n          font-weight bold\n          font-size 30rpx\n          color #fff\n          line-height 30rpx\n          display flex\n          align-items center\n        .course-name\n          height 180rpx\n          font-size 30rpx\n          font-weight 700\n        .course-info\n          font-size 30rpx\n          display flex\n          flex-direction column\n    .swiper-behind\n      position absolute\n.course\n  min-height 100vh\n  .animation-icon\n    position absolute\n    z-index 100\n  .animation-button\n    height 90rpx\n    width 90rpx\n    .animation-button-image\n      width 90rpx\n      height 90rpx\n      background-image url('https://static.airbob.org/under-graduate/timetable_pic_editor.png')\n      background-repeat no-repeat\n      background-position center\n      background-size contain\n  .chooseItem\n    background #fff\n    height 270rpx\n    font-size 26rpx\n    margin 0 0 -270rpx 0\n    .choose-item-container\n      height 90rpx\n      display flex\n      align-items center\n      border-bottom 1rpx solid #E3E3E3\n      padding-right 20rpx\n      .change-choose\n        display flex\n        width 130rpx\n        height 90rpx\n        align-items center\n        justify-content center\n        .change-container\n          text-align center\n          width 110rpx\n          color #353535\n          font-weight 700\n      .topScroll\n        position relative\n        display inline-block\n        max-width 540rpx\n        font-family PingFangSC-Light\n        white-space nowrap\n        height 90rpx\n        color #fff\n        font-weight 700\n        display flex\n        flex-direction row\n        align-items center\n        .course-choose\n          display inline-block\n          text-align center\n          background rgba(106, 213, 225, 0.4)\n          margin-left 26rpx\n        .course-choose-text\n          margin-top 20rpx\n          line-height 50rpx\n          height 50rpx\n          font-size 22rpx\n          padding-left 20rpx\n          padding-right 20rpx\n          border-radius 25rpx\n        .course-choose-circle\n          margin-top 15rpx\n          height 60rpx\n          width 60rpx\n          font-size 40rpx\n          line-height 60rpx\n          border-radius 50%\n  .main\n    width 750rpx\n    position absolute\n    .main-scroll\n      width 100%\n      font-size 26rpx\n      height 1280rpx\n      color rgb(139, 139, 139)\n    .cover-column\n      margin-left 80rpx\n      width 670rpx\n      .is-exam\n        position absolute\n        width 750rpx\n        height 80vh\n        display flex\n        flex-direction column\n        align-items center\n        align-content center\n        justify-content center\n        text-align center\n        .is-exam-text\n          margin-top 30rpx\n          font-size 28rpx\n          color #999CA0\n        .is-exam-nav\n          margin-top 30rpx\n          color #fff\n          font-size 30rpx\n          height 60rpx\n          line-height 60rpx\n          padding-left 30rpx\n          padding-right 30rpx\n          background #6DCDF1\n          border-radius 15rpx\n        image\n          width 500rpx\n          height 500rpx\n      .column\n        display inline-block\n        width 95rpx\n        height 1296rpx\n      .course-item\n        position absolute\n        width 84rpx\n        padding-left 3rpx\n        padding-right 3rpx\n        border-radius 10rpx\n        font-size 22rpx\n        color #fff\n        display flex\n        align-items center\n        justify-content center\n        flex-direction column\n        overflow hidden\n        .course-text\n          text-overflow ellipsis\n          display -webkit-box\n          -webkit-box-orient vertical\n          overflow hidden\n          width 80rpx\n          text-align center\n        .class-name\n          -webkit-line-clamp 4\n        .class-teacher\n          -webkit-line-clamp 3\n        .bottom-angel\n          position absolute\n          right 0rpx\n          bottom 0rpx\n          border-right 22rpx solid transparent\n          border-top-left-radius 10rpx\n        .bottom-angel-2\n          position absolute\n          bottom 0rpx\n          right -20rpx\n          border-left 20rpx solid transparent\n          border-right 20rpx solid transparent\n          border-bottom 20rpx solid #D8D8D8\n      .course-add-item\n        .course-text\n          width 46rpx\n        .course-add\n          line-height 40rpx\n          font-size 40rpx\n          font-weight bold\n    .column_1\n      position absolute\n      top 90rpx\n      width 80rpx\n      display flex\n      flex-direction column\n      justify-content center\n      align-items center\n      align-content center\n      text-align center\n      background #F5F5F5\n      .left-column\n        text-align center\n        height 108rpx\n        color #888888\n        .left-column-sequence\n          line-height 52rpx\n          height 52rpx\n          font-weight 500\n        .left-column-time\n          line-height 27rpx\n          height 54rpx\n          font-size 20rpx\n          text-align right\n          width 50rpx\n        .left-column-full\n          line-height 108rpx\n\n\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 485rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n"
  },
  {
    "path": "src/edu-admin-page/pages/credit.wpy",
    "content": "\n<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <QyModal width=\"500rpx\">\n        <view slot=\"content\" class=\"bind-container\">\n          <input class=\"bind-input\" placeholder=\"{{placeholder}}\" password=\"true\" @input=\"bindCardPassword\" placeholder-style=\"color: #999CA0\" />\n          <button class=\"bind-button\" @tap.stop=\"bindHandle\" hover-class=\"button-click\">立即绑定</button>\n        </view>\n      </QyModal>\n      <view class=\"credit-top\">\n        <view class=\"credit-top-item\">\n          <view class=\"credit-name\">创新有效学分</view>\n          <view class=\"credit-count\">{{innovationValidScore}}</view>\n        </view>\n        <view class=\"credit-top-item\">\n          <view class=\"credit-name\">创新总学分</view>\n          <view class=\"credit-count\">{{innovationScore}}</view>\n        </view>\n        <view class=\"credit-top-item\">\n          <view class=\"credit-name\">有效学分</view>\n          <view class=\"credit-count\">{{totalValidScore}}</view>\n        </view>\n        <view class=\"credit-top-item\" style=\"border:none;\">\n          <view class=\"credit-name\">总学分</view>\n          <view class=\"credit-count\">{{totalScore}}</view>\n        </view>\n      </view>\n      <view class=\"detailed\">\n        <view class=\"detail-circle\"></view>\n        <view class=\"detail-info\">详细信息</view>\n      </view>\n      <view class=\"main-load\" hidden=\"{{loadHide}}\">\n        <view class=\"boxLoading\"></view>\n      </view>\n      <view class=\"main-container\">\n        <repeat for=\"{{creditDetails}}\" key=\"key\" index=\"index\" item=\"item\">\n          <view class=\"credit-info\" @tap=\"showCreditDetail(index)\">\n            <view class=\"credit-main-info\">\n              <view class=\"credit-semester\">{{item.semester}}</view>\n              <view class=\"credit-standard\">{{item.standard}}</view>\n              <view class=\"credit-score\">{{item.score}}学分</view>\n            </view>\n            <view class=\"credit-detail-info\" animation=\"{{showDetailAnimation[index]}}\">\n              <view>所属内容：{{item.project}}</view>\n              <view>考核内容：{{item.content}}</view>\n              <view>考核标准：{{item.standard}}</view>\n              <view>级别：{{item.level}}</view>\n            </view>\n          </view>\n        </repeat>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport QyModal from \"@/components/qy-modal\";\nimport { changeSecretCodeLower, ownGraduateGrade } from \"@/api/common\";\nimport { mockOwnGraduateGrade } from \"@/mock/common\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class extends wepy.page {\n  components = {\n    QyModal,\n    BaseContainer\n  };\n  config = {\n    navigationBarTitleText: \"自主学分\"\n  };\n  mixins = [JudgeStatus];\n  data = {\n    navTitle: \"自主学分\",\n    bindInputPassword: \"\",\n    creditDetails: [],\n    isShow: [],\n    showDetailAnimation: [],\n    loadHide: false,\n    innovationScore: \"\",\n    innovationValidScore: \"\",\n    totalScore: \"\",\n    totalValidScore: \"\",\n    placeholder: \"\",\n    visitorModeStatus: false\n  };\n  methods = {\n    bindCardPassword(e) {\n      this.bindInputPassword = e.detail.value;\n    },\n    async bindHandle() {\n      await changeSecretCodeLower(\n        wepy.getStorageSync(\"User\").studentId,\n        this.bindInputPassword,\n        \"3\"\n      ).then(res => {\n        if (res.data && res.data.data) {\n          // 绑定成功\n          this.placeholder = \"\";\n          this.$invoke(\"QyModal\", \"close\");\n          this.init();\n        } else {\n          wepy.showModal({\n            content: \"密码错误\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          });\n        }\n      });\n    },\n    showCreditDetail(id, e) {\n      this.isShow[id] = !this.isShow[id];\n      let animation = wepy.createAnimation({\n        duration: 100\n      });\n      animation.height(this.isShow[id] ? \"200rpx\" : \"0rpx\").step();\n      this.showDetailAnimation[id] = animation.export();\n      this.$apply();\n    }\n  };\n  async init() {\n    let that = this;\n    const creditDetail = this.visitorModeStatus\n      ? await mockOwnGraduateGrade()\n      : await ownGraduateGrade();\n    if (!creditDetail.data.data) {\n      this.placeholder = \"自主学分密码\";\n      this.$invoke(\"QyModal\", \"open\");\n      this.$apply();\n    } else {\n      that.loadHide = true;\n      that.creditDetails = creditDetail.data.data.ziZhuResultModels;\n      that.totalValidScore = creditDetail.data.data.totalValidScore;\n      that.totalScore = creditDetail.data.data.totalScore;\n      that.innovationScore = creditDetail.data.data.innovationScore;\n      that.innovationValidScore = creditDetail.data.data.innovationValidScore;\n      that.$apply();\n    }\n  }\n  onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name).then(() => {\n      this.init();\n    });\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n@import '../../css/loading'\n.main-load\n  position relative\n  margin 100rpx\n.credit-top\n  width 720rpx\n  height 186rpx\n  margin 0 auto\n  background linear-gradient(109deg, rgb(64, 174, 255) 0%, rgb(115, 234, 255) 100%)\n  border-radius 5rpx\n  display flex\n  justify-content center\n  text-align center\n  .credit-top-item\n    height 110rpx\n    margin-top 38rpx\n    width 25%\n    color rgb(255, 255, 255)\n    border-right 2rpx solid rgb(255, 255, 255)\n    .credit-name\n      font-size 24rpx\n    .credit-count\n      font-size 50rpx\n      padding-top 15rpx\n.detailed\n  width 720rpx\n  display flex\n  margin 50rpx auto 0 auto\n  height 30rpx\n  font-size 30rpx\n  line-height 30rpx\n  font-weight bold\n  .detail-circle\n    position inline-block\n    border 1rpx solid rgb(52, 177, 244)\n    border-radius 50%\n    width 20rpx\n    height 20rpx\n    margin 5rpx 10rpx 5rpx 0\n  .detail-info\n    position inline-block\n    width 300rpx\n    font-size 30rpx\n    line-height 30rpx\n.credit-info\n  position relative\n  width 670rpx\n  margin 26rpx auto 0rpx auto\n  box-shadow rgba(4, 0, 0, 0.35) 2rpx 2rpx 14rpx 0\n  font-family SimHei\n  border-radius 50rpx\n  .credit-main-info\n    min-height 100rpx\n    display flex\n    align-items center\n    font-size 26rpx\n    text-align center\n    .credit-semester\n      width 200rpx\n    .credit-standard\n      width 350rpx\n    .credit-score\n      width 120rpx\n  .credit-detail-info\n    height 0\n    overflow hidden\n    text-align center\n    font-size 26rpx\n    padding 20rpx auto\n    view\n      line-height 50rpx\n.main-container\n  padding-bottom 50rpx\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 485rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n"
  },
  {
    "path": "src/edu-admin-page/pages/cut-down.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"考试倒计时\">\n    <view slot=\"qy-content\">\n      <view>\n        <QyModal containerClass=\"cutdown-modal-containerClass\" height=\"550rpx\" width=\"605rpx\">\n          <view slot=\"content\" class=\"slot-content\">\n            <input\n              class=\"input space\"\n              value=\"{{subject}}\"\n              placeholder-class=\"placeholder\"\n              placeholder=\"{{placeholder.subject}}\"\n              @input=\"handleInput\"\n              data-input=\"subject\"\n            >\n            <QyDatetimeSelect endDate=\"2030-01-01\" style=\"margin-bottom:28rpx;\"/>\n            <input\n              class=\"input space\"\n              value=\"{{room}}\"\n              placeholder-class=\"placeholder\"\n              placeholder=\"{{placeholder.room}}\"\n              @input=\"handleInput\"\n              data-input=\"room\"\n            >\n            <input\n              class=\"input space\"\n              value=\"{{teacher}}\"\n              placeholder-class=\"placeholder\"\n              placeholder=\"{{placeholder.teacher}}\"\n              @input=\"handleInput\"\n              data-input=\"teacher\"\n            >\n            <button class=\"add-button\" @tap.stop=\"addSubject\" data-input=\"subject\">增加课程</button>\n          </view>\n        </QyModal>\n        <QyQuestionModal width=\"auto\">\n          <view slot=\"content\" class=\"question-container\">\n            <view class=\"bb\">\n              <text class=\"left-container\">我的考试</text>\n              <text class=\"right-container\">由学生个人课表通过课名和老师名过滤一次之后得到的考试安排</text>\n            </view>\n            <view class=\"bb\" style=\"margin-top:20rpx;margin-bottom:20rpx;\">\n              <text class=\"left-container\">专业考试</text>\n              <text class=\"right-container\">该专业所有考试安排</text>\n            </view>\n            <view class=\"button\" @tap.stop=\"isQuestionModalVisible\" data-is-visible=\"{{false}}\">知道了</view>\n          </view>\n        </QyQuestionModal>\n        <view class=\"exam-card\">\n          <view class=\"exam-card-top\">\n            <repeat for=\"{{examCard}}\" key=\"index\" index=\"index\" item=\"item\">\n              <view class=\"exam-card-top-item {{currentTab==index ? 'active' : ''}}\"  data-current=\"{{index}}\"  @tap=\"handleSwiperChange\">\n                {{item.type}}\n              </view>\n            </repeat>\n          </view>\n          <view class=\"exam-card-main\" >\n            <swiper current=\"{{currentTab}}\" style=\"box-shadow: {{currentTab === 0 ? '0px 0px 15rpx #a2f8d8' : '0px 0px 15rpx #f3dc8d'}}\" class=\"swiper-container\" duration=\"200\">\n              <repeat for=\"{{examCard}}\" key=\"index\" index=\"index\" item=\"item\">\n                <swiper-item  class=\"exam-card-item\" catchtouchmove=\"stopTouchMove\">\n                  <view>\n                    <view class=\"question\" @tap.stop=\"isQuestionModalVisible\" data-is-visible=\"{{true}}\"></view>\n                    <view class=\"remaining-times\">{{item.remainingTimes}}</view>\n                    <view class=\"remaining-times-title\">剩余科目</view>\n                    <view class=\"subtitle\">\n                      <p>{{item.subtitle}}</p>\n                    </view>\n                    </view>\n                </swiper-item>\n              </repeat>\n            </swiper>\n          </view>\n        </view>\n        <view class='devide-line'/>\n        <view class=\"container\" style=\"height:{{clientHeight}}px\" >\n          <view class=\"swiper-container\" animation=\"{{toggleAnimation}}\">\n            <repeat for=\"{{examCard}}\" key=\"index\" index=\"index\" item=\"examCardItem\">\n              <view class=\"swiper-item\" id=\"swiper-item-{{index}}\">\n                <view class=\"head-container\">\n                  <text class=\"text\" style=\"{{fetchdata2.length === 0?'display:none':''}}\">近期考试</text>\n                  <image\n                    class=\"add\"\n                    mode=\"widthFix\"\n                    src=\"https://static.airbob.org//QjE2MDEyMzI3LXBsdXMucG5n\"\n                    @tap.stop=\"addModal\"\n                  >\n                </view>\n                <view wx:for=\"{{examCardItem.subjects.unFinished}}\" wx:key=\"{{index}}\" >\n                  <view class=\"unfinished-line\" hidden=\"{{index ===0}}\" ></view>\n                  <SubjectCard :item.sync=\"item\" :isFinished=\"false\" :distanceX.sync=\"distanceX[index]\" :bg.sync=\"unfinishBg[index%3]\"/>\n                </view>\n                <view class='devide-line'/>\n                <text class=\"finish-text\" style=\"{{fetchdata1.length === 0?'display:none':''}}\">已结束</text>\n                <view wx:for=\"{{examCardItem.subjects.finished}}\" wx:key=\"{{index}}\">\n                  <SubjectCard :item.sync=\"item\" :isFinished=\"true\" :show.sync=\"shows[index]\"/>\n                </view>\n              </view>\n            </repeat>\n          </view>\n          <view style=\"{{hasExam?'display:none':''}}\">\n            <image\n              class=\"no-image\"\n              mode=\"widthFix\"\n              src=\"https://static.airbob.org/under-graduate/%E7%BC%BA%E7%9C%81%E6%8F%92%E7%94%BB.png\"\n            >\n            <view class=\"no-text\">考试安排还没出来哦</view>\n          </view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport SubjectCard from \"../components/subject-card\";\nimport QyModal from \"@/components/qy-modal\";\nimport QyDatetimeSelect from \"@/components/qy-datetime-select\";\nimport JudgeStatus from \"@/mixins/module\";\nimport {\n  strikeOutYourExam,\n  restoreYourOwnExam,\n  addYourOwnExam,\n  selfExam,\n  getYourOwnExam\n} from \"@/api/education\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class CutDown extends wepy.page {\n  components = {\n    SubjectCard,\n    QyModal,\n    QyQuestionModal: QyModal,\n    QyDatetimeSelect,\n    BaseContainer\n  };\n  config = {\n    enablePullDownRefresh: true\n  };\n  mixins = [JudgeStatus];\n  data = {\n    placeholder: {\n      subject: \"科目名称\",\n      room: \"地点\",\n      teacher: \"老师\"\n    },\n    shows: [], // 控制已结束的卡片是否展开\n    distanceX: [], // 未结束的每个滑块的距离\n    tempDistanceX: [], // 临时的未结束的每个滑块的距离\n    rawSubjects: {\n      fetchdata1: [], // 课程表相关\n      fetchdata2: [] // 专业安排相关\n    },\n    subject: \"\",\n    room: \"\",\n    beginTimestamp: 0,\n    duration: 0,\n    teacher: \"\",\n    arrowAnimation: {},\n    unfinishBg: [\n      {\n        left:\n          \"linear-gradient( 45deg, rgb(96,203,228) 0%, rgb(146,227,249) 100%)\",\n        right: \"rgb(131,220,242)\"\n      },\n      {\n        left:\n          \"linear-gradient( 45deg, rgb(239,90,97) 0%, rgb(251,144,149) 100%)\",\n        right: \"rgb(247,126,132)\"\n      },\n      {\n        left:\n          \"linear-gradient( 45deg, rgb(253,178,59) 0%, rgb(252,196,107) 100%)\",\n        right: \"rgb(252,192,97)\"\n      }\n    ],\n    currentTab: 0,\n    clientHeight: \"\",\n    examCard: [\n      {\n        id: 0,\n        type: \"我的考试\",\n        remainingTimes: \"\",\n        subtitle: \"考试已经结束了\",\n        subjects: {\n          unFinished: [],\n          finished: []\n        }\n      },\n      {\n        id: 1,\n        type: \"专业考试\",\n        remainingTimes: \"\",\n        subtitle: \"考试已经结束了\",\n        subjects: {\n          unFinished: [],\n          finished: []\n        }\n      }\n    ],\n    toggleAnimation: {}\n  };\n  async onPullDownRefresh() {\n    await this.fetchData(true);\n    await this.onLoad();\n    wepy.stopPullDownRefresh();\n    wepy.showToast({\n      title: \"刷新成功\",\n      icon: \"success\",\n      duration: 1000\n    });\n  }\n  events = {\n    movableViewTouchEnd: () => {\n      this.distanceX = this.tempDistanceX;\n      this.$apply();\n    },\n    movableViewChange: (itemIndex, itemX) => {\n      this.tempDistanceX = new Array(\n        this.examCard[this.currentTab].subjects.unFinished.length\n      ).fill(0);\n      this.tempDistanceX[itemIndex] = itemX * 2;\n      this.$apply();\n    },\n    showchange: index => {\n      // 切换已完成科目的可见状态\n      this.shows[index] = !this.shows[index];\n      setTimeout(this.getClientHeight.bind(this), 200);\n      this.$apply();\n    },\n    down: async (originIndex, coursecode, courseteacher) => {\n      // 手动把一个课程移动到下面 删除\n      wepy.showLoading({\n        title: \"发起删除课程请求\"\n      });\n      const res = await strikeOutYourExam(coursecode, encodeURI(courseteacher));\n      wepy.hideLoading();\n      if (res.data) {\n        // 删除成功\n        this.rawSubjects[`fetchdata${this.currentTab + 1}`][\n          originIndex\n        ].enable = false;\n        const { fetchdata1, fetchdata2 } = this.rawSubjects;\n        this.initFetchData(fetchdata1, fetchdata2);\n        this.initShowAndX();\n        this.getClientHeight();\n        wepy.showToast({\n          title: \"删除课程成功\",\n          icon: \"none\",\n          duration: 2000\n        });\n        this.$apply();\n      } else {\n        wepy.showToast({\n          title: \"删除课程失败，请重试\",\n          icon: \"none\",\n          duration: 2000\n        });\n      }\n    },\n    up: async (originIndex, coursecode, courseteacher) => {\n      // 手动把一个课程移到上面 恢复\n      wepy.showLoading({\n        title: \"加载中\"\n      });\n      const res = await restoreYourOwnExam(\n        coursecode,\n        encodeURI(courseteacher)\n      );\n      wepy.hideLoading();\n      if (res.data) {\n        this.rawSubjects[`fetchdata${this.currentTab + 1}`][\n          originIndex\n        ].enable = true;\n        const { fetchdata1, fetchdata2 } = this.rawSubjects;\n        this.initFetchData(fetchdata1, fetchdata2);\n        this.initShowAndX();\n        this.getClientHeight();\n        wepy.showToast({\n          title: \"恢复课程成功\",\n          icon: \"none\",\n          duration: 2000\n        });\n      } else {\n        wepy.showToast({\n          title: \"恢复课程失败，请重试\",\n          icon: \"none\",\n          duration: 2000\n        });\n      }\n      this.$apply();\n    },\n    datetimeSelect: (date, begintime, endtime) => {\n      date = date.replace(/-/g, \"/\");\n      const begin = new Date(`${date} ${begintime}`);\n      const end = new Date(`${date} ${endtime}`);\n      this.beginTimestamp = begin.getTime();\n      this.duration = (end.getTime() - begin.getTime()) / 1000 / 60; // 分钟\n    }\n  };\n  watch = {\n    currentTab() {\n      this.methods.toggle.call(this);\n    }\n  };\n  methods = {\n    toggle() {\n      const animation = wepy.createAnimation({\n        duration: 200,\n        timingFunction: \"ease-out\"\n      });\n      this.toggleAnimation = animation\n        .translateX(`${this.currentTab !== 0 ? -100 : 0}vw`)\n        .step()\n        .export();\n      this.$apply();\n    },\n    addModal() {\n      // 打开添加课程Moal\n      this.$invoke(\"QyModal\", \"open\");\n    },\n    handleInput(e) {\n      this[e.target.dataset.input] = e.detail.value;\n    },\n    stopTouchMove() {\n      return false;\n    },\n    async handleSwiperChange(e) {\n      if (this.currentTab === e.target.dataset.current) {\n        return false;\n      } else {\n        this.currentTab = e.target.dataset.current;\n        this.initShowAndX();\n        this.getClientHeight();\n        this.$apply();\n      }\n    },\n    async addSubject() {\n      // 添加课程请求\n      if (this.duration < 0) {\n        wepy.showToast({\n          title: \"考试结束时间必须大于开始时间\",\n          icon: \"none\",\n          duration: 2000\n        });\n      } else {\n        wepy.showLoading({\n          title: \"加载中\"\n        });\n        const res = await addYourOwnExam(\n          this.subject,\n          this.beginTimestamp,\n          String(this.duration),\n          this.teacher,\n          this.room\n        );\n        wepy.hideLoading();\n        if (res.data) {\n          wepy.showToast({\n            title: \"添加成功\",\n            icon: \"none\",\n            duration: 2000\n          });\n          this.$invoke(\"QyModal\", \"close\");\n          this.currentTab = 0;\n          this.fetchData();\n          this.$apply();\n        } else {\n          wepy.showToast({\n            title: \"添加失败\",\n            icon: \"none\",\n            duration: 2000\n          });\n        }\n      }\n    },\n    isQuestionModalVisible(event) {\n      let isVisible = event.currentTarget.dataset.isVisible;\n      if (isVisible) {\n        this.$invoke(\"QyQuestionModal\", \"open\");\n      } else if (!isVisible) {\n        this.$invoke(\"QyQuestionModal\", \"close\");\n      }\n    }\n  };\n  async onLoad(op) {\n    if (op) {\n      // 如果非下拉刷新，就判断模块是否已关闭\n      await this.judgeStatus(op.name);\n    }\n    wepy.showLoading({\n      title: \"加载中\"\n    });\n    // const cache = wepy.getStorageSync(\"cutdown\");\n    // if (cache) {\n    //   // 如果有缓存就先显示缓存里的，最终都会重新从后端获取\n    //   this.rawSubjects = cache;\n    //   const { fetchdata1, fetchdata2 } = this.rawSubjects;\n    //   this.initFetchData(fetchdata1, fetchdata2);\n    //   this.$apply();\n    //   this.getCardInfo();\n    //   this.initShowAndX();\n    //   this.getClientHeight();\n    // }\n    this.rawSubjects = await this.fetchData();\n    const { fetchdata1, fetchdata2 } = this.rawSubjects;\n    this.initFetchData(fetchdata1, fetchdata2);\n    this.$apply();\n    this.getCardInfo();\n    this.initShowAndX();\n    this.getClientHeight();\n    wepy.hideLoading();\n  }\n  initFetchData(fetchdata1, fetchdata2) {\n    this.examCard[0].subjects = this.handleFetchData(\n      this.initSubjects(fetchdata1)\n    );\n    this.examCard[1].subjects = this.handleFetchData(\n      this.initSubjects(fetchdata2)\n    );\n    this.$apply();\n  }\n  setFetchDataItem(item) {\n    const backToZero = raw => raw - (raw % 86400000);\n    const diffDay = (t1, t2) => (backToZero(t1) - backToZero(t2)) / 86400000;\n    const fillZero = number => (\"00\" + number).slice(-2);\n    const formatBeginAndEnd = (begin, end) =>\n      `${fillZero(begin.getMonth() + 1)}.${fillZero(\n        begin.getDate()\n      )} ${fillZero(begin.getHours())}:${fillZero(\n        begin.getMinutes()\n      )}-${fillZero(end.getHours())}:${fillZero(end.getMinutes())}`;\n\n    const beginDate = new Date(item.examDate);\n    const endDate = new Date(\n      item.examDate + Number(item.examDuration * 60 * 1000)\n    );\n    const remain = diffDay(item.examDate, Date.now());\n    return {\n      subject: item.courseName, // 考试名称\n      place: item.examPosition, // 考试地点\n      teacher: item.courseTeacher, // 授课老师\n      time: formatBeginAndEnd(beginDate, endDate), // 考试时间格式化后\n      enable: item.enable, // 考试是否被用户手动删除\n      courseCode: item.courseCode, // 考试号\n      examDate: item.examDate, // 考试还有几天\n      remain // 离考试还有几天\n    };\n  }\n  getCardInfo() {\n    for (const examCardItem of this.examCard) {\n      const latelySubject = examCardItem.subjects.unFinished[0];\n      examCardItem.subtitle = latelySubject\n        ? `最近一门：${latelySubject.subject}`\n        : \"考试已经结束了\";\n      examCardItem.remainingTimes = examCardItem.subjects.unFinished.length;\n    }\n    this.$apply();\n  }\n  async initShowAndX() {\n    this.shows = new Array(\n      this.examCard[this.currentTab].subjects.finished.length\n    ).fill(false);\n    this.distanceX = new Array(\n      this.examCard[this.currentTab].subjects.unFinished.length\n    ).fill(0);\n    this.tempDistanceX = new Array(\n      this.examCard[this.currentTab].subjects.unFinished.length\n    ).fill(0);\n    this.$apply();\n  }\n  async getClientHeight() {\n    const query = wepy.createSelectorQuery();\n    query.select(`#swiper-item-${this.currentTab}`).boundingClientRect();\n    query.selectViewport().scrollOffset();\n    query.exec(res => {\n      this.clientHeight = res[0].height + 30;\n      this.$apply();\n    });\n  }\n  async fetchData(force = false) {\n    const result = { fetchdata1: [], fetchdata2: [] };\n    const [selfExamResponse, getYourOwnExamResponse] = await Promise.all([\n      selfExam(),\n      getYourOwnExam(0)\n    ]);\n    if (selfExamResponse.data && selfExamResponse.data.data) {\n      result.fetchdata1 = selfExamResponse.data.data;\n    }\n    if (getYourOwnExamResponse.data && getYourOwnExamResponse.data.data) {\n      result.fetchdata2 = getYourOwnExamResponse.data.data;\n    }\n    // wepy.setStorageSync(\"cutdown\", result);\n    result.fetchdata1 = result.fetchdata1.map(this.setFetchDataItem);\n    result.fetchdata2 = result.fetchdata2.map(this.setFetchDataItem);\n    return result;\n  }\n  initSubjects(rawSubjects) {\n    return (rawSubjects = rawSubjects.map((item, index) => ({\n      ...item,\n      originIndex: index\n    })));\n  }\n  handleFetchData(rawSubjects) {\n    rawSubjects = rawSubjects.filter(x => x.enable);\n    const unFinished = rawSubjects.filter(item => item.remain > -1);\n    const finished = rawSubjects.filter(item => item.remain <= -1);\n\n    // const unFinished = rawSubjects.filter(\n    //   item => item.remain > -1 && item.enable\n    // );\n    // const finished = rawSubjects.filter(\n    //   item => item.remain <= -1 || !item.enable\n    // );\n    unFinished.sort((a, b) => a.examDate - b.examDate);\n    return { unFinished, finished };\n  }\n  computed = {\n    // 考试安排是否已出来\n    hasExam() {\n      const { unFinished, finished } = this.examCard[this.currentTab].subjects;\n      return unFinished.length + finished.length !== 0;\n    }\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n@import '../../css/normal-input'\n.devide-line\n  background-color #f5f5f5\n  width 100vw\n  height 23rpx\n  margin 12.87rpx 0 12.87rpx 0\n\n.container\n  font-family 'SimHei'\n  width 100vw\n  color  #353535\n  overflow hidden\n  .swiper-container\n    display flex\n    // overflow-y hidden\n    .swiper-item\n      width 100vw\n      display flex\n      flex-direction column\n      align-items center\n      height 0%\n      .unfinished-line\n        background-color #f5f5f5\n        width 93vw\n        height 2.5rpx\n        margin 0 auto\n      .text\n        color #353535\n        font-family \"PingFangSC-Medium\"\n        font-size 28rpx\n        font-weight 400\n      .finish-text\n        color #353535\n        font-family \"PingFangSC-Medium\"\n        font-size 28rpx\n        font-weight 400\n        line-height 32rpx\n        margin 10rpx 0 10rpx 54rpx\n        align-self flex-start\n  .select-container\n    position relative\n    // z-index 23\n    .select-title\n      color rgb(53, 53, 53)\n      text-align center\n      font-size 30rpx\n      position relative\n      z-index 22\n      border-radius 30rpx\n      box-shadow 0rpx 3rpx 14rpx 0rpx rgba(0, 0, 0, 0.35)\n      width 524rpx\n      height 71rpx\n      line-height 71rpx\n    .drop\n      width 524rpx\n      height 150rpx\n      display flex\n      flex-direction column\n      position absolute\n      align-items center\n      background-color rgb(255, 255, 255)\n      box-shadow 0rpx 3rpx 14rpx 0rpx rgba(0, 0, 0, 0.35)\n      top 34rpx\n      z-index 20\n      .drop-text\n        font-size 30rpx\n        font-family 'SimHei'\n        color rgb(53, 53, 53)\n        width 100%\n        text-align center\n        &:first-of-type\n          margin 59rpx 0 4rpx\n    .arrow\n      width 45rpx\n      position absolute\n      top 16rpx\n      left 457rpx\n      z-index 30\n  .head-container\n    width 699rpx\n    height 67rpx\n    display flex\n    margin-left 50rpx !important\n    margin 0 auto\n    justify-content space-between\n    align-items center\n    .add\n      width 33rpx\n      height 33rpx\n      padding 33rpx\n  .text\n    font-weight 400\n    color #353535\n    font-family \"PingFangSC-Medium\"\n    font-size 33rpx\n    align-self flex-start\n    margin 10rpx 0 10rpx 0\n\n  .no-image\n    width 400rpx\n    margin-top 129rpx\n  .no-text\n    color #999CA0\n    font-size 28rpx\n    margin-top 55rpx\n    text-align center\n.slot-content\n  display flex\n  flex-direction column\n  align-items center\n  margin-top 56rpx\n  .add-button\n    margin-top 0\n    width 100%\n    background-color #fff\n    border-radius 30rpx\n    // border-bottom 2px solid #fff\n    color  #39C9FF\n    font-size 30rpx\n    text-align center\n    height 94rpx\n    line-height 94rpx\n    border-bottom none !important\n  .add-button::after\n    border-bottom none\n  .space\n    margin-bottom 28rpx\n.question-container\n  width 524rpx\n  height 271rpx\n  border-radius 10rpx\n  background-color white\n  font-size 24rpx\n  font-family 'SimHei'\n  color rgb(0, 0, 0)\n  display flex\n  flex-direction column\n  .bb\n    display flex\n    justify-content space-between\n    line-height 1rem\n    margin 29rpx 42rpx 0\n    .right-container\n      width 290rpx\n    .left-container\n      width 143rpx\n\n  .button\n    border-top 2rpx solid rgb(246, 246, 246)\n    text-align center\n    color #39C9FF\n    font-size 30rpx\n    height 85rpx\n    line-height 85rpx\n.exam-card\n  height 421rpx\n  .exam-card-top\n    height 65rpx\n    position relative\n    .exam-card-top-item.active\n      top 0\n    .exam-card-top-item\n      position absolute\n      top 20%\n      height 65rpx\n      width 210rpx\n      line-height 65rpx\n      text-align center\n      border-radius 15rpx 15rpx 0 0\n      font-size 28rpx\n      transition all 200ms ease-out\n      &:nth-child(1)\n        left 58rpx\n        background-color #7be5d8\n      &:nth-child(2)\n        left 268rpx\n        background-color #ffc65c\n  .swiper-container\n    height 356rpx\n    width 698rpx\n    margin 0 auto\n    swpier-item\n    .exam-card-item\n      height 356rpx\n      width 700rpx\n      background-size 100% 100%\n      text-align center\n      color #353535\n      &:nth-of-type(1)\n        background-image url(\"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LeaIkeeahOiAg+ivlS5wbmc=\")\n        // .subtitle\n        //   background-color rgba(140,251,243,0.9)\n      &:nth-of-type(2)\n        background-image url(\"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LemHkeiJsl8wMy5wbmc=\")\n        // .subtitle\n        //   background-color rgba(250,222,146,0.9)\n      .remaining-times\n        font-size 100rpx\n        padding-top 30rpx\n        height 110rpx\n      .remaining-times-title\n        letter-spacing 10rpx\n        margin 10rpx 0 10rpx 0\n      // .subtitle\n      //   margin-top 10rpx\n      //   width 60%\n      //   display inline-block\n      //   font-size 0.8em\n      //   line-height 50rpx\n      //   border-radius 50rpx\n      .question\n        border-radius 50%\n        width 45rpx\n        height 45rpx\n        position absolute\n        background-image url(\"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LemXruWPt+Wkh+S7vS5wbmc=\")\n        background-size 100% 100%\n        top 20rpx\n        right 20rpx\n</style>\n"
  },
  {
    "path": "src/edu-admin-page/pages/score-inquire.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"成绩查询\" :passwordModelOptions.sync=\"passwordModelOptions\">\n    <view slot=\"qy-content\">\n      <view class=\"cover\" hidden=\"{{!showModal}}\" animation=\"{{coverAnimation}}\">\n      </view>\n      <view class=\"cover-modal\" hidden=\"{{!showModal}}\">\n        <view>排名根据使用小程序用户产生</view>\n        <view>仅供参考，具体请通过辅导员查询</view>\n        <view style=\"color:#47CFF5;margin-top:30rpx\" @tap=\"getRankRule\">知道了</view>\n      </view>\n      <view slot=\"qy-content\" class=\"container\">\n        <view class=\"top-container\">\n          <view class=\"performance-point\">{{GPA}}\n            <view class=\"average-point\">平 均 绩 点</view>\n          </view>\n          <view class=\"rank-thing\" @tap=\"rankQuestion\">\n            <view class=\"ranking\">当前排名：{{rank}}/{{collegeNumber}}</view><view class=\"rank-question\"></view>\n          </view>\n        </view>\n        <view class=\"credit-column\">\n          <view class=\"credit-item\"><view>总学分</view><view class=\"credit-item-score\">{{creditSelected}}</view></view>\n          <view class=\"credit-item\"><view>已修学分</view><view class=\"credit-item-score\">{{creditGained}}</view></view>\n          <view class=\"credit-item\" style=\"border:none\"><view>重修学分</view><view class=\"credit-item-score\">{{creditRetake}}</view></view>\n        </view>\n        <view class=\"divide\"></view>\n        <view style=\"position:relative;\">\n          <view hidden=\"{{loadHide}}\" class=\"hide-container\">\n            <view class=\"boxLoading\"></view>\n          </view>\n          <repeat for=\"{{terms}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"term-card\" data-index=\"{{index}}\" @tap=\"{{hide[index] ? 'showDetails' : 'hideDetails'}}\"><view class=\"term-card-item\">{{item.term}}</view>\n              <image data-index=\"{{index}}\" hidden = \"{{Loading[index]}}\" animation=\"{{spinS[index]}}\" src=\"https://static.airbob.org/under-graduate/image/score/button_down.png\" mode=\"aspectFill\"/>\n              <i class=\"weui-loading\" wx:if=\"{{Loading[index]}}\"/>\n              <view class=\"detail-cover\" id=\"detail{{index}}\" animation=\"{{animationData[index]}}\">\n                <repeat for=\"{{item.course}}\" index=\"INDEX\" key=\"KEY\" item=\"ITEM\">\n                  <view class=\"detail-information\" id=\"detailCourse{{INDEX}}\">\n                    <view class=\"main-info\">\n                      <view class=\"detail-name\">{{ITEM.courseName}}</view>\n                      <view class=\"detail-info\">编号：{{ITEM.courseCode}} 学分{{ITEM.credit}}</view>\n                      <view class=\"detail-info\">成绩：{{ITEM.score}}（正考）\n                        <span wx:if=\"{{ITEM.resitScore !== ''}}\">{{ITEM.resitScore}}（补考）</span>\n                        <span wx:if=\"{{ITEM.retakeScore !== ''}}\">{{ITEM.retakeScore}}（重修）</span>\n                        </view>\n                    </view>\n                    <view class=\"credit-info\">{{ITEM.point}}</view>\n                  </view>\n                </repeat>\n              </view>\n            </view>\n          </repeat>\n          <view hidden=\"{{terms[0] || !loadHide}}\">\n            <view class=\"image-container\">\n              <image src=\"https://static.airbob.org/under-graduate/%E7%BC%BA%E7%9C%81%E9%A1%B5_%E7%A9%BA.png\" style=\"width:400rpx;height:300rpx\" mode=\"aspecfFit\"/>\n            </view>\n            <view class=\"words\">大学生活刚刚开始，加油～</view>\n          </view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n<script>\nimport wepy from \"wepy\";\nimport { changeSecretCode } from \"@/api/common\";\nimport JudgeStatus from \"@/mixins/module\";\nimport { getUserGrade, rankingSelf } from \"@/api/education\";\nimport { mockGetUserGrade } from \"@/mock/education\";\nimport GpaMixin from \"../../mixins/Gpa/Gpa\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport { connect } from \"wepy-redux\";\n\n@connect({\n  graduateIdentity(state) {\n    return state.graduateReducer.graduateIdentity;\n  }\n})\nexport default class Score extends wepy.page {\n  config = {\n    navigationBarTitleText: \"成绩查询\"\n  };\n  data = {\n    GPA: \"0\",\n    creditRetake: \"0\",\n    creditGained: \"0\",\n    creditSelected: \"0\",\n    showModal: false,\n    Loading: [],\n    hide: [],\n    terms: [],\n    animationData: [],\n    coverAnimation: {},\n    alreadyTap: false,\n    screenWidth: \"\",\n    dealedHeight: 0,\n    collegeNumber: 0,\n    rank: \"\",\n    loadHide: false,\n    spinS: [],\n    placeholder: \"\",\n    passwordModelOptions: {\n      passwordModelProps: false,\n      placeholder: \"正方密码\",\n      refreshData: this.init,\n      bindInfo: {\n        username: wepy.getStorageSync(\"User\").studentId,\n        domainType: \"1\"\n      }\n    },\n    visitorModeStatus: false\n  };\n  components = {\n    BaseContainer\n  };\n  mixins = [JudgeStatus, GpaMixin];\n  changeModuleStatus(status) {\n    let that = this;\n    return new Promise(resolve => {\n      that.showModal = status;\n      resolve();\n    });\n  }\n  methods = {\n    bindCardPassword(e) {\n      this.bindInputPassword = e.detail.value;\n    },\n    async rankQuestion() {\n      let that = this;\n      await that.changeModuleStatus(true);\n      setTimeout(() => {\n        let coverAnimation = wepy.createAnimation({\n          duration: 500\n        });\n        coverAnimation.opacity(0.5).step();\n        that.coverAnimation = coverAnimation.export();\n        that.$apply();\n      }, 0);\n    },\n    async getRankRule() {\n      let that = this;\n      await that.changeModuleStatus(false);\n      setTimeout(() => {\n        let coverAnimation = wepy.createAnimation({\n          duration: 500\n        });\n        coverAnimation.opacity(0).step();\n        that.coverAnimation = coverAnimation.export();\n        that.$apply();\n      }, 0);\n    },\n    async showDetails(e) {\n      let that = this;\n      let index = e.currentTarget.dataset.index;\n      that.hide[index] = false;\n      that.alreadyTap = true;\n      that.Loading[index] = true;\n      await that.Fold(that.terms[index]);\n      that.$apply();\n      that.Loading[index] = false;\n      that.dealedHeight = 0;\n      that.dealHeight(index).then(() => {\n        let query = wepy.createSelectorQuery();\n        let Ind = \"#\" + \"detail\" + index.toString();\n        query.select(Ind).boundingClientRect();\n        query.exec(function(res) {\n          let transHeight = that.dealedHeight / that.screenWidth;\n          let showOff = wepy.createAnimation({\n            duration: 1000,\n            timingFunction: \"ease\"\n          });\n          let spin = wepy.createAnimation({\n            duration: 300,\n            timingFunction: \"ease\"\n          });\n          setTimeout(() => {\n            spin.rotate(-180).step();\n            that.spinS[index] = spin.export();\n            showOff.height(transHeight + \"rpx\").step();\n            that.animationData[index] = showOff.export();\n            that.$apply();\n          }, 0);\n        });\n      });\n    },\n    hideDetails(e) {\n      let index = e.currentTarget.dataset.index;\n      this.hide[index] = true;\n      this.terms[index].unfold = true;\n      let showAnimation = wepy.createAnimation({\n        duration: 500,\n        timingFunction: \"ease-out\"\n      });\n      let spin = wepy.createAnimation({\n        duration: 300,\n        timingFunction: \"ease\"\n      });\n      showAnimation.height(0 + \"rpx\").step();\n      spin.rotate(0).step();\n      this.spinS[index] = spin.export();\n      this.animationData[index] = showAnimation.export();\n      this.$apply();\n      this.animationData = [];\n    }\n  };\n  Fold(e) {\n    return new Promise(resolve => {\n      e.unfold = false;\n      resolve();\n    });\n  }\n  dealHeight(ind) {\n    let that = this;\n    return new Promise(resolve => {\n      setTimeout(() => {\n        for (let i in that.terms[ind].course) {\n          let newquery = wepy.createSelectorQuery();\n          let index = \"#\" + \"detailCourse\" + i.toString();\n          newquery.select(index).boundingClientRect();\n          newquery.exec(function(res) {\n            if (!res[0]) {\n              that.dealedHeight = 0;\n              return that.dealHeight(ind);\n            }\n            that.dealedHeight += res[0].height;\n          });\n        }\n        that.$apply();\n        resolve(that.dealedHeight);\n      }, 0);\n    });\n  }\n  forEachTerm(ITEM) {\n    let that = this;\n    return new Promise(resolve => {\n      ITEM.forEach((item, index) => {\n        let detailTerm =\n          item.year +\n          \" \" +\n          `第${(item.term === 1 || item.term) === \"1\" ? \"一\" : \"二\"}学期`;\n        let judge = that.terms.find(course => course.term === detailTerm);\n        if (judge === undefined || judge === \"undefined\") {\n          that.terms.unshift({\n            term: detailTerm,\n            course: [item],\n            unfold: true\n          });\n        } else {\n          judge.course.push(item);\n        }\n      });\n      resolve();\n    });\n  }\n  async init() {\n    await wepy.getSystemInfo().then(res => {\n      this.screenWidth = parseFloat(res.screenWidth / 750);\n    });\n    let res = this.visitorModeStatus\n      ? await mockGetUserGrade()\n      : await getUserGrade();\n    if (!res.data.data) {\n      this.passwordModelOptions.passwordModelProps = true;\n    } else {\n      let data = res.data.data;\n      const { studentId } = wepy.getStorageSync(\"User\");\n      if (this.graduateIdentity) {\n        const { credits } = this.handleScores(\n          res.data.data.score.sort(\n            (x, y) =>\n              Number(x.year.substring(0, 4)) - Number(y.year.substring(0, 4)) ||\n              Number(x.term) - Number(y.term)\n          )\n        );\n        let reTakeScore;\n        const reTakeData = res.data.data.score.filter(item => item.retakeScore);\n        if (reTakeData.length !== 0) {\n          reTakeScore = reTakeData.reduce(\n            (x, y) => Number(x.credit) + Number(y.credit)\n          );\n        } else {\n          reTakeScore = 0;\n        }\n        this.creditGained = credits;\n        this.creditSelected = credits + reTakeScore;\n        this.creditRetake = reTakeScore;\n      } else {\n        this.creditGained = data.creditGained;\n        this.creditSelected = data.creditSelected;\n        this.creditRetake = data.creditRetake === \"\" ? \"0\" : data.creditRetake;\n      }\n      this.loadHide = true;\n      let allScore = data.score;\n      await this.forEachTerm(allScore);\n      this.GPA = data.gpa;\n    }\n    if (!this.visitorModeStatus) {\n      const rankRes = await rankingSelf();\n      this.rank = Number(rankRes.data.data.rank) + 1;\n      this.collegeNumber = rankRes.data.data.total;\n    } else {\n      this.rank = \"100\";\n      this.collegeNumber = 200;\n    }\n    if (this.terms.length === 0) {\n      this.GPA = \"-.--\";\n      this.ranl = \"-\";\n    } else {\n      for (let i = 0; i < this.terms.length; i++) {\n        this.Loading.push(false);\n        this.hide.push(true);\n      }\n    }\n    this.$apply();\n  }\n  async onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name).then(() => {\n      this.init();\n    });\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n@import '../../css/loading'\n.hide-container\n  margin 200rpx auto\n.cover\n  position fixed\n  width 100vw\n  height 100vh\n  background rgb(0, 0, 0)\n  opacity 0\n  z-index 100000\n.cover-modal\n  position absolute\n  margin 0 auto\n  width 500rpx\n  left 125rpx\n  padding 20rpx\n  top 40vh\n  background #fff\n  z-index 100000\n  border-radius 10rpx\n  font-size 28rpx\n  text-align center\n.weui-loading\n  margin 0 5px\n  width 20px\n  height 20px\n  display inline-block\n  vertical-align middle\n  animation spin 1s steps(12) infinite\n  background transparent url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=') no-repeat\n  background-size 100%\n  @keyframes spin\n    0%\n      transform rotate(0deg)\n    to\n      transform rotate(1turn)\n.top-container\n  width 750rpx\n  height 350rpx\n  text-align center\n  background-image url('https://static.airbob.org/under-graduate/image/score/score_pic_card.png')\n  background-position center\n  background-repeat no-repeat\n  background-size contain\n  color #fff\n  .performance-point\n    font-size 120rpx\n    padding-top 40rpx\n    .average-point\n      font-size 30rpx\n      margin-bottom 20rpx\n      margin-top -20rpx\n  .rank-thing\n    display flex\n    width 400rpx\n    align-items center\n    justify-content center\n    margin 0 auto\n    .ranking\n      font-size 30rpx\n      width 300rpx\n      padding 0 20rpx\n      background #5ED6F7\n      border-radius 40rpx\n    .rank-question\n      width 30rpx\n      height 30rpx\n      background-image url('https://static.airbob.org/under-graduate/image/score/pic_why.png')\n      background-position center\n      background-repeat no-repeat\n      background-size contain\n.rank-question-modal\n  text-align center\n  margin 0 auto\n.credit-column\n  padding 24rpx 60rpx\n  display flex\n  justify-content space-around\n  align-items center\n  font-size 30rpx\n  color #888888\n  text-align center\n  .credit-item\n    width 33%\n    border-right 1rpx solid #E3F3E3\n    .credit-item-score\n      color #353535\n      font-size 36rpx\n.divide\n  height 25rpx\n  width 750rpx\n  background #F5F5F5\n.term-card\n  position relative\n  background #FFFFFF\n  box-shadow 0 0 20rpx 0 rgba(0, 0, 0, 0.05)\n  border-radius 20rpx\n  margin-top 30rpx\n  margin-left 42rpx\n  width 665rpx\n  line-height 90rpx\n  font-size 28rpx\n  color #353535\n  .term-card-item\n    display inline-block\n    width 570rpx\n    padding-left 30rpx\n  .detail-cover\n    position relative\n    width 665rpx\n    height 0rpx\n    border-bottom-left-radius 20rpx\n    border-bottom-right-radius 20rpx\n    box-shadow 0 0 20rpx 0 rgba(0, 0, 0, 0.05)\n    overflow hidden\n    .detail-information\n      position relative\n      display flex\n      margin-left 30rpx\n      margin-right 30rpx\n      border-top 1rpx solid #E3E3E3\n      align-items center\n      .main-info\n        width 550rpx\n        margin 30rpx 0rpx\n        .detail-name\n          line-height 50rpx\n          margin 10rpx 0rpx\n          font-size 35rpx\n        .detail-info\n          line-height 40rpx\n          font-size 24rpx\n          margin 10rpx 0rpx\n  .credit-info\n    font-size 50rpx\n    font-weight bold\n  image\n    width 34rpx\n    height 20rpx\n.image-container\n  padding-top 120rpx\n  width 400rpx\n  height 300rpx\n  margin 0 auto\n.words\n  margin-top 50rpx\n  text-align center\n  font-family PingFangSC-Regular\n  font-size 28rpx\n  color #999CA0\n  letter-spacing 0.11rpx\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 485rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n"
  },
  {
    "path": "src/edu-admin-page/pages/search-course.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"search-bar\">\n      <image src=\"https://static.airbob.org/under-graduate/magnifying glass.png\" class=\"search-icon\">\n        <input type=\"text\" class=\"search-input\" placeholder=\"老师名字/课程名\" placeholder-style=\"color:#fff;\" @input=\"searchConfirm\" value=\"{{search}}\">\n    </view>\n    <view class=\"search-list\" wx:if=\"{{search&&searchList.length}}\">\n      <repeat for=\"{{searchList}}\" index=\"index\" item=\"item\" key=\"key\">\n        <view class=\"list-item\" data-item=\"{{item}}\" @tap=\"searchCourses\">\n          <repeat for=\"{{item.keyArray}}\" item=\"text\" key=\"textKey\">\n            <text class=\"{{text == search ? 'text-highlight' : '' }}\">{{text}}</text>\n          </repeat>\n        </view>\n      </repeat>\n    </view>\n    <view class=\"search-content\" hidden=\"{{!courses.length}}\">\n      <view class=\"search-status\" hidden=\"{{!searchInfo}}\">通过搜索“{{searchInfo}}”检索到的课程：</view>\n      <repeat for=\"{{courses}}\" index=\"index\" item=\"item\" key=\"key\">\n        <view class=\"course-item\" style=\"background:{{item.bgc}};\">\n          <view class=\"course-detail\">\n            <view class=\"course-name\">{{item.name}}</view>\n            <view class=\"course-info\">\n              <span>老师：</span> {{item.teacher}}\n            </view>\n            <view class=\"course-info\">\n              <span>教室：</span> {{item.locale}}\n            </view>\n            <view class=\"course-info\">\n              <span>上课周数：</span> {{item.week}}\n            </view>\n            <view class=\"course-info\">\n              <span>上课时间：</span> {{item.day}}\n            </view>\n          </view>\n          <image src=\"https://static.airbob.org/under-graduate/course-add.png\" class=\"add-icon\" data-coursesid=\"{{item.coursesId}}\" @tap=\"addNewCourse\">\n        </view>\n      </repeat>\n    </view>\n    <view class=\"search-blank\" hidden=\"{{courses.length||search}}\">快搜搜看自己喜欢的老师都上什么课吧！</view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  import ClassMixin from \"@/mixins/class.js\";\n  import navigation from \"@/components/qy-navigation\";\n  import {\n    searchList,\n    queryCoursesByteacher,\n    queryCoursesByCourse,\n    addCourse\n  } from \"@/api/education\";\n  export default class SearchCourse extends wepy.page {\n    config = {\n      navigationBarTitleText: \"搜课\"\n    };\n    mixins = [ClassMixin];\n    data = {\n      navTitle: \"搜课\",\n      search: \"\", // 输入框中输入的信息\n      searchInfo: \"\", // 调用接口时传入的key值（完整的课程名/教师名）\n      courses: [],\n      allCourses: [],\n      searchList: [],\n      timer: null\n    };\n    components = {\n      \"qy-navigation\": navigation\n    };\n    methods = {\n      addNewCourse(e) {\n        let coursesId = e.currentTarget.dataset.coursesid;\n        let course = [];\n        for (let key in this.allCourses) {\n          if (key === coursesId) {\n            course[key] = this.allCourses[key];\n            addCourse(course).then(res => {\n              if (res.data && res.data.data) {\n                wepy.setStorageSync(\"courseRoute\", \"canRefresh\");\n                wepy.showToast({\n                  title: \"添加成功\",\n                  icon: \"success\",\n                  duration: 2000\n                });\n              } else {\n                wepy.showToast({\n                  title: \"添加失败！\",\n                  icon: \"none\",\n                  mask: true\n                });\n              }\n            });\n          }\n        }\n      },\n      searchConfirm(e) {\n        let search = e.detail.value;\n        this.search = search;\n      }\n    };\n    watch = {\n      search() {\n        this.searchInfo = \"\";\n        this.searchList = [];\n        this.courses = [];\n        this.throttle(\n          this.returnSearchList(encodeURIComponent(this.search)),\n          200\n        );\n      }\n    };\n    returnSearchList(search) {\n      searchList(search).then(res => {\n        if (res.data && res.data.data.length) {\n          let searchList = res.data.data;\n          searchList.map(item => {\n            item.keyArray = this.getHilightStrArray(item.key, search);\n          });\n          this.searchList = searchList;\n        } else {\n          this.searchInfo = decodeURIComponent(search);\n        }\n        this.$apply();\n      });\n    }\n    throttle(method, delay) {\n      return function() {\n        var context = this,\n          args = arguments;\n        clearTimeout(this.timer);\n        this.timer = setTimeout(function() {\n          method.apply(context, args);\n        }, delay);\n      };\n    }\n    searchCourses(e) {\n      const item = e.currentTarget.dataset.item;\n      let searchInfo = item.key;\n      const type = item.type;\n      wepy.showLoading({\n        title: \"搜索中\"\n      });\n      if (type === \"teacherName\") {\n        queryCoursesByteacher(searchInfo).then(res => {\n          this.setCourses(res);\n          wepy.hideLoading();\n        });\n      } else if (type === \"course\") {\n        queryCoursesByCourse(searchInfo).then(res => {\n          this.setCourses(res);\n          wepy.hideLoading();\n        });\n      }\n      this.searchList = [];\n      this.searchInfo = searchInfo;\n      this.$apply();\n    }\n    changeNumber(num) {\n      const num1 = [1, 2, 3, 4, 5, 6, 7];\n      const num2 = [\"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"日\"];\n      for (let i in num1) {\n        if (num === num1[i]) {\n          return num2[i];\n        }\n      }\n    }\n    handleCourseItem(courseItem) {\n      let course = [];\n      let week = [];\n      let day = [];\n      const { locale, name, teacher } = courseItem[0];\n      courseItem.map(item => {\n        week.push(item.week);\n        day.push(\n          \"周\" +\n            this.changeNumber(item.day) +\n            String(item.sectionstart) +\n            String(item.sectionend) +\n            \"节\"\n        );\n      });\n      course = {\n        locale,\n        name,\n        teacher,\n        week: week.join(\"|\"),\n        day: day.join(\"|\")\n      };\n      return course;\n    }\n    setCourses(res) {\n      if (res.data.data) {\n        this.allCourses = res.data.data;\n        let course = [];\n        let courses = [];\n        for (let key in res.data.data) {\n          course = this.handleCourseItem(res.data.data[key].timetable);\n          course.coursesId = key;\n          courses.push(course);\n        }\n        this.courses = this.getColor(courses);\n        this.$apply();\n      }\n    }\n    getHilightStrArray(str, key) {\n      return str.replace(new RegExp(`${key}`, \"g\"), `%%${key}%%`).split(\"%%\");\n    }\n    onLoad() {\n      this.$apply();\n    }\n  }\n</script>\n\n<style lang=\"stylus\" type=\"text/stylus\" scoped>\n.container\n  width 100%\n  height 100%\n  color #fff\n  font-size 30rpx\n  .search-list\n    width calc(100% - 50rpx)\n    height 100%\n    background #fff\n    display flex\n    flex-direction column\n    align-items center\n    margin 24rpx 25rpx\n    .list-item\n      width calc(100% - 50rpx)\n      color #353535\n      height 83rpx\n      font-size 32rpx\n      line-height 83rpx\n      border-bottom solid 2rpx #e3e3e3\n      padding 0 24rpx\n      overflow hidden\n      text-overflow ellipsis\n      white-space nowrap\n      .text-highlight\n        font-weight bold\n  .search-content\n    display flex\n    flex-direction column\n    align-items center\n    .search-status\n      width calc(100% - 60rpx)\n      color #4a4a4a\n      margin 24rpx 0 9rpx 0\n    .course-item\n      width calc(100% - 60rpx)\n      height 281rpx\n      margin 15rpx 0\n      border-radius 20rpx\n      box-shadow 5rpx 5rpx 5rpx 0rpx rgba(0, 0, 0, 0.1)\n      padding 26rpx 32rpx 30rpx 30rpx\n      box-sizing border-box\n      position relative\n      display flex\n      align-items center\n      .course-detail\n        height 100%\n        display flex\n        flex-direction column\n        justify-content space-between\n        .course-name\n          font-weight 700\n        .course-info\n          font-size 28rpx\n          letter-spacing 1rpx\n      .add-icon\n        width 50rpx\n        height 50rpx\n        position absolute\n        right 32rpx\n  .search-blank\n    color #4a4a4a\n    width 270rpx\n    margin 0 auto\n    margin-top 40vh\n.search-bar\n  display flex\n  align-items center\n  justify-content center\n  box-shadow 0px 4px 5px 0px rgba(0, 0, 0, 0.1)\n  padding 24rpx 60rpx 30rpx 60rpx\n  position relative\n  .search-icon\n    height 30rpx\n    width 30rpx\n    position absolute\n    left 198rpx\n    z-index 2\n    margin-right 23rpx\n  .search-input\n    width 100%\n    background #5bcfe6\n    height 60rpx\n    border-radius 50rpx\n    font-size 28rpx\n    text-align center\n    padding 0 180rpx\n</style>\n"
  },
  {
    "path": "src/edu-admin-page/pages/supplement-and-tutorials.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"辅导课\">\n    <view slot=\"qy-content\">\n      <view>\n        <view class=\"head\">\n          <text class=\"title\">你一共挂了{{credit}}个学分</text>\n        </view>\n        <view class=\"button-list\">\n          <view\n            @tap.stop=\"toTutorials\"\n            class=\"button-common {{current==='tutorials'?'button-active':null}}\"\n          >考前辅导</view>\n          <view\n            @tap.stop=\"toSupplements\"\n            class=\"button-common {{current==='supplements'?'button-active':null}}\"\n          >补考安排</view>\n        </view>\n        <!-- <view class=\"line\" /> -->\n        <view class=\"card-list\">\n          <repeat\n            wx:if=\"{{current==='tutorials'}}\"\n            for=\"{{tutorials}}\"\n            key=\"index\"\n            index=\"index\"\n            item=\"item\"\n          >\n            <card1\n              :item.sync=\"item\"\n              :bg.sync=\"bg[index % 4]\"\n              showbg=\"https://static.airbob.org/under-graduate/%E8%BE%85%E5%AF%BC%E8%AF%BE.png\"\n            />\n          </repeat>\n          <repeat\n            wx:if=\"{{current==='supplements'}}\"\n            for=\"{{supplements}}\"\n            key=\"index\"\n            index=\"index\"\n            item=\"item\"\n          >\n            <card2\n              :item.sync=\"item\"\n              :bg.sync=\"bg[index % 4]\"\n              showbg=\"https://static.airbob.org/under-graduate/%E8%AF%95%E5%8D%B7.png\"\n            />\n          </repeat>\n          <view wx:if=\"{{supplements.length === 0}}\">\n            <image\n              class=\"no-image\"\n              mode=\"widthFix\"\n              src=\"https://static.airbob.org/under-graduate/%E8%BE%B9%E7%95%8C%E6%83%85%E5%86%B52.png\"\n            >\n            <view class=\"no-text\">你不需要补考哦</view>\n          </view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport card from \"../components/card\";\nimport JudgeStatus from \"@/mixins/module\";\nimport { getUserGrade, getSupplyment, getYourOwnExam } from \"@/api/education\";\nimport {\n  mockGetUserGrade,\n  mockGetSupplyment,\n  mockGetYourOwnExam\n} from \"@/mock/education\";\nimport BaseContainer from \"@/components/baseContainer\";\n\n// import QyNav from \"@/components/qy-navigation\";\nexport default class SupplementAndTutorials extends wepy.page {\n  // 辅导课和补考查询页面\n  components = {\n    card1: card,\n    card2: card,\n    BaseContainer\n    // QyNav,\n  };\n  config = {\n    navigationBarTitleText: \"辅导课\" // \"补考\"\n  };\n  mixins = [JudgeStatus];\n  data = {\n    credit: 0,\n    current: \"tutorials\", // or supplements补考\n    supplements: [\n      // {\n      //   courseName: \"微型计算机原理与接口技术\",\n      //   courseTeacher: \"薛明XXXXXXXXXXX\",\n      //   examPosition: \"3-203\",\n      //   examDate: \"2018.3.14\"\n      // }\n    ],\n    tutorials: [\n      // {\n      //   courseName: \"C语言\",\n      //   courseTeacher: \"xxxXXXXXXXXXXXXXXXXXXXXX\",\n      //   examPosition: \"3-221\",\n      //   examDate: \"2018.2.14\"\n      // }\n    ],\n    bg: [\n      \"https://static.airbob.org/under-graduate/supplementary/bg1.png\",\n      \"https://static.airbob.org/under-graduate/supplementary/bg2.png\",\n      \"https://static.airbob.org/under-graduate/supplementary/bg3.png\",\n      \"https://static.airbob.org/under-graduate/supplementary/bg4.png\"\n    ],\n    visitorModeStatus: false\n  };\n  onLoad(option) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(option.name).then(() => {\n      if (option.name === \"辅导课查询\") {\n        option.title = \"tutorials\";\n      } else if (option.name === \"补考查询\") {\n        option.title = \"supplements\";\n      }\n      this.current = option.title;\n      const title = option.title === \"tutorials\" ? \"辅导课查询\" : \"补考查询\";\n      this.navTitle = title;\n      this.getData();\n      this.$apply();\n    });\n  }\n  methods = {\n    toTutorials() {\n      if (this.current !== \"tutorials\") {\n        this.navTitle = \"辅导课查询\";\n        this.current = \"tutorials\";\n        this.$apply();\n      }\n    },\n    toSupplements() {\n      if (this.current !== \"supplements\") {\n        this.navTitle = \"补考查询\";\n        this.current = \"supplements\";\n        this.$apply();\n      }\n    }\n  };\n  judgeApi(cmd) {\n    switch (cmd) {\n      case \"getUserGrade\":\n        return this.visitorModeStatus ? mockGetUserGrade() : getUserGrade();\n        break;\n      case \"getSupplyment\":\n        return this.visitorModeStatus ? mockGetSupplyment() : getSupplyment();\n        break;\n      case \"getYourOwnExam\":\n        return this.visitorModeStatus\n          ? mockGetYourOwnExam()\n          : getYourOwnExam(1);\n        break;\n      default:\n        break;\n    }\n  }\n  getData() {\n    // 获取挂了的学分\n    this.judgeApi(\"getUserGrade\").then(res => {\n      if (res.data) {\n        this.credit =\n          Number(res.data.data.creditSelected) -\n          Number(res.data.data.creditGained);\n        this.$apply();\n      }\n    });\n\n    // 获取辅导课\n    this.judgeApi(\"getSupplyment\").then(res => {\n      if (res.statusCode === 200) {\n        if (res.data.data != null) {\n          const requestData = res.data.data.map(x => {\n            const year = x.courseDate.split(\"年\")[0];\n            const month = x.courseDate.split(\"年\")[1].split(`月`)[0];\n            const day = x.courseDate\n              .split(\"年\")[1]\n              .split(`月`)[1]\n              .split(`日`)[0];\n            const times = x.courseDate\n              .split(\"年\")[1]\n              .split(`月`)[1]\n              .split(`日`)[1];\n            const time = times.substring(1, times.length - 1);\n            const formatDate = `${year}.${month}.${day}`;\n            x.examDate = formatDate;\n            x.examPosition = x.coursePosition;\n            x.examTime = `${time}`;\n            return x;\n          });\n          this.tutorials = requestData;\n          // 9月3日（8:00-11:00）\n          this.$apply();\n        }\n      }\n    });\n    // 获取补考\n    this.judgeApi(\"getYourOwnExam\").then(res => {\n      if (res.statusCode === 200) {\n        const requestData = res.data.data;\n        const formatData = requestData.map(x => {\n          let formatDate = new Date(x.examDate);\n          let minute =\n            formatDate.getMinutes() === 0 ? \"00\" : formatDate.getMinutes();\n          const examTime = `${formatDate.getHours()}:${minute}`;\n          formatDate = `${formatDate.getFullYear()}年${formatDate.getMonth() +\n            1}月${formatDate.getDate()}日`;\n          x.examDate = formatDate;\n          x.examTime = examTime;\n          return x;\n        });\n        this.supplements = formatData;\n      }\n    });\n  }\n}\n</script>\n<style lang=\"stylus\" scoped>\n.head\n  background-image url('https://static.airbob.org/under-graduate/supplementary/head.png')\n  background-size contain\n  height 243rpx\n  display flex\n  justify-content center\n  .title\n    font-family 'DengXian'\n    font-size 44rpx\n    margin-top 50rpx\n.button-list\n  display flex\n  justify-content space-between\n  width 381rpx\n  margin 0 auto\n  .button-common\n    width 157rpx\n    height 63rpx\n    line-height 63rpx\n    font-size 30rpx\n    text-align center\n    border-radius 33rpx\n    font-family 'SimHei'\n    background-color white\n    background-image url('https://static.airbob.org/under-graduate/supplementary/%E6%8C%89%E9%92%AE%E8%99%9A%E7%BA%BF.png')\n    background-size contain\n    background-repeat no-repeat\n    color rgb(53, 53, 53)\n    cursor pointer\n  .button-active\n    background-color rgb(101, 205, 230)\n    color rgb(255, 255, 255)\n    background-image none\n.no-image\n  width 400rpx\n  margin-top 129rpx\n.no-text\n  color #999CA0\n  font-size 28rpx\n  margin-top 55rpx\n  text-align center\n.card-list\n  display flex\n  align-items center\n  flex-direction column\n  border-top 4rpx dotted rgb(126, 226, 255)\n  width 86%\n  margin 36rpx auto 0\n  padding-top 30rpx\n</style>\n\n\n"
  },
  {
    "path": "src/mixins/Gpa/Gpa.js",
    "content": "import wepy from \"wepy\";\nimport {\n  sumCredits,\n  termReducer,\n  sumCreditMultiplyPoint,\n  handleSum,\n  handleTerm\n} from \"./utils\";\n\nexport default class GpaMixin extends wepy.mixin {\n  /**\n   * 处理成绩的逻辑\n   * @param { Array } scores 各学期所有的成绩\n   */\n  handleScores(scores) {\n    if (this.hasData()) {\n      return {\n        credits: sumCredits(),\n        scores: termReducer(),\n        sumOfCreditMultiplyPoint: sumCreditMultiplyPoint() // 获取总的 [学分 * 绩点]\n      };\n    }\n    for (let i = 0; i < scores.length; i++) {\n      const score = scores[i];\n      /**\n       *  isEnd 判断是否是 最后一条成绩的记录\n       *  用于判断是否到了累加最后一个学期的所有成绩的时候\n       */\n      let isEnd = false;\n      if (i === scores.length - 1) isEnd = true;\n      handleSum(score);\n      handleTerm(score, isEnd);\n    }\n    return {\n      credits: sumCredits(),\n      scores: termReducer(),\n      sumOfCreditMultiplyPoint: sumCreditMultiplyPoint() // 获取总的 [学分 * 绩点]\n    };\n  }\n\n  /**\n   * 处理绩点变动的逻辑，关注两个关键量\n   * sumOfCreditMultiplyPoint 总（学分 * 单科绩点）的变化量\n   * credits 总学分 的变化量\n   */\n  handleModifyScore(sumOfCreditMultiplyPoint, credits) {\n    this.sumOfCreditMultiplyPoint += sumOfCreditMultiplyPoint;\n    this.credits += credits;\n  }\n\n  processScoreInput({ value: score }, type) {\n    score = this.discardUnnecessaryChars(score);\n    score = this.limitScore(score);\n    score = score.length === 0 ? 0 : score;\n    this.$emit(type, this.$index, score);\n    return score;\n  }\n\n  discardUnnecessaryChars(value) {\n    return value.replace(/[^\\d.]/g, \"\");\n  }\n\n  limitScore(score) {\n    if (Number(score) > 100) {\n      // 如果 score 大于 100，截断后面的\n      if (Number(score.slice(0, 3)) === 100) {\n        score = score.slice(0, 3);\n      } else {\n        score = score.slice(0, 2);\n      }\n    }\n    return score;\n  }\n\n  hasData() {\n    return sumCredits() !== 0;\n  }\n}\n"
  },
  {
    "path": "src/mixins/Gpa/utils.js",
    "content": "// 延迟计算\nconst curry = (fn, ...optionalArgs) => {\n  const cache = [];\n  return (...args) => {\n    if (args.length === 0) return fn(cache, ...optionalArgs);\n    else cache.push(args[0]);\n  };\n};\n\nconst sum = ary => {\n  let result = 0;\n  for (const value of ary) result += Number(value);\n\n  return result;\n};\n\n/**\n * 累加单个学期的成绩\n * @param { Array }   scores  成绩对象的数组\n * @param { string }  year    年份\n * @param { string }  term    学期\n */\nconst reduceScores = (scores, year, term) => {\n  /**\n   * 返回一个对象\n   * title 显示在卡片顶部的标题\n   * courses 具体的课程成绩\n   */\n  const termScores = {\n    title: `${year}学年 第${Number(term) === 1 ? `一` : `二`}学期`,\n    scores: [],\n    isFolded: true,\n    count: 0\n  };\n\n  for (const score of scores) {\n    termScores.scores.push(score);\n  }\n\n  termScores.scores.sort((a, b) => Number(b.credit) - Number(a.credit));\n  termScores.count = termScores.scores.length;\n\n  return termScores;\n};\n\n/**\n * 累加各学期的成绩\n * @param { Array } terms  各学期成绩的数组\n */\nconst reduceAllTeams = terms => {\n  /**\n   * 返回各学期成绩的数组\n   */\n  const allScores = [];\n  for (const term of terms) {\n    allScores.unshift(term);\n  }\n  return allScores;\n};\n\nconst isTheSameTerm = (currentYear, year, currentTerm, term) =>\n  currentYear === year && currentTerm === term;\n\nconst mapScore = score => {\n  switch (score) {\n    case `优秀`:\n      return 95;\n    case `良好`:\n      return 85;\n    case `中等`:\n      return 75;\n    case `及格`:\n      return 65;\n    default:\n      return Number(score);\n  }\n};\n\nconst currySum = () => curry(sum);\nexport const sumCredits = currySum();\nexport const sumCreditMultiplyPoint = currySum();\nexport const termReducer = curry(reduceAllTeams);\n\n/**\n * 需要关注的属性\n * credit 学分\n * point 单科绩点\n * type 课程类型\n */\n\nexport const handleSum = ({ credit, point, courseType: type }) => {\n  // 任选课不统计学分\n  if (type === `任选`) return;\n  sumCredits(Number(credit));\n  sumCreditMultiplyPoint(Number(credit) * Number(point));\n};\n\nexport const handleTerm = (() => {\n  /**\n   * 闭包保存几个变量，用于判断累加\n   * currentYear  当前年份\n   * currentTerm  当前学期\n   * scoreReducer 当前学期的成绩累加器\n   */\n  let currentYear = ``;\n  let currentTerm = ``;\n  let scoreReducer = null;\n\n  return (\n    {\n      courseName: name,\n      credit,\n      point,\n      score,\n      resitScore,\n      retakeScore,\n      year,\n      term,\n      courseType: type\n    },\n    isEnd\n  ) => {\n    /**\n     * 如果年份和学期不一样了，那自然是到了别的学期，\n     * 如果之前的 scoreReducer 不为 null, 累加之前学期记录的成绩\n     */\n    if (!isTheSameTerm(currentYear, year, currentTerm, term)) {\n      if (scoreReducer) {\n        termReducer(scoreReducer());\n      }\n      scoreReducer = curry(reduceScores, year, term);\n      currentYear = year;\n      currentTerm = term;\n    }\n\n    score = mapScore(score);\n    resitScore = mapScore(resitScore);\n    retakeScore = mapScore(retakeScore);\n\n    const scoreItem = {\n      name,\n      credit: Number(credit).toFixed(1),\n      point: Number(point),\n      score: Math.max(score, resitScore, retakeScore),\n      isOptionalCourses: type === `任选`,\n      isEditing: false,\n      shouldFocus: false\n    };\n    scoreReducer(scoreItem);\n\n    if (isEnd) {\n      termReducer(scoreReducer());\n      currentYear = currentTerm = scoreReducer = null;\n    }\n  };\n})();\n"
  },
  {
    "path": "src/mixins/all-search-thing.js",
    "content": "import wepy from \"wepy\";\n\nexport default class allSearch extends wepy.mixin {\n  allSearchThing() {\n    const AllSearhes = [\n      {\n        name: \"图书馆\",\n        icon: \"https://static.airbob.org/under-graduate/more/library.png\",\n        isIndex: true,\n        id: 0,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"已借书目\",\n        icon: \"https://static.airbob.org/under-graduate/more/borrow.png\",\n        isIndex: false,\n        id: 1,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"检索书目\",\n        icon: \"https://static.airbob.org/under-graduate/more/retrieval.png\",\n        isIndex: false,\n        id: 2,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"座位查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/seat inquiry.png\",\n        isIndex: false,\n        id: 3,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"一卡通\",\n        icon: \"https://static.airbob.org/under-graduate/more/card.png\",\n        isIndex: true,\n        id: 4,\n        path: \"../campus-card-page/pages/campus-card-index\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"校园卡充值\",\n        icon: \"https://static.airbob.org/under-graduate/more/recharge.png\",\n        isIndex: false,\n        id: 5,\n        path: \"../campus-card-page/pages/campus-card-charge\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"电费充值\",\n        icon: \"https://static.airbob.org/under-graduate/more/electricity.png\",\n        isIndex: false,\n        id: 6,\n        path: \"../campus-card-page/pages/electric-charge\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"校园网充值\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/ campus network.png\",\n        isIndex: false,\n        id: 7,\n        path: \"../campus-card-page/pages/net-charge\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"校园卡挂失\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/report the loss.png\",\n        isIndex: false,\n        id: 8,\n        path: \"../campus-card-page/pages/campus-card-loss\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"成绩查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/results query.png\",\n        isIndex: true,\n        id: 9,\n        path: \"../edu-admin-page/pages/score-inquire\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"体育部\",\n        icon: \"https://static.airbob.org/under-graduate/more/sport.png\",\n        isIndex: true,\n        id: 10,\n        path: \"../others-edu-page/pages/pe-score\",\n        isOpen: true,\n        module: \"体育部\"\n      },\n      {\n        name: \"考试倒计时\",\n        icon: \"https://static.airbob.org/under-graduate/more/exam.png\",\n        isIndex: false,\n        id: 11,\n        path: \"../edu-admin-page/pages/course\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"等级考试\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/rank examination.png\",\n        isIndex: false,\n        id: 12,\n        path: \"../edu-admin-page/pages/check-grade\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"补考查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/resit.png\",\n        isIndex: true,\n        id: 13,\n        path: \"../edu-admin-page/pages/cut-down\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"辅导课查询\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/prenatal class.png\",\n        isIndex: false,\n        id: 14,\n        path: \"../edu-admin-page/pages/supplement-and-tutorials\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"GPA计算器\",\n        icon: \"https://static.airbob.org/under-graduate/more/gpa.png\",\n        isIndex: false,\n        id: 15,\n        path: \"../others-edu-page/pages/GpaCalculator\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"课表\",\n        icon: \"https://static.airbob.org/under-graduate/more/timetable.png\",\n        isIndex: true,\n        id: 16,\n        path: \"../edu-admin-page/pages/course\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"校历\",\n        icon: \"https://static.airbob.org/under-graduate/more/calendar.png\",\n        isIndex: true,\n        id: 17,\n        path: \"../others-page/pages/calendar\",\n        isOpen: true,\n        module: \"校历\"\n      },\n      {\n        name: \"自主学分\",\n        icon: \"https://static.airbob.org/under-graduate/more/credit.png\",\n        isIndex: false,\n        id: 18,\n        path: \"../edu-admin-page/pages/credit\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"晨跑\",\n        icon: \"https://static.airbob.org/under-graduate/more/run.png\",\n        isIndex: true,\n        id: 19,\n        path: \"../others-page/pages/run\",\n        isOpen: true,\n        module: \"晨跑\"\n      },\n      {\n        name: \"学费查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/tuition.png\",\n        isIndex: false,\n        id: 20,\n        path: \"../others-page/pages/tuition\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"社团招新\",\n        icon: \"https://static.airbob.org/under-graduate/more/club.png\",\n        isIndex: false,\n        id: 21,\n        path: \"../others-page/pages/associationPages/association\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"认证\",\n        icon: \"https://static.airbob.org/under-graduate/more/club.png\",\n        isIndex: false,\n        id: 22,\n        path: \"../others-page/pages/auth\",\n        isOpen: true,\n        module: \"正方\"\n      }\n    ];\n    return AllSearhes;\n  }\n}\n"
  },
  {
    "path": "src/mixins/class.js",
    "content": "import wepy from \"wepy\";\n\nexport default class ClassMixin extends wepy.mixin {\n  getColor(data) {\n    var all = data;\n    let colorArr = [\"#6AD5E1\", \"#87E5DA\", \"#F7C562\", \"#FFB677\", \"#FF8364\"];\n    let borderColor = [\"#44888F\", \"#57938C\", \"#9C7C3E\", \"#A7784F\", \"#9C503D\"];\n    let firstcolor;\n    for (var i = 0; i <= all.length - 1; i++) {\n      let secondcolor;\n      do {\n        secondcolor = Math.floor(Math.random() * 5);\n      } while (firstcolor ? firstcolor === secondcolor : false);\n      firstcolor = secondcolor;\n      all[i].bgc = colorArr[secondcolor];\n      all[i].borderColor = borderColor[secondcolor];\n    }\n    return all;\n  }\n\n  /**\n   * 计算课的与上边界的距离\n   * @param {Object} courseItem\n   * @returns {Object}\n   */\n  getElementHeight(courseItem) {\n    const { sectionend, sectionstart } = courseItem;\n    return (\n      parseInt(sectionend - sectionstart + 1) *\n        (sectionend - sectionstart === 3 ? 106 : 105) +\n      \"rpx\"\n    );\n  }\n\n  /**\n   * 计算课的高度\n   * @param {Object} courseItem\n   * @returns {Object}\n   */\n  getElementTop(courseItem) {\n    const { sectionstart } = courseItem;\n    return parseInt((sectionstart - 1) * 108 + 93) + \"rpx\";\n  }\n\n  /**\n   * @param {Object} courseItem 想搜寻的课\n   * @param {Array} courses 从哪些课中搜寻\n   * @returns {Boolean} 是否有相同时间的课\n   */\n  getCourseItemAtSameTimeIndex(courseItem, courses) {\n    const { day, sectionstart, sectionend } = courseItem;\n    return courses.findIndex(\n      x =>\n        x !== courseItem &&\n        x.day === day &&\n        x.sectionstart === sectionstart &&\n        x.sectionend === sectionend\n    );\n  }\n\n  /**\n   *\n   * @param {Array} courses 所有的课程\n   * @param {Number} chosenWeek 当前的周次\n   * @param {Boolean} onlyShowThisWeek 是否为只显示单周模式,为true时为显示单双周模式\n   * @returns {[Array<Object>,Array<Object>]} shownCourse unShownCourse\n   */\n  handleCourses(courses, chosenWeek, onlyShowThisWeek) {\n    courses = this.getColor(courses);\n    const shownCourse = [[], [], [], [], [], [], []]; // 一个二维数组，每个元素为本周当天需要上的课\n    const unShownCourse = [[], [], [], [], [], [], []]; // 一个二维数组，每个元素为本周当天不需要上的课\n\n    // 遍历courses,计算courses中的每个元素的bgc,elementHeight,elemntTop\n    for (const course of courses) {\n      if (course.day === 7 || course.day === \"7\") {\n        course.day = 0;\n      }\n      course.elementHeight = this.getElementHeight(course);\n      course.elementTop = this.getElementTop(course);\n      course.withMoreCourse = false;\n    }\n    // 将courses中的course进行分组,分入unShownCourse和shownCourse中\n    for (const course of courses) {\n      const { day, weekarr } = course;\n      if (!weekarr.includes(chosenWeek)) {\n        course.bgc = \"#D8D8D8\";\n        if (!onlyShowThisWeek) {\n          shownCourse[day].push(course);\n        }\n      } else {\n        shownCourse[day].push(course);\n      }\n    }\n\n    const allShownCourse = shownCourse.reduce(\n      (total, current) => total.concat(current),\n      []\n    );\n    const allUnShownCourse = unShownCourse.reduce(\n      (total, current) => total.concat(current),\n      []\n    );\n\n    for (const dailyCourses of shownCourse) {\n      // 对shownCourse中的每个数组排序，使本周会上的课排在前面\n      dailyCourses.sort(course => (course.bgc === \"#D8D8D8\" ? -1 : 1));\n\n      // 使有不止一个课的时间段的课,withMoreCourse 为true\n      for (const dailyCoursesItem of dailyCourses) {\n        const swipperCourseAtSameTimeIndex = this.getCourseItemAtSameTimeIndex(\n          dailyCoursesItem,\n          allShownCourse.concat(allUnShownCourse)\n        );\n        if (swipperCourseAtSameTimeIndex !== -1) {\n          dailyCoursesItem.withMoreCourse = true;\n        }\n      }\n    }\n\n    // 将shownCourse和unShownCourse中的最后一个元素移到前面\n    shownCourse.push(shownCourse.shift());\n    unShownCourse.push(unShownCourse.shift());\n\n    // 过滤掉课程出现重叠的课程\n    const newShownCourse = shownCourse.map(dailyCourses =>\n      dailyCourses.filter(\n        course =>\n          !(\n            course.bgc === \"#D8D8D8\" &&\n            dailyCourses.find(\n              x =>\n                x !== course &&\n                x.sectionstart >= course.sectionstart &&\n                x.sectionend <= course.sectionend\n            )\n          )\n      )\n    );\n\n    return [newShownCourse, unShownCourse];\n  }\n}\n"
  },
  {
    "path": "src/mixins/get-div-info.js",
    "content": "import wepy from \"wepy\";\n\nexport default class getDivInfoMixin extends wepy.mixin {\n  // id 为字符串\"#XXX\"形式\n  // 调用方式：\n  //  import getDivInfoMixin   mixins = [getDivInfoMixin];\n  // from \"@/mixins/get-div-info.js\";\n  //     that.getDivInfo(\"#XXX\").then(res => {\n  //     });\n  // 在回调函数中获取元素信息：res为对象{height: 150, width: 375, left: 0, right: 375, top: 130…}\n  getDivInfo(id) {\n    return new Promise((resolve, reject) => {\n      let query = wepy.createSelectorQuery();\n      query.select(id).boundingClientRect();\n      query.exec(res => {\n        let divInfo = {};\n        divInfo.height = res[0].height; // px\n        divInfo.width = res[0].width; // px\n        divInfo.left = res[0].left; // px\n        divInfo.right = res[0].right; // px\n        divInfo.top = res[0].top; // px\n        divInfo.bottom = res[0].bottom; // px\n        divInfo.dataset = res[0].dataset;\n        resolve(divInfo);\n      });\n    });\n  }\n}\n"
  },
  {
    "path": "src/mixins/module.js",
    "content": "import wepy from \"wepy\";\n\nexport default class module extends wepy.mixin {\n  judgeStatus(name) {\n    return new Promise((resolve, reject) => {\n      const moduleStatus = wepy.getStorageSync(\"moduleStatus\");\n      for (let i of moduleStatus) {\n        if (i.moduleName === name && !i.open) {\n          if (name !== \"课表\") {\n            this.$redirect({\n              url: \"/others-page/pages/close\"\n            });\n            reject();\n          } else {\n            resolve();\n          }\n          break;\n        }\n      }\n      resolve();\n    });\n  }\n}\n"
  },
  {
    "path": "src/mixins/test.js",
    "content": "import wepy from \"wepy\";\n\nexport default class testMixin extends wepy.mixin {}\n"
  },
  {
    "path": "src/mock/campusCard.js",
    "content": "import { mockRequest as request } from \"@/api/request\";\nimport qs from \"qs\";\n\nexport const mockCampusCardRequestInfo = () => {\n  return request.post(\"/5a6e75c9011d2a207121663d\");\n};\n\nexport const mockSevenDayTurnOver = () => {\n  return request.post(\"/5ab7aee122017f206f8bf382\");\n};\n\nexport const mockYearTurnOver = () => {\n  const year = new Date().getFullYear();\n  return request.post(\n    `/5a6ea8ef97c1292065e2452c`,\n    qs.stringify({\n      year: year\n    })\n  );\n};\n\nexport const mockInternetRemain = (tran = \"1\", password = \"1\") => {\n  return request.post(\n    `/5ab86e5df21ec32066101d81`,\n    qs.stringify({\n      tran: tran,\n      password: password\n    })\n  );\n};\n\nexport const mockOneDayTurnOver = (page = \"1\") => {\n  return request.post(\n    \"/5a6fd895011d2a20712167ab\",\n    qs.stringify({\n      page: page\n    })\n  );\n};\n\nexport const mockGetMoneyLog = () => {\n  return request.get(\"/5c11c210cc00a21d11d2b7f9\");\n};\n"
  },
  {
    "path": "src/mock/common.js",
    "content": "import { mockRequest as request } from \"@/api/request\";\n\nexport const mockGetUserPEGrade = (semester = \"1\") => {\n  return request.get(\"/5a5d9300f21ec320660ff3d4\", {\n    params: {\n      semester\n    }\n  });\n};\n\nexport const mockGetExercise = () => {\n  return request.get(\"/5d294b3ce640c81fad72a058\");\n};\n\nexport const mockGetRunHistory = () => {\n  return request.get(\"/5d29524fa992181fb4f64ec1\");\n};\n\nexport const mockOwnGraduateGrade = () => {\n  return request.get(\"/5d31678103cf111fb9ed623a\");\n};\n\nexport const getUpdateLog = () => request.get(\"/5de23e43db66aa1fb0609cc3\");\n\nexport const getSchoolBus = () => request.get(\"/5de66a21db66aa1fb0609e1e\");\n"
  },
  {
    "path": "src/mock/education.js",
    "content": "import { mockRequest as request } from \"@/api/request\";\n\nexport const mockClassSchedule = () => {\n  return request.get(\"/5a7b2324011d2a20712177ae\");\n};\n\nexport const mockGetAddCourses = (type = \"type\") => {\n  return request.post(`/5c054f50b2e9fd1d1feef378?type=${type}`);\n};\n\nexport const mockGetUserGrade = () => {\n  return request.get(\"/5a7b2641011d2a20712177bb\");\n};\n\nexport const mockRankingSelf = () => {\n  return request.get(\"/5ab9b7ae22017f206f8bf4cc\");\n};\n\nexport const mockGetUserGradeTest = () => {\n  return request.get(\"/5a7b237cf21ec320661009ac\");\n};\n\nexport const mockGetSupplyment = () => {\n  return request.get(\"/5a6194a797c1292065e240dc\");\n};\n\nexport const mockGetYourOwnExam = (type = 1) => {\n  return request.get(`/5a617d38f21ec320660ff3d9?type=${type}`);\n};\n"
  },
  {
    "path": "src/mock/index.js",
    "content": "import wepy from \"wepy\";\n\nconsole.log(wepy.$store.getState());\n"
  },
  {
    "path": "src/mock/library.js",
    "content": "import { mockRequest as request } from \"@/api/request\";\n\nexport const mockCheckBookHistory = () => {\n  return request.get(\"/5c4476be1382fc1d1917dccc\");\n};\nexport const mockHotBooks = () => {\n  return request.get(\"/5a9662d7011d2a2071218137\");\n};\n\nexport const mockRemainSeats = () => {\n  return request.get(\"/5a9639d1f21ec3206610131f\");\n};\n\nexport const mockLibrarySearch = (content, page) => {\n  return request.post(\"/5a9639fb97c1292065e25fed\", {\n    content,\n    page\n  });\n};\n\nexport const mockAlreadyBorrowBooksSum = () => {\n  return request.post(\"/5a9639ee22017f206f8bea5e\");\n};\nexport const mockHistoricalBorrow = () => {\n  return request.post(\"/5a9635a4011d2a207121812c\");\n};\nexport const mockBookArrears = () => {\n  return request.post(\"/5a966239011d2a2071218134\");\n};\nexport const mockBookStore = () => {\n  return request.get(\"/5c4476be1382fc1d1917dccc\");\n};\nexport const mockBookStoreAgain = () => {\n  return request.post(\"/5a96a283f21ec320661013b3\");\n};\nexport const mockBookStoreContent = (marc_no = \"123\") => {\n  return request.post(\"/5a963dcc97c1292065e25ff1\", {\n    marc_no\n  });\n};\n"
  },
  {
    "path": "src/mock/notification.js",
    "content": "import { mockRequest as request } from \"@/api/request\";\n\nexport const mockGetNotification = () => {\n  return request.get(\"/5abccaa0011d2a2071218d43\");\n};\n\nexport const mockMarkAllAsRead = () => {\n  return request.put(\"/5abccb7a22017f206f8bf68e\");\n};\n\nexport const mockDeleteAll = () => {\n  return request.put(\"/5abccba497c1292065e26c0c\");\n};\n"
  },
  {
    "path": "src/others-edu-page/components/GpaCard.wpy",
    "content": "<template lang=\"pug\">\nview.card\n  view.header( @tap=\"toggleCardFolded\")\n    text.title {{termScores.title}}\n    image.angle(class=\"{{termScores.isFolded ? '' : 'active'}}\" src=\"https://static.airbob.org/under-graduate/gpa/button_down.png\")\n\n  view.guide( class=\"{{guideStatus}}\")\n    view.content 点击编辑可以删课或修改成绩哦\n    view.triangle\n\n  view.score-wrapper(style=\"height:{{!termScores.isFolded ? scoreItemHeight * termScores.count * 750 / screenWidth + 10 : 0}}rpx\")\n    repeat(for=\"{{termScores.scores}}\" key=\"key\" index=\"index\" item=\"scoreItem\")\n      view.score-item( @tap=\"closeEdit({{scoreItem}})\")\n        view.info-wrapper\n          view.name {{scoreItem.name}}\n          view.info\n            text.credit 学分：{{scoreItem.credit}}\n            text.score 成绩：\n            input.input( @input=\"handleScoreInput({{scoreItem.name}}, {{scoreItem.isOptionalCourses}})\" @blur=\"handleBlur({{scoreItem.name}})\" value=\"{{scoreItem.score === 0 ? '' : scoreItem.score}}\" focus=\"{{scoreItem.shouldFocus}}\" disabled=\"{{ !scoreItem.shouldFocus }}\" type=\"number\")\n        view.btn-wrapper\n          view.edit-wrapper( @tap.stop=\"toggleEditScore({{scoreItem}})\" class=\"{{!scoreItem.isEditing ? 'active' : ''}}\")\n            view.edit-btn 编辑\n          view.wrapper(class=\"{{scoreItem.isEditing ? 'active' : ''}}\")\n            view.delete-btn( @tap.stop=\"deleteScore({{scoreItem}})\" ) 删课\n            view.modify-btn( @tap.stop=\"handleClickModifyBtn({{scoreItem}})\")\n              text.text 修改成绩\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport GpaMixin from \"../../mixins/Gpa/Gpa.js\";\n\nexport default class GpaCard extends wepy.component {\n  props = {\n    termScores: {\n      // 学期成绩\n      type: Object,\n      twoWay: true\n    }\n  };\n\n  data = {\n    scoreItemHeight: null,\n    screenWidth: null\n  };\n\n  mixins = [GpaMixin];\n\n  computed = {\n    guideStatus() {\n      if (this.$index !== 0) {\n        return `destroyed`;\n      }\n\n      switch (this.termScores.showGuide) {\n        case 1:\n          return `active`;\n        case 0:\n          return `inactive`;\n        case -1:\n          return `destroyed`;\n      }\n    }\n  };\n\n  methods = {\n    // 控制卡片折叠\n    toggleCardFolded() {\n      this.termScores.isFolded = !this.termScores.isFolded;\n    },\n\n    // 关闭编辑面板\n    closeEdit({ name }) {\n      const item = this.termScores.scores.find(x => x.name === name);\n      item.isEditing = false;\n      item.shouldFocus = false;\n    },\n\n    // 开启编辑\n    toggleEditScore({ name }) {\n      const item = this.termScores.scores.find(x => x.name === name);\n      item.isEditing = true;\n    },\n\n    // 删除该条成绩\n    async deleteScore({ name, credit, point, isOptionalCourses }) {\n      const res = await wepy.showModal({\n        title: \"确认删除\",\n        content: \"确认删除该课程吗？\",\n        confirmText: \"确认\",\n        confirmColor: \"#353535\",\n        cancelColor: `#86d6ef`\n      });\n\n      if (res.confirm) {\n        for (let i = 0; i < this.termScores.scores.length; i++) {\n          const score = this.termScores.scores[i];\n          if (score.name === name) {\n            this.termScores.scores.splice(i, 1);\n            this.termScores.count--;\n            break;\n          }\n        }\n        this.$emit(\"delete\", credit, point, isOptionalCourses);\n      }\n    },\n\n    // 点击修改按钮\n    handleClickModifyBtn({ name }) {\n      const item = this.termScores.scores.find(x => x.name === name);\n      item.shouldFocus = true;\n    },\n\n    // 修改成绩的逻辑\n    handleScoreInput(name, isOptionalCourses, { detail }) {\n      // 如果只输入\".\"，会无法计算\n      if (detail.value.startsWith(\".\")) return;\n\n      let { value: score } = detail;\n\n      score = this.discardUnnecessaryChars(score);\n      score = this.limitScore(score);\n      score = score.length === 0 ? 0 : score;\n      this.$emit(\"modifyScore\", this.$index, name, score, isOptionalCourses);\n\n      return score;\n    },\n\n    handleBlur(name) {\n      const item = this.termScores.scores.find(x => x.name === name);\n      item.shouldFocus = false;\n    }\n  };\n\n  onLoad() {\n    let timer1 = setInterval(() => {\n      this.scoreItemHeight = this.$parent.scoreItemHeight;\n      this.screenWidth = this.$parent.screenWidth;\n\n      if (this.scoreItemHeight !== null && this.screenWidth !== null) {\n        clearInterval(timer1);\n        timer1 = null;\n      }\n    }, 100);\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.card\n  position relative\n  margin-top 30rpx\n  padding 0 56rpx 0 28rpx\n  overflow hidden\n  box-shadow 0 0 10rpx 0 rgba(0, 0, 0, 0.05)\n  background #fff\n  .header\n    display flex\n    position relative\n    z-index 1\n    height 94rpx\n    justify-content space-between\n    align-items center\n    border-bottom 1rpx solid #e3e3e3\n    background #fff\n    .title\n      font-size 28rpx\n      color #353535\n    .angle\n      padding 30rpx\n      width 30rpx\n      height 16rpx\n      transition transform 0.4s ease-out\n      &.active\n        transform rotate(-180deg)\n  .guide\n    position absolute\n    top 218rpx\n    right 56rpx\n    z-index 3\n    opacity 0\n    transition opacity 0.4s ease-out\n    &.active\n      opacity 1\n    &.inactive\n      opacity 0\n    &.destroyed\n      display none\n    .content\n      padding 14rpx\n      font-size 28rpx\n      color #fff\n      background #ffc145\n      border-radius 18rpx\n    .triangle\n      position absolute\n      top -20rpx\n      right 64rpx\n      width 0\n      height 0\n      border-left 16rpx solid transparent\n      border-right 16rpx solid transparent\n      border-bottom 24rpx solid #ffc145\n  .score-wrapper\n    transition height 0.6s ease-in-out\n    .score-item\n      display flex\n      color #353535\n      border-bottom 1rpx solid #e3e3e3\n      justify-content space-between\n      .info-wrapper\n        margin 30rpx 0 20rpx 0\n        // width 控制显示字符数\n        width 60%\n        .name\n          width 100%\n          font-size 32rpx\n          font-weight bold\n          overflow hidden\n          white-space nowrap\n          text-overflow ellipsis\n        .info\n          display flex\n          margin-top 4rpx\n          font-size 24rpx\n          align-items center\n          .score\n            margin-left 50rpx\n          .input\n            display inline-block\n            width 60rpx\n            font-size 24rpx\n            line-height 24rpx\n            min-height 0\n      .btn-wrapper\n        display flex\n        position relative\n        justify-content flex-end\n        align-items center\n        .edit-wrapper\n          display none\n          padding 36rpx\n          &.active\n            display block\n          .edit-btn\n            padding 10rpx 20rpx\n            line-height 28rpx\n            font-size 28rpx\n            color #47cff5\n            border 1rpx solid #47cff5\n            border-radius 30rpx\n        .wrapper\n          display flex\n          position absolute\n          top 0\n          right 0\n          z-index 1\n          height 100%\n          transform scaleX(0)\n          transform-origin right center\n          transition transform 0.3s ease-out\n          &.active\n            transform scaleX(1)\n            .delete-btn,\n            .modify-btn\n              display flex\n          .delete-btn,\n          .modify-btn\n            display flex\n            width 110rpx\n            height 100%\n            font-size 28rpx\n            font-weight bold\n            color #fff\n            text-align center\n            justify-content center\n            align-items center\n          .delete-btn\n            background linear-gradient(-225deg, #ffb6b6, #ff808c)\n          .modify-btn\n            background linear-gradient(-225deg, #9ec9ff, #80ddff)\n            .text\n              width 70%\n</style>\n"
  },
  {
    "path": "src/others-edu-page/components/GpaCustomScore.wpy",
    "content": "<template lang=\"pug\">\nview.custom-score\n  view.course-name-wrapper\n    input( @input=\"handleCourseNameInput\" value=\"{{score.name}}\" placeholder=\"(点击可修改课程名)\" placeholder-style=\"{{placeholderStyles1}}\")\n  view.input-wrapper\n    view.credit\n      text.desc 学分\n      input.input( @input=\"handleCreditInput\" value=\"{{score.credit === 0 ? '' : score.credit}}\" type=\"digit\" placeholder=\"点击填写课程学分\" placeholder-style=\"{{placeholderStyles2}}\")\n    view.score\n      text.desc 成绩\n      input.input( @input=\"handleScoreInput\" value=\"{{score.score === 0 ? '' : score.score}}\" type=\"number\" placeholder=\"点击填写考试成绩\" placeholder-style=\"{{placeholderStyles2}}\")\n    image.close( @tap=\"closeCard\" src=\"https://static.airbob.org/under-graduate/gpa/close.png\")\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport GpaMixin from \"../../mixins/Gpa/Gpa.js\";\n\nexport default class GpaCustomScore extends wepy.component {\n  props = {\n    score: {\n      type: Object,\n      twoWay: true\n    }\n  };\n\n  data = {\n    placeholderStyles1: `\n      font-size: 24rpx;\n      color: #fff;\n      text-align: center;\n    `,\n    placeholderStyles2: `\n      font-size: 28rpx;\n      font-weight: normal;\n      color: #999ca0;\n    `\n  };\n\n  mixins = [GpaMixin];\n\n  methods = {\n    handleCreditInput({ detail }) {\n      // 如果只输入\".\"，会无法计算\n      if (detail.value.startsWith(\".\")) return;\n\n      let { value: credit } = detail;\n\n      credit = this.discardUnnecessaryChars(credit);\n      if (Number(credit) > 100) {\n        // 如果 score 大于 100，截断后面的\n        credit = credit.slice(0, 2);\n      }\n      credit = credit.length === 0 ? 0 : credit;\n      this.$emit(\"modifyCredit\", this.$index, credit);\n      return credit;\n    },\n\n    handleScoreInput({ detail }) {\n      // 如果只输入\".\"，会无法计算\n      if (detail.value.startsWith(\".\")) return;\n\n      return this.processScoreInput(detail, \"modifyCustomScore\");\n    },\n\n    handleCourseNameInput({ detail }) {\n      let { value: name } = detail;\n      this.$emit(\"modifyName\", this.$index, name);\n    },\n\n    async closeCard() {\n      const res = await wepy.showModal({\n        title: \"确认删除\",\n        content: \"确认删除该课程吗？\",\n        confirmText: \"确认\",\n        confirmColor: \"#353535\",\n        cancelColor: `#86d6ef`\n      });\n\n      if (res.confirm) {\n        this.$emit(\"close\", this.score.id);\n      }\n    }\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.custom-score\n  display flex\n  margin-top 30rpx\n  align-items center\n  .course-name-wrapper\n    display flex\n    flex 1\n    min-height 130rpx\n    font-size 24rpx\n    font-weight bold\n    color #fff\n    text-align center\n    justify-content center\n    align-items center\n    box-shadow 0 0 10rpx 0 rgba(0, 0, 0, 0.1)\n    background linear-gradient(-45deg, #75d3ce, #98e9e3)\n  .input-wrapper\n    display flex\n    position relative\n    padding-left 76rpx\n    flex 0 0 460rpx\n    height 150rpx\n    font-size 28rpx\n    font-weight bold\n    color #353535\n    flex-wrap wrap\n    align-items center\n    box-shadow 0 0 10rpx 0 rgba(0, 0, 0, 0.1)\n    box-sizing border-box\n    .credit,\n    .score\n      display flex\n      align-items center\n      .desc\n        min-width 70rpx\n      .input\n        display inline-block\n        margin-left 18rpx\n    .close\n      position absolute\n      z-index 2\n      top 0\n      right 0\n      padding 20rpx\n      width 20rpx\n      height 20rpx\n</style>\n"
  },
  {
    "path": "src/others-edu-page/components/pe-card.wpy",
    "content": "<template>\n  <view\n    class=\"container\"\n    style=\"background-color:{{titleBgColor}};\"\n    @tap.stop=\"toggle\"\n    data-h=\"{{indexx}}\"\n  >\n    <view class=\"banner\">{{result.year}}</view>\n    <view class=\"result-list\" animation=\"{{animation}}\" @tap.stop=\"prevent\">\n      <view class=\"result-item\">\n        <view class=\"result-text1\">项目</view>\n        <view class=\"result-text2\">项目成绩</view>\n        <view class=\"result-text3\">得分</view>\n      </view>\n      <view id=\"{{result.term==='体测'?'Test':'Class'}}-{{indexx}}\">\n        <repeat for=\"{{result.data}}\" item=\"item\">\n          <view class=\"result-item\">\n            <view class=\"result-text1\">{{item.project==='total'?'总分':item.project}}</view>\n            <view class=\"result-text2\">{{item.score==null?'无':item.score}}</view>\n            <view class=\"result-text3\">{{item.mark==null?'无':item.mark}}</view>\n          </view>\n        </repeat>\n      </view>\n    </view>\n    <view class=\"banner\">{{result.term}}</view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class PeCard extends wepy.component {\n  props = {\n    result: Array,\n    titleBgColor: {\n      type: String, // rgb\n      default: \"rgb(20,126,232)\"\n    },\n    animation: Object,\n    indexx: Number\n  };\n  methods = {\n    toggle(e) {\n      if (this.result.term !== \"体测\") {\n        this.$emit(\"changeClassShow\", this.$index);\n      } else {\n        this.$emit(\"changeTestShow\", this.$index);\n      }\n    },\n    prevent(e) {}\n  };\n}\n</script>\n<style lang=\"stylus\" scoped>\n.container\n  margin-top 30rpx\n  border-radius 30rpx\n  width 601rpx\n  font-family 'SimHei'\n  color rgb(255, 255, 255)\n  display flex\n  flex-direction column\n  align-items center\n  .banner\n    padding 10rpx 0\n  .result-list\n    overflow hidden\n    height 0\n    width 584rpx\n    box-sizing border-box\n    background-color rgb(255, 255, 255)\n    font-size 24rpx\n    color rgb(0, 0, 0)\n    .result-item\n      display flex\n      margin 16rpx 52rpx\n      .result-text1\n        width 216rpx\n      .result-text2\n        width 192rpx\n</style>\n\n\n\n"
  },
  {
    "path": "src/others-edu-page/graduatePages/clear-memory.wpy",
    "content": "<template>\n  <view>\n    <view class=\"background\">\n      <view class=\"content\">\n        <view class=\"content-text\">\n          <view class=\"content-title\">记忆模式</view>\n          <p>你选择不开启记忆模式。</p>\n          <view>数据将在选择生效后被清空，且该操作不可逆。</view>\n          <view>感谢小程序能够陪伴你的大学时光。江湖再见！</view>\n          <p>请点击确定，选择生效。</p>\n        </view>\n        <button class=\"confirm-btn\" @tap=\"next\"><span>确定并清空数据</span></button>\n        <view class=\"reselect\" @tap=\"reselect\">重新选择</view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  import { chooseMemoryMode } from \"@/api/graduateMode\";\n  export default class Login extends wepy.page {\n    data = {};\n    methods = {\n      reselect() {\n        wepy.navigateBack();\n      },\n      next() {\n        chooseMemoryMode(0);\n        wepy.navigateTo({ url: \"./say-goodbye\" });\n      }\n    };\n    onLoad() {}\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.background\n  position absolute\n  top 0\n  left 0\n  width 100vw\n  height 100vh\n  z-index 0\n  background url('https://static.airbob.org/under-graduate/memory/memory3.jpg') no-repeat\n  background-size cover\n  overflow hidden\n  display flex\n  justify-content center\n  .content\n    width 623rpx\n    margin-top 570rpx\n    color #000\n    .content-text\n      font-size 26rpx\n      color #4a4a4a\n      margin-bottom 75rpx\n      view\n        margin-bottom 20rpx\n      p\n        font-weight 700\n      .content-title\n        font-size 36rpx\n        font-weight 700\n        line-height 54rpx\n    .confirm-btn\n      width 630rpx\n      height 80rpx\n      border-radius 80rpx\n      color #fff\n      background-image linear-gradient(90deg, #ac7461 0%, #ae3506 100%),linear-gradient(#f2f2f2, #f2f2f2)\n      display flex\n      align-items center\n      justify-content center\n      margin-bottom 32rpx\n    .reselect\n      font-size 24rpx\n      color #282828\n      text-align center\n\nbutton:after\n  border none\n</style>\n"
  },
  {
    "path": "src/others-edu-page/graduatePages/index.wpy",
    "content": "<template>\n  <view>\n    <view class=\"background\">\n      <view class=\"content\">\n        <view class=\"content-text\">\n          <view class=\"content-title\">亲爱的{{name}}</view>\n          <view>这可能是你在校园里最后一次打开南邮小程序。 当你离开校园后，你的正方、智慧校园等系统账号将被注销，无法再次登录，数据将被清空，南邮小程序也无法再通过接口更新这些数据。</view>\n          <view>这些存在数据库里的 0 和 1 ，见证了你的南邮青春，是你大学四年回忆的一部分。</view>\n          <view>肖辰旭有幸能从 2017 年 6 月起，陪伴你走过两年的大学时光，并和你一起成长。临别之际，肖辰旭准备了一份礼物，帮你记录下这部分数据记忆。</view>\n          <p>点击下一步，进入“南邮小程序 · 记忆模式”。</p>\n        </view>\n        <button class=\"next-btn\" @tap=\"next\"><span>下一步</span></button>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  export default class Login extends wepy.page {\n    data = {\n      name: \"\"\n    };\n    methods = {\n      next() {\n        wepy.navigateTo({\n          url: \"./memory-choose\"\n        });\n      }\n    };\n    onLoad({ name }) {\n      this.name = name;\n    }\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.background\n  position absolute\n  top 0\n  left 0\n  width 100vw\n  height 100vh\n  z-index 0\n  background url('https://static.airbob.org/under-graduate/memory/memory1.jpg') no-repeat\n  background-size cover\n  overflow hidden\n  display flex\n  justify-content center\n  .content\n    width 623rpx\n    margin-top 570rpx\n    color #000\n    .content-text\n      font-size 26rpx\n      color #4a4a4a\n      margin-bottom 75rpx\n      view\n        margin-bottom 20rpx\n      p\n        font-weight 700\n      .content-title\n        font-size 36rpx\n        font-weight 700\n        line-height 54rpx\n    .next-btn\n      width 630rpx\n      height 80rpx\n      border-radius 80rpx\n      color #fff\n      background-image linear-gradient(82deg, #94e6f4 0%, #68d5f2 86%, #3bc3f0 100%),linear-gradient(#f2f2f2, #f2f2f2)\n      display flex\n      align-items center\n      justify-content center\n\nbutton:after\n  border none\n</style>\n"
  },
  {
    "path": "src/others-edu-page/graduatePages/memory-choose.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation title=\"\" background=\"transparent\"></qy-navigation>\n    <view class=\"background\">\n      <view class=\"content\">\n        <view class=\"content-text\">\n          <view class=\"content-title\">记忆模式</view>\n          <view>当你的校园账号被注销后，将无法再登录校园各个系统，数据将被清空。同时也无法再登录小程序刷新数据。</view>\n          <view>现在，若你选择开启“记忆模式”，南邮小程序将会把你现有的数据静态保留下来。这之后，你将还可打开南邮小程序查看过往信息。</view>\n          <view>若你选择不开启“记忆模式”，南邮小程序将在你的正方系统账号注销的同时，清空你的现有数据，操作不可逆。</view>\n          <p>请确认你的选择。</p>\n        </view>\n        <button class=\"btn open-btn\" @tap=\"open\"><span>开启“记忆模式”</span></button>\n        <button class=\"btn close-btn\" @tap=\"close\"><span>关闭“记忆模式”</span></button>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  import navigation from \"@/components/qy-navigation\";\n  export default class Login extends wepy.page {\n    data = {};\n    components = {\n      \"qy-navigation\": navigation\n    };\n    methods = {\n      open() {\n        wepy.navigateTo({\n          url: \"./memory-mode\"\n        });\n      },\n      close() {\n        wepy.navigateTo({\n          url: \"./clear-memory\"\n        });\n      }\n    };\n    onLoad() {}\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.background\n  position absolute\n  top 0\n  left 0\n  width 100vw\n  height 100vh\n  z-index 0\n  background url('https://static.airbob.org/under-graduate/memory/memory4.jpg') no-repeat\n  background-size cover\n  overflow hidden\n  display flex\n  justify-content center\n  .content\n    width 623rpx\n    margin-top 570rpx\n    color #000\n    .content-text\n      font-size 26rpx\n      color #4a4a4a\n      margin-bottom 75rpx\n      view\n        margin-bottom 20rpx\n      p\n        font-weight 700\n      .content-title\n        font-size 36rpx\n        font-weight 700\n        line-height 54rpx\n    .btn\n      width 630rpx\n      height 80rpx\n      border-radius 80rpx\n      color #fff\n      display flex\n      align-items center\n      justify-content center\n    .open-btn\n      background-image linear-gradient(82deg, #dcbf86 0%, #be8d43 100%),linear-gradient(#f2f2f2, #f2f2f2)\n      margin-bottom 32rpx\n    .close-btn\n      background-image linear-gradient(82deg, #d78f58 0%, #ba6733 100%),linear-gradient(#f2f2f2, #f2f2f2)\n\n\nbutton:after\n  border none\n</style>\n\n"
  },
  {
    "path": "src/others-edu-page/graduatePages/memory-mode.wpy",
    "content": "<template>\n  <view>\n    <view class=\"background\">\n      <view class=\"content\">\n        <view class=\"content-text\">\n          <view class=\"content-title\">记忆模式</view>\n          <p>你已开启记忆模式。</p>\n          <view>记忆模式可在“个人中心”中关闭，关闭操作将清空数据，操作不可逆。</view>\n          <view>请点击下一步，进行登录。</view>\n        </view>\n        <button class=\"next-btn\" @tap=\"next\"><span>下一步</span></button>\n        <view class=\"reselect\" @tap=\"reselect\">重新选择</view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  import { chooseMemoryMode } from \"@/api/graduateMode\";\n  export default class Login extends wepy.page {\n    data = {};\n    methods = {\n      reselect() {\n        wepy.navigateBack();\n      },\n      async next() {\n        const {\n          data: { success }\n        } = await chooseMemoryMode(1);\n        if (success) {\n          wepy.switchTab({ url: \"../../pages/index\" });\n        }\n      }\n    };\n    onLoad() {}\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.background\n  position absolute\n  top 0\n  left 0\n  width 100vw\n  height 100vh\n  z-index 0\n  background url('https://static.airbob.org/under-graduate/memory/memory2.jpg') no-repeat\n  background-size cover\n  overflow hidden\n  display flex\n  justify-content center\n  .content\n    width 623rpx\n    margin-top 570rpx\n    color #000\n    .content-text\n      font-size 26rpx\n      color #4a4a4a\n      margin-bottom 75rpx\n      view\n        margin-bottom 20rpx\n      p\n        font-weight 700\n      .content-title\n        font-size 36rpx\n        font-weight 700\n        line-height 54rpx\n    .next-btn\n      width 630rpx\n      height 80rpx\n      border-radius 80rpx\n      color #fff\n      background-image linear-gradient(82deg, #94e6f4 0%, #68d5f2 86%, #3bc3f0 100%),linear-gradient(#f2f2f2, #f2f2f2)\n      display flex\n      align-items center\n      justify-content center\n      margin-bottom 32rpx\n    .reselect\n      font-size 24rpx\n      color #282828\n      text-align center\nbutton:after\n  border none\n</style>\n"
  },
  {
    "path": "src/others-edu-page/graduatePages/say-goodbye.wpy",
    "content": "<template>\n  <view>\n    <view class=\"background\"></view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  export default class Login extends wepy.page {\n    data = {};\n    onLoad() {\n      setTimeout(() => {\n        wepy.clearStorage();\n      }, 10000);\n    }\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.background\n  position absolute\n  top 0\n  left 0\n  width 100vw\n  height 100vh\n  z-index 0\n  background url('https://static.airbob.org/under-graduate/memory/goodbye.jpg') no-repeat\n  background-size auto 100%\n  background-position center\n  overflow hidden\n  display flex\n  flex-direction column\n  align-items center\n  .content\n    height 256rpx\n    font-size 36rpx\n    opacity 0.8\n    color #fff\n    margin-top 472rpx\n    writing-mode vertical-rl\n    writing-mode tb-rl\n  .farewell-btn\n    width 360rpx\n    height 80rpx\n    background-color #ffffff\n    border-radius 80rpx\n    border solid 4rpx #fff\n    display flex\n    align-items center\n    justify-content center\n    margin-top 455rpx\n    span\n      color #070f4a\n      font-size 36rpx\n\nbutton:after\n  border none\n</style>\n"
  },
  {
    "path": "src/others-edu-page/pages/GpaCalculator.wpy",
    "content": "<template lang=\"pug\">\nBaseContainer(navTitle=\"GPA计算器\")\n  view(slot=\"qy-content\")\n    view.gpa\n      view.header\n        view.banner-wrapper\n          image.banner(src=\"https://static.airbob.org/under-graduate/gpa/gpa_pic_blackboard.png\")\n        view.info-wrapper\n          text.title GPA:\n          text.gpa-number {{gpa}}\n          text.credit 已修学分：{{credits}}（除任选课）\n\n      view.gap\n\n      view.custom-score-wrapper\n        repeat(for=\"{{customScores}}\" key=\"key\" index=\"index\" item=\"score\")\n          custom-score( :score=\"score\" @modifyCredit.user=\"handleCreditInput\" @modifyCustomScore.user=\"handleCustomScore\" @modifyName.user=\"handleCourseNameInput\" @close.user=\"closeCustomScore\")\n\n\n      view.card-wrapper\n        repeat(for=\"{{scores}}\" key=\"key\" index=\"index\" item=\"score\")\n          card( :termScores.sync=\"score\" :scoreItemHeight.sync=\"scoreItemHeight\" @delete.user=\"deleteScore\" @modifyScore.user=\"handleScoreInput\")\n\n    view.footer\n      view.add-btn( @tap=\"addCouse\") 添加课程\n      view.calculate-btn( @tap=\"calculateGPA\") 查看 GPA\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport GpaCard from \"../components/GpaCard\";\nimport GpaCustomScore from \"../components/GpaCustomScore\";\nimport GpaMixin from \"../../mixins/Gpa/Gpa.js\";\nimport { getUserGrade } from \"@/api/education\";\nimport { mockGetUserGrade } from \"@/mock/education\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class GPACalculator extends wepy.page {\n  config = {\n    navigationBarTitleText: \"GPA计算器\",\n    navigationBarBackgroundColor: \"#ffffff\",\n    navigationBarTextStyle: \"black\"\n  };\n\n  data = {\n    credits: 0, // 总学分\n    sumOfCreditMultiplyPoint: 0, // 总（学分 * 单科绩点）\n    scores: [], // 所有成绩\n    customScores: [], // 自定义成绩\n    scoreItemHeight: null,\n    screenWidth: null,\n    visitorModeStatus: false\n  };\n\n  components = {\n    card: GpaCard,\n    \"custom-score\": GpaCustomScore,\n    BaseContainer\n  };\n\n  mixins = [GpaMixin, JudgeStatus];\n\n  computed = {\n    gpa() {\n      const avePoint = this.sumOfCreditMultiplyPoint / this.credits;\n      return Number.isNaN(avePoint) ? `计算中...` : avePoint.toFixed(2);\n    }\n  };\n\n  methods = {\n    // 新增自定义课程\n    addCouse() {\n      this.customScores.unshift({\n        id: Math.floor(Math.random() * 100000), // 用于删除的判断\n        name: ``,\n        credit: 0,\n        point: 0,\n        score: 0\n      });\n      this.scrollToTop();\n    },\n\n    calculateGPA() {\n      this.scrollToTop();\n    },\n\n    // 删课\n    deleteScore(credit, point, isOptionalCourses) {\n      if (isOptionalCourses) {\n        return;\n      }\n      credit = Number(credit);\n      this.handleModifyScore(-credit * point, -credit);\n    },\n\n    // 处理学分输入的逻辑\n    handleCreditInput(i, newCredit) {\n      const scoreItem = this.customScores[i];\n      const { credit: oldCredit, point: oldPoint } = scoreItem;\n      scoreItem.credit = newCredit;\n\n      this.handleModifyScore(\n        (newCredit - oldCredit) * oldPoint,\n        newCredit - oldCredit\n      );\n    },\n\n    // 处理成绩输入的逻辑\n    handleCustomScore(i, score) {\n      const scoreItem = this.customScores[i];\n      const { credit: oldCredit, point: oldPoint } = scoreItem;\n      scoreItem.score = score;\n      const newPoint = score < 60 ? 0 : (Number(score) - 50) / 10;\n      scoreItem.point = newPoint;\n\n      this.handleModifyScore((newPoint - oldPoint) * oldCredit, 0);\n    },\n\n    handleScoreInput(i, name, score, isOptionalCourses) {\n      const item = this.scores[i].scores.find(x => x.name === name);\n      item.score = score;\n      if (isOptionalCourses) return;\n\n      const { point: oldPoint, credit: oldCredit } = item;\n      const newPoint = score < 60 ? 0 : (Number(score) - 50) / 10;\n      item.point = newPoint;\n\n      this.handleModifyScore((newPoint - oldPoint) * oldCredit, 0);\n    },\n\n    // 处理课程名输入的逻辑\n    handleCourseNameInput(i, name) {\n      this.customScores[i].name = name;\n    },\n\n    // 删除自定义成绩\n    closeCustomScore(id) {\n      const scores = this.customScores;\n      for (let i = 0; i < scores.length; i++) {\n        if (scores[i].id === id) {\n          const { credit, point } = scores[i];\n          this.handleModifyScore(-credit * point, -credit);\n          scores.splice(i, 1);\n        }\n      }\n    }\n  };\n\n  // 获取成绩\n  getScore() {\n    return !this.visitorModeStatus ? getUserGrade() : mockGetUserGrade();\n  }\n\n  // 初始化成绩数据\n  async initData() {\n    if (this.hasData()) {\n      const { credits, scores, sumOfCreditMultiplyPoint } = this.handleScores();\n\n      this.handleFirstScores(scores[0]);\n      this.mountData(credits, scores, sumOfCreditMultiplyPoint);\n      this.$apply();\n\n      this.setScoreItemHeight();\n    } else {\n      const { data: res } = await this.getScore();\n\n      if (res.success === true) {\n        const { data } = res;\n        const sortScore = data.score.sort(\n          (x, y) =>\n            Number(x.year.substring(0, 4)) - Number(y.year.substring(0, 4)) ||\n            Number(x.term) - Number(y.term)\n        );\n        const { credits, scores, sumOfCreditMultiplyPoint } = this.handleScores(\n          sortScore\n        );\n        this.handleFirstScores(scores[0]);\n        this.mountData(credits, scores, sumOfCreditMultiplyPoint);\n        this.$apply();\n        this.setScoreItemHeight();\n      } else {\n        return false;\n      }\n    }\n  }\n\n  mountData(credits, scores, sumOfCreditMultiplyPoint) {\n    this.credits = credits;\n    this.scores = scores;\n    this.sumOfCreditMultiplyPoint = sumOfCreditMultiplyPoint;\n  }\n\n  scrollToTop() {\n    wepy.pageScrollTo({\n      scrollTop: 0,\n      duration: 500\n    });\n  }\n\n  handleFirstScores(score) {\n    score.isFolded = false; // 打开第一张卡片\n    score.showGuide = 1;\n    setTimeout(() => {\n      score.showGuide = 0;\n      this.$apply();\n    }, 4000);\n    setTimeout(() => {\n      score.showGuide = -1;\n      this.$apply();\n    }, 4500);\n  }\n\n  async getScoreItemHeight() {\n    const { screenWidth } = await wepy.getSystemInfo();\n    this.screenWidth = screenWidth;\n\n    wepy\n      .createSelectorQuery()\n      .select(\".score-item\")\n      .boundingClientRect()\n      .exec(res => {\n        if (res[0] !== null) {\n          this.scoreItemHeight = res[0].height;\n          this.$apply();\n        }\n      });\n  }\n\n  setScoreItemHeight() {\n    let timer = setInterval(() => {\n      this.getScoreItemHeight();\n\n      if (this.scoreItemHeight !== null && this.screenWidth !== null) {\n        clearInterval(timer);\n        timer = null;\n      }\n    }, 100);\n  }\n\n  // 页面加载的时候请求成绩数据\n  onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name).then(() => {\n      this.initData();\n    });\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.gpa\n  .header\n    position relative\n    padding-top 30rpx\n    .banner-wrapper\n      display flex\n      position relative\n      z-index -1\n      width 100%\n      justify-content center\n      .banner\n        width 680rpx\n        height 250rpx\n        border-radius 24rpx\n        box-shadow 0 3rpx 18rpx rgba(0, 0, 0, 0.117647), 0 3rpx 12rpx rgba(0, 0, 0, 0.117647)\n    .info-wrapper\n      position absolute\n      display flex\n      top 30rpx\n      padding 16rpx 50rpx\n      z-index 1\n      width 100%\n      height calc(100% - 30rpx)\n      box-sizing border-box\n      flex-direction column\n      justify-content space-around\n      text\n        display block\n        text-align center\n        font-weight bold\n        color #fff\n      .title\n        font-size 36rpx\n        line-height 36rpx\n      .gpa-number\n        margin-top -16rpx\n        font-size 100rpx\n        line-height 88rpx\n      .credit\n        font-size 24rpx\n        line-height 24rpx\n  .gap\n    margin 60rpx 0 30rpx 0\n    height 20rpx\n    background #f5f5f5\n  .custom-score-wrapper\n    margin 0 20rpx 0 20rpx\n  .card-wrapper\n    margin 0 20rpx\n    padding-bottom 120rpx\n.footer\n  display flex\n  position fixed\n  z-index 4\n  bottom 0\n  width 100%\n  height 100rpx\n  .add-btn, .calculate-btn\n    display flex\n    flex 1\n    font-size 36rpx\n    font-weight bold\n    color #fff\n    justify-content center\n    align-items center\n  .add-btn\n    background linear-gradient(-45deg, #ff9c77, #ffe388)\n  .calculate-btn\n    background linear-gradient(-225deg, #aaee7b, #5ae090)\n</style>\n"
  },
  {
    "path": "src/others-edu-page/pages/calendar.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <image src=\"https://static.airbob.org/2019-2020/QjE2MDEyMzI3LTIwMTktMjAyMC5qcGc=\" mode=\"widthFix\" class=\"img\">\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport JudgeStatus from \"@/mixins/module\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"校历\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"校历\"\n  };\n  mixins = [JudgeStatus];\n  onLoad(op) {\n    this.judgeStatus(op.name);\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.img\n  width 100vw\n</style>\n"
  },
  {
    "path": "src/others-edu-page/pages/pe-score.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"体育部\" :passwordModelOptions.sync=\"passwordModelOptions\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"background\"/>\n        <view class=\"head-container\">\n          <view class=\"button-list\">\n            <view class=\"button-common {{current==='class'?'button-active':''}}\" @tap.stop=\"toClass\">体育课</view>\n            <view class=\"button-common {{current==='test'?'button-active':''}}\" @tap.stop=\"toTest\">体测</view>\n          </view>\n          <image\n            class=\"head-icon\"\n            src=\"https://static.airbob.org/under-graduate/%E4%BD%93%E8%82%B2%E6%88%90%E7%BB%A9/Sport.png\"\n            mode=\"widthFix\"\n          >\n        </view>\n        <block wx:if=\"{{current==='class'}}\">\n          <repeat for=\"{{peClass}}\" key=\"index\" item=\"item\" index=\"index\">\n            <PeCard1\n              :result.sync=\"item\"\n              :titleBgColor.sync=\"titleBgColor[index%2]\"\n              :animation.sync=\"peClassAnimations[index]\"\n              :indexx=\"index\"\n            />\n          </repeat>\n        </block>\n        <block wx:if=\"{{(peClass.length === 0 && current==='class')}}\">\n          <view class=\"no-container\">\n            <image\n              class=\"no-image\"\n              mode=\"widthFix\"\n              src=\"https://static.airbob.org/under-graduate/%E8%BE%B9%E7%95%8C%E6%83%85%E5%86%B52.png\"\n            >\n            <view class=\"no-text\">还没参加过体育考试，但要多运动哦</view>\n          </view>\n        </block>\n        <block wx:if=\"{{current==='test'}}\">\n          <repeat for=\"{{peTest}}\" key=\"index\" item=\"item\" index=\"index\">\n            <PeCard2\n              :result.sync=\"item\"\n              :titleBgColor.sync=\"titleBgColor[index%2]\"\n              :animation.sync=\"peTestAnimations[index]\"\n              :indexx=\"index\"\n            />\n          </repeat>\n        </block>\n        <block wx:if=\"{{peTest.length === 0 && current==='test'}}\">\n          <view class=\"no-container\">\n            <image\n              class=\"no-image\"\n              mode=\"widthFix\"\n              src=\"https://static.airbob.org/under-graduate/%E8%BE%B9%E7%95%8C%E6%83%85%E5%86%B52.png\"\n            >\n            <view class=\"no-text\">还没参加过体测，但要多运动哦</view>\n          </view>\n        </block>\n        <!-- <QyBinding :isGet=\"isGet\" :visible.sync=\"bindingVisible\" :zIndex=\"bindingZIndex\" :width=\"bindingWidth\" :height=\"bindingHeight\" :top=\"bindingTop\" :mockURL.sync=\"bindingURL\" :domainType.sync=\"bindingDomainType\" :domainUserName.sync=\"studentId\" :VerifyURL.sync=\"bindingDomainVerifyURL\"></QyBinding> -->\n        <!-- <QyBinding :visible.sync=\"bindingVisible\"  :mockURL.sync=\"URL\" :domainType.sync=\"bindingDomainType\" :domainUserName=\"studentId\" :VerifyURL=\"bindingDomainVerifyURL\"></QyBinding> -->\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport PeCard from \"../components/pe-card\";\nimport { getUserPEGrade, changeSecretCode } from \"@/api/common\";\nimport { mockGetUserPEGrade } from \"@/mock/common\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class PeScore extends wepy.page {\n  components = {\n    PeCard1: PeCard,\n    PeCard2: PeCard,\n    BaseContainer\n  };\n  data = {\n    current: \"class\", // or test\n    peClass: [],\n    peClassShows: [],\n    peClassAnimations: [],\n    peTest: [],\n    peTestShows: [],\n    peTestAnimations: [],\n    titleBgColor: [\"rgb(20,126,232)\", \"rgb(239,90,97)\"],\n    winWidth: 750,\n    bindModalVisible: false,\n    bindInputPassword: \"\",\n    passwordModelOptions: {\n      passwordModelProps: false,\n      placeholder: \"请输入体育部密码\",\n      refreshData: this.check,\n      bindInfo: {\n        username: wepy.getStorageSync(\"User\").studentId,\n        domainType: \"2\"\n      }\n    },\n    visitorModeStatus: false\n  };\n  config = {\n    navigationBarTitleText: \"体育部\"\n  };\n  mixins = [JudgeStatus];\n  onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name).then(async () => {\n      const { studentId } = wepy.getStorageSync(\"User\");\n      this.studentId = studentId;\n      wepy.showLoading({\n        title: \"加载中\"\n      });\n      await this.check();\n      wepy.hideLoading();\n    });\n  }\n  methods = {\n    toTest() {\n      if (this.current !== \"test\") {\n        this.current = \"test\";\n      }\n    },\n    toClass() {\n      if (this.current !== \"class\") {\n        this.current = \"class\";\n      }\n    },\n    bindCardPassword(e) {\n      this.bindInputPassword = e.detail.value;\n    }\n  };\n  async check() {\n    const { data: check } = this.visitorModeStatus\n      ? await mockGetUserPEGrade()\n      : await getUserPEGrade(`20${this.studentId.slice(1, 3)}`, \"00\");\n    if (check && check.success) {\n      // 校验成功\n      this.getData();\n      this.passwordModelOptions.passwordModelProps = false;\n    } else {\n      this.passwordModelOptions.passwordModelProps = true;\n    }\n    this.$apply();\n  }\n  async getData() {\n    const fetchData1 = [];\n    const fetchData2 = [];\n    const studentYear = this.visitorModeStatus\n      ? \"18\"\n      : this.studentId.slice(1, 3); // 学生年级\n    const tempYear = [\n      `20${studentYear}`,\n      `20${parseInt(studentYear) + 1}`,\n      `20${parseInt(studentYear) + 2}`,\n      `20${parseInt(studentYear) + 3}`\n    ]; // 四年\n    const allTestReq = this.visitorModeStatus\n      ? tempYear.slice(0, 2).map(item => mockGetUserPEGrade()) //  游客模式下只获取两年数据去展示\n      : tempYear.map(item => getUserPEGrade(item, \"00\"));\n    // 获取体测数据\n    let total1;\n    Promise.all(allTestReq).then(Tests => {\n      Tests.forEach((item, index) => {\n        if (item.data && item.data.data && item.data.data.length > 1) {\n          fetchData1.push({\n            term: \"体测\",\n            data: item.data.data,\n            year: `${tempYear[index].slice(0, 4)}-${parseInt(\n              tempYear[index].slice(0, 4)\n            ) + 1}学年`\n          });\n        }\n      });\n      fetchData1.forEach(item => {\n        for (let i = 0; i < item.data.length; i++) {\n          if (item.data[i].project === \"total\") {\n            total1 = item.data.splice(i, 1);\n            break;\n          }\n        }\n        item.data.sort((a, b) => b.mark - a.mark);\n        item.data.push(total1[0]);\n      });\n      this.peTest = fetchData1.reverse();\n      this.peTestShows = new Array(fetchData1.length).fill(false);\n      this.peTestAnimations = new Array(fetchData1.length).fill({});\n      this.$apply();\n    });\n    // 获取体育成绩 大一大二\n    const allClassReq1 = tempYear\n      .slice(0, 2)\n      .map(item =>\n        this.visitorModeStatus\n          ? mockGetUserPEGrade()\n          : getUserPEGrade(item, \"01\")\n      );\n    const allClassReq2 = tempYear\n      .slice(0, 2)\n      .map(item =>\n        this.visitorModeStatus\n          ? mockGetUserPEGrade()\n          : getUserPEGrade(item, \"02\")\n      );\n    let total2;\n    Promise.all([...allClassReq1, ...allClassReq2]).then(Classes => {\n      Classes.forEach((item, index) => {\n        if (item.data && item.data.data && item.data.data.length > 1) {\n          fetchData2.push({\n            term: `第${(index >> 1) + 1}学期`,\n            data: item.data.data,\n            year: `${tempYear[index % 2].slice(0, 4)}-${parseInt(\n              tempYear[index % 2].slice(0, 4)\n            ) + 1}学年`\n          });\n        }\n      });\n      // 把总分调到最后一项\n      fetchData2.forEach(item => {\n        for (let i = 0; i < item.data.length; i++) {\n          if (item.data[i].project === \"total\") {\n            total2 = item.data.splice(i, 1);\n            break;\n          }\n        }\n        item.data.sort((a, b) => b.mark - a.mark);\n        item.data.push(total2[0]);\n      });\n      this.peClass = fetchData2.sort(\n        (x, y) =>\n          Number(x.year.split(\"-\")[0]) - Number(y.year.split(\"-\")[0]) < 0\n      );\n      this.peClassShows = new Array(fetchData2.length).fill(false);\n      this.peClassAnimations = new Array(fetchData2.length).fill({});\n      this.$apply();\n    });\n    const systemInfo = await wepy.getSystemInfo();\n    this.winWidth = systemInfo.windowWidth;\n  }\n  events = {\n    changeClassShow: index => {\n      const animation = wepy.createAnimation({\n        timingFunction: \"ease-in-out\",\n        duration: 1000\n      });\n      if (this.peClassShows[index]) {\n        // 去关闭\n        this.peClassAnimations[index] = animation\n          .height(\"0rpx\")\n          .step()\n          .export();\n        this.$apply();\n      } else {\n        // 去打开\n        const query = wepy\n          .createSelectorQuery()\n          .select(`#Class-${index}`)\n          .boundingClientRect();\n        query.exec(res => {\n          const real = ((res[0].height + 50) * 750) / this.winWidth + \"rpx\";\n          this.peClassAnimations[index] = animation\n            .height(real)\n            .step()\n            .export();\n          this.$apply();\n        });\n      }\n      this.peClassShows[index] = !this.peClassShows[index];\n    },\n    changeTestShow: index => {\n      const animation = wepy.createAnimation({\n        timingFunction: \"ease-in-out\",\n        duration: 1000\n      });\n      if (this.peTestShows[index]) {\n        this.peTestAnimations[index] = animation\n          .height(\"0rpx\")\n          .step()\n          .export();\n        this.$apply();\n      } else {\n        // 去打开\n        const query = wepy\n          .createSelectorQuery()\n          .select(`#Test-${index}`)\n          .boundingClientRect();\n        query.exec(res => {\n          const real = ((res[0].height + 50) * 750) / this.winWidth + \"rpx\";\n          this.peTestAnimations[index] = animation\n            .height(real)\n            .step()\n            .export();\n          this.$apply();\n        });\n      }\n      this.peTestShows[index] = !this.peTestShows[index];\n    }\n  };\n}\n</script>\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  align-items center\n  .no-container\n    .no-image\n      width 400rpx\n      margin-top 129rpx\n    .no-text\n      color #999CA0\n      font-size 28rpx\n      margin-top 55rpx\n      text-align center\n  .background\n    position fixed\n    width 100vw\n    height 100vh\n    background-color rgb(#C2D8F8)\n    z-index -1000\n  .head-container\n    display flex\n    flex-direction column\n    align-items center\n    width 100%\n    height 284rpx\n    background-size cover\n    background-position-y -116rpx\n    background-image url('https://static.airbob.org/under-graduate/%E4%BD%93%E8%82%B2%E6%88%90%E7%BB%A9/Half.png')\n    .button-list\n      display flex\n      margin-top 58rpx\n      justify-content space-between\n      width 381rpx\n      .button-common\n        width 157rpx\n        height 63rpx\n        line-height 63rpx\n        font-size 30rpx\n        text-align center\n        border-radius 33rpx\n        font-family 'SimHei'\n        background-color white\n        background-image url('https://static.airbob.org/under-graduate/supplementary/%E6%8C%89%E9%92%AE%E8%99%9A%E7%BA%BF.png')\n        background-size contain\n        background-repeat no-repeat\n        color rgb(53, 53, 53)\n        cursor pointer\n      .button-active\n        background-color rgb(101, 205, 230)\n        color rgb(255, 255, 255)\n        background-image none\n    .head-icon\n      width 102rpx\n      margin-top 23rpx\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 485rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "src/others-page/components/bus-card.wpy",
    "content": "<template>\n  <view class=\"bus-container\">\n    <view class=\"bus-during\">{{during}}</view>\n    <view class=\"bus-sites-wrapper\">\n      <view class=\"sites-container\">\n        <view class=\"site start\">\n          <view class=\"tips\">始发站 {{departureTime.hour}}:{{departureTime.minute}}</view>\n          <view class=\"site-text\">\n            <view class=\"circle-container\">\n              <view class=\"ring\" style=\"border-color: {{color}}\">\n                <view class=\"vertical-line start\" style=\"background-color: {{color}}\" hidden=\"{{!showStop}}\"/>\n              </view>    \n            </view>\n            <view class=\"text\">{{start}}</view>\n          </view>\n        </view>\n        <view class=\"site-via-container\" animation=\"{{cardAnimation}}\">\n          <repeat for=\"{{stopSites}}\" key=\"index\" index=\"siteIndex\" item=\"item\">\n            <view class=\"site via\">\n              <view class=\"tips via\" wx:if=\"{{item.time}}\">预计到达 {{item.time.hour}}:{{item.time.minute}}</view>\n              <view class=\"site-text\">\n                <view class=\"circle-container\">\n                  <view class=\"round\" style=\"background-color: {{color}}\">\n                    <view class=\"vertical-line via\" style=\"background-color: {{color}}\"/>\n                  </view>\n                </view>\n                <view class=\"text via\">{{item.name}}</view>\n              </view>\n            </view>\n          </repeat>\n        </view>\n        <view class=\"site end\">\n          <view class=\"tips\">终点站</view>\n          <view class=\"site-text\">\n            <view class=\"circle-container\">\n              <view class=\"ring\" style=\"border-color: {{color}}\">\n                <view class=\"vertical-line end\" style=\"background-color: {{color}}\" hidden=\"{{!showStop}}\"/>\n              </view>\n            </view>\n            <view class=\"text\">{{destination}}</view>\n          </view>\n        </view>\n      </view>\n      <view class=\"arrow-container\" @tap.stop=\"showStopSites\" data-index=\"{{index}}\">\n        <view class=\"text\">途经站</view>\n        <view class=\"arrow-down {{showStop ? 'active' : ''}}\"/>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class BusCard extends wepy.component {\n  props = {\n    stopSites: {\n      type: Array,\n      default: []\n    },\n    departureTime: {\n      type: Object,\n      default: {}\n    },\n    start: {\n      type: String,\n      default: \"\"\n    },\n    destination: {\n      type: String,\n      default: \"\"\n    },\n    during: {\n      type: String,\n      default: \"\"\n    },\n    index: {\n      type: Number,\n      default: -1\n    },\n    cardAnimation: {\n      type: Object,\n      default: {}\n    },\n    color: {\n      type: String,\n      default: \"\"\n    },\n    showStop: {\n      type: Boolean,\n      default: false\n    }\n  };\n  methods = {\n    showStopSites(e) {\n      const { index } = e.currentTarget.dataset;\n      this.$emit(\"showStopSites\", index);\n    }\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.bus-container\n  padding 40rpx\n  .bus-during\n    text-align right\n  .bus-sites-wrapper\n    display flex\n    justify-content space-between\n    .sites-container\n      min-height 250rpx\n      display flex\n      flex-direction column\n      justify-content space-between\n      .site-via-container\n        display flex\n        flex-direction column\n        justify-content space-around\n        overflow hidden\n        height 0\n      .site\n        margin 22.5rpx 0\n        &.start\n          margin-top 0\n        &.end\n          margin-bottom 20rpx\n        .tips\n          min-width 150rpx\n          font-size 28rpx\n          border-bottom 1px solid #ccc\n          margin-left 52rpx\n          padding-bottom 3rpx\n          color #353535\n          &.via\n            opacity 0.8\n            font-size 22rpx\n        .site-text\n          width 100%\n          display flex\n          align-items center\n          .text\n            margin-left 16rpx\n            &.via\n              font-size 25rpx\n          .circle-container\n            width 36rpx\n            height 36rpx\n            display flex\n            justify-content center\n            align-items center\n            .ring\n              width 20rpx\n              height 20rpx\n              background-color #ffffff\n              border-radius 50%\n              border 8rpx solid\n            .round\n              width 20rpx\n              height 20rpx\n              border-radius 50%\n              border 8rpx solid #fff\n            .vertical-line\n              width 8rpx\n              height 120rpx\n              margin 0 auto\n              &.start\n                transform translateY(20rpx)\n              &.via\n                // height 120rpx\n                transform translateY(16rpx)\n              &.end\n                transform translateY(-100%)\n    .arrow-container\n      display flex\n      justify-content center\n      align-items center\n      .arrow-down\n        display inline-block\n        position relative\n        width 60rpx\n        height 30rpx\n        margin-left 10rpx\n        transition transform 0.4s\n        transform-origin center\n        transform rotate(0)\n        &::after\n          display inline-block\n          content \" \"\n          height 18rpx\n          width 18rpx\n          border-width 0 2px 2px 0\n          border-color #999999\n          border-style solid\n          transform matrix(0.71, 0.71, -0.71, 0.71, 0, 0)\n          transform-origin center\n          transition transform 0.3s\n          position absolute\n          top 50%\n          right 10px\n          margin-top -14rpx\n        &.active\n          transition transform 0.4s\n          transform-origin center\n          transform rotate(-180deg)\n</style>\n"
  },
  {
    "path": "src/others-page/components/changeLogItem.wpy",
    "content": "<template>\n  <view>\n    <view class=\"item-header\">\n      <image src=\"https://static.airbob.org/under-graduate/circle.png\" class=\"header-round\">\n      <text>{{log.title}}</text>\n    </view>\n    <view class=\"item-body\">\n      <view class=\"change-item\" wx-if=\"{{log.content !== ''}}\">更新概述：</view>\n      <repeat for=\"{{log.content}}\">\n        <view class=\"change-item\">{{index + 1}}. {{item}}</view>\n      </repeat>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\n\nexport default class extends wepy.component {\n  props = {\n    log: Object\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.item-header\n  color #f65357\n  font-size 36rpx\n  margin 2rpx 0\n  .header-round\n    width 40rpx\n    height 40rpx\n    margin 0 48rpx 0 0\n    vertical-align middle\n  text\n    vertical-align middle\n.item-body\n  margin 0 30rpx 0 20rpx\n  border-left #6f8392 solid 4rpx\n  padding 20rpx 0 40rpx 0\n  .change-item\n    margin-left 68rpx\n    font-size 30rpx\n    color #a4b6c2\n    line-height 1.5\n</style>\n"
  },
  {
    "path": "src/others-page/components/information-card.wpy",
    "content": "<template>\n  <view class=\"info-container\" id=\"tag{{id}}\">\n    <view wx:if=\"{{info.length !== 0}}\">\n      <repeat for=\"{{info}}\" key=\"index\" index=\"index\" item=\"item\">\n        <view\n          class=\"{{item.read ? 'box-item-read' : 'box-item-unread'}} {{item.ontap ? 'box-item-tap' : ''}}\"\n          @tap=\"tapCard\"\n          data-taptype=\"{{item.type}}\"\n          data-title=\"{{item.title}}\"\n          data-id=\"{{item.id}}\"\n          data-ontap=\"{{item.ontap}}\"\n          data-read=\"{{item.read}}\"\n        >\n          <view class=\"box-item-container\">\n            <view class=\"box-item-in\">\n              <view\n                class=\"lines\"\n                style=\"font-size:34rpx;padding-top:20rpx;color:#353535;font-weight:bold;\"\n              >\n                <view wx:if=\"{{!item.read}}\" class=\"dot\"></view>\n                {{item.title}}{{item.ontap?'*点击*':''}}\n              </view>\n              <view class=\"lines\">\n                <repeat for=\"{{item.content}}\" key=\"index2\" index=\"index2\" item=\"content\">\n                  <view>{{content}}</view>\n                </repeat>\n              </view>\n              <view class=\"lines\" style=\"color:#888888;font-size:24rpx;\">{{item.creatDate}}</view>\n            </view>\n            <view class=\"right-line\"></view>\n          </view>\n        </view>\n      </repeat>\n    </view>\n    <view wx:else class=\"noInfo\">目前没有这类通知哦~</view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class InfoCard extends wepy.component {\n  props = {\n    info: {\n      type: Array,\n      default: []\n    },\n    id: {\n      type: Number,\n      default: -1\n    }\n  };\n  methods = {\n    tapCard(e) {\n      this.$emit(\"tapCard\", e.currentTarget.dataset);\n    }\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.info-container\n  width 100vw\n  height 100%\n  overflow-y auto\n  display inline-block\n  white-space normal\n  .noInfo\n    width 100%\n    height 100%\n    display flex\n    justify-content center\n    align-items center\n    font-size 32rpx\n    font-weight 800\n  .box-item-read\n    width 700rpx\n    min-height 150rpx\n    margin-top 30rpx\n    margin-left 25rpx\n    background #F5F5F5\n    border-radius 15rpx\n    color #888888\n    display flex\n    align-items center\n    font-size 24rpx\n    .box-item-container\n      width 700rpx\n      .box-item-in\n        width 620rpx\n        margin 0 auto\n        .lines\n          overflow hidden\n          padding-bottom 20rpx\n          font-size 28rpx\n  .box-item-unread\n    width 700rpx\n    min-height 150rpx\n    margin-top 30rpx\n    margin-left 25rpx\n    background #D8D8D8\n    background-image linear-gradient(-225deg, #E5F4FF 0%, #E8FBFF 100%)\n    border-radius 15rpx\n    color #353535\n    font-size 24rpx\n    .box-item-container\n      width 700rpx\n      display flex\n      .box-item-in\n        min-height 150rpx\n        width 620rpx\n        display flex\n        align-items center\n        flex-wrap wrap\n        margin 0 auto\n        .lines\n          flex-grow 0\n          width 620rpx\n          text-align justify\n          overflow hidden\n          padding-bottom 20rpx\n          font-size 28rpx\n          .dot\n            background #47CFF5\n            width 15rpx\n            height 15rpx\n            margin-right 15rpx\n            display inline-block\n            border-radius 50%\n      .right-line\n        width 14rpx\n        min-height 150rpx\n        background #47CFF5\n        overflow hidden\n        border-top-right-radius 15rpx\n        border-bottom-right-radius 15rpx\n  .box-item-tap\n    background #d8d8d8\n    background-image linear-gradient(44deg, #f7e5a4 0%, #fee082 100%)\n    .box-item-container\n      .right-line\n        background #f6b500\n      .box-item-in\n        .lines\n          .dot\n            background #f6b500\n</style>\n"
  },
  {
    "path": "src/others-page/components/seats-card.wpy",
    "content": "<template>\n  <view class=\"floor-contanier\">\n    <view class=\"floor-head\">{{lib.floor}}层</view>\n    <view class=\"floor-room\">\n      <repeat for=\"{{lib.rooms}}\" key=\"key\" index=\"index\" item=\"item\">\n        <view class=\"circleProgress-wrapper\">\n          <view\n            class=\"right\"\n            style=\"-webkit-transform:rotate({{(item.curSeats/item.totalSeats)*360<=180?(item.curSeats/item.totalSeats)*360:0}}deg);background-color:{{(item.curSeats/item.totalSeats)*360<=180?'#f5f5f5':'#39c9ff'}};\"\n          >\n            <view class=\"clip-right\"></view>\n          </view>\n          <view\n            class=\"left\"\n            style=\"-webkit-transform:rotate({{(item.curSeats/item.totalSeats)*360<=180?0:(item.curSeats/item.totalSeats-0.5)*360}}deg)\"\n          >\n            <view class=\"clip-left\"></view>\n          </view>\n          <view class=\"seats-left\">{{item.curSeats}}</view>\n        </view>\n        <view class=\"floor-room-info\">\n          <view style=\"font-size:28rpx;font-weight:bold\">{{item.name}}</view>\n          <view style=\"font-size:24rpx;\">总座位数：{{item.totalSeats}}</view>\n        </view>\n      </repeat>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nexport default class extends wepy.component {\n  data = {\n    screenWidth: 0,\n    dpr: 0\n  };\n  props = {\n    lib: {\n      type: Object,\n      default: {},\n      twoWay: true\n    }\n  };\n  methods = {};\n  async onLoad() {\n    await wepy.getSystemInfo().then(res => {\n      this.screenWidth = parseInt(res.screenWidth);\n      this.dpr = res.pixelRatio;\n    });\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.floor-contanier\n  width 750rpx\n  height 200rpx\n  margin 30rpx 20rpx 10rpx 20rpx\n  font-size 30rpx\n  .floor-head\n    font-weight bold\n    margin-bottom 30rpx\n  .floor-room\n    width 750rpx\n    height 200rpx\n    display flex\n    justify-content flex-start\n    .circleProgress-wrapper\n      font-size 0rpx\n      width 100rpx\n      height 100rpx\n      position relative\n      border-radius 50%\n      background-color #39c9ff\n      .right\n        width 100rpx\n        height 100rpx\n        position absolute\n        border-radius 50%\n        top 0\n        left 0\n        background-color #f5f5f5\n        clip rect(0, auto, auto, 50rpx)\n        z-index 2\n        .clip-right\n          width 100rpx\n          height 100rpx\n          position absolute\n          top 0\n          left 0\n          clip rect(0, auto, auto, 50rpx)\n      .left\n        width 100rpx\n        height 100rpx\n        position absolute\n        border-radius 50%\n        top 0\n        left 0\n        background #f5f5f5\n        clip rect(0, 50rpx, auto, 0)\n        .clip-left\n          width 100rpx\n          height 100rpx\n          position absolute\n          top 0\n          left 0\n          clip rect(0, 50rpx, auto, 0)\n      .seats-left\n        width 75rpx\n        height 75rpx\n        border-radius 50%\n        position absolute\n        left 0\n        right 0\n        bottom 0\n        top 0\n        margin auto\n        font-size 40rpx\n        line-height 75rpx\n        font-weight bolder\n        text-align center\n        background #ffffff\n        z-index 12\n    .floor-room-info\n      color #353535\n      width 200rpx\n      height 100rpx\n      display flex\n      flex-direction column\n      justify-content center\n      margin-right 42rpx\n      margin-left 30rpx\n</style>\n"
  },
  {
    "path": "src/others-page/mixins/all-search-thing.js",
    "content": "import wepy from \"wepy\";\n\nexport default class allSearch extends wepy.mixin {\n  allSearchThing() {\n    const AllSearhes = [\n      {\n        name: \"图书馆\",\n        icon: \"https://static.airbob.org/under-graduate/more/library.png\",\n        isIndex: true,\n        id: 0,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"已借书目\",\n        icon: \"https://static.airbob.org/under-graduate/more/borrow.png\",\n        isIndex: false,\n        id: 1,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"检索书目\",\n        icon: \"https://static.airbob.org/under-graduate/more/retrieval.png\",\n        isIndex: false,\n        id: 2,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"座位查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/seat inquiry.png\",\n        isIndex: false,\n        id: 3,\n        path: \"../others-page/pages/libraryPages/library\",\n        isOpen: true,\n        module: \"图书馆\"\n      },\n      {\n        name: \"一卡通\",\n        icon: \"https://static.airbob.org/under-graduate/more/card.png\",\n        isIndex: true,\n        id: 4,\n        path: \"../campus-card-page/pages/campus-card-index\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"校园卡充值\",\n        icon: \"https://static.airbob.org/under-graduate/more/recharge.png\",\n        isIndex: false,\n        id: 5,\n        path: \"../campus-card-page/pages/campus-card-charge\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"电费充值\",\n        icon: \"https://static.airbob.org/under-graduate/more/electricity.png\",\n        isIndex: false,\n        id: 6,\n        path: \"../campus-card-page/pages/electric-charge\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"校园网充值\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/ campus network.png\",\n        isIndex: false,\n        id: 7,\n        path: \"../campus-card-page/pages/net-charge\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"校园卡挂失\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/report the loss.png\",\n        isIndex: false,\n        id: 8,\n        path: \"../campus-card-page/pages/campus-card-loss\",\n        isOpen: true,\n        module: \"一卡通\"\n      },\n      {\n        name: \"成绩查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/results query.png\",\n        isIndex: true,\n        id: 9,\n        path: \"../edu-admin-page/pages/score-inquire\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"体育部\",\n        icon: \"https://static.airbob.org/under-graduate/more/sport.png\",\n        isIndex: true,\n        id: 10,\n        path: \"../others-edu-page/pages/pe-score\",\n        isOpen: true,\n        module: \"体育部\"\n      },\n      {\n        name: \"考试倒计时\",\n        icon: \"https://static.airbob.org/under-graduate/more/exam.png\",\n        isIndex: false,\n        id: 11,\n        path: \"../edu-admin-page/pages/course\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"等级考试\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/rank examination.png\",\n        isIndex: false,\n        id: 12,\n        path: \"../edu-admin-page/pages/check-grade\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"补考查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/resit.png\",\n        isIndex: true,\n        id: 13,\n        path: \"../edu-admin-page/pages/cut-down\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"辅导课查询\",\n        icon:\n          \"https://static.airbob.org/under-graduate/more/prenatal class.png\",\n        isIndex: false,\n        id: 14,\n        path: \"../edu-admin-page/pages/supplement-and-tutorials\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"GPA计算器\",\n        icon: \"https://static.airbob.org/under-graduate/more/gpa.png\",\n        isIndex: false,\n        id: 15,\n        path: \"../others-edu-page/pages/GpaCalculator\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"课表\",\n        icon: \"https://static.airbob.org/under-graduate/more/timetable.png\",\n        isIndex: true,\n        id: 16,\n        path: \"../edu-admin-page/pages/course\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"校历\",\n        icon: \"https://static.airbob.org/under-graduate/more/calendar.png\",\n        isIndex: true,\n        id: 17,\n        path: \"../others-edu-page/pages/calendar\",\n        isOpen: true,\n        module: \"校历\"\n      },\n      {\n        name: \"自主学分\",\n        icon: \"https://static.airbob.org/under-graduate/more/credit.png\",\n        isIndex: false,\n        id: 18,\n        path: \"../edu-admin-page/pages/credit\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"晨跑\",\n        icon: \"https://static.airbob.org/under-graduate/more/run.png\",\n        isIndex: true,\n        id: 19,\n        path: \"../others-page/pages/run\",\n        isOpen: true,\n        module: \"晨跑\"\n      },\n      {\n        name: \"学费查询\",\n        icon: \"https://static.airbob.org/under-graduate/more/tuition.png\",\n        isIndex: false,\n        id: 20,\n        path: \"../others-page/pages/tuition\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"社团招新\",\n        icon: \"https://static.airbob.org/under-graduate/more/club.png\",\n        isIndex: false,\n        id: 21,\n        path: \"../others-page/pages/associationPages/association\",\n        isOpen: true,\n        module: \"正方\"\n      },\n      {\n        name: \"认证\",\n        icon: \"https://static.airbob.org/under-graduate/more/club.png\",\n        isIndex: false,\n        id: 22,\n        path: \"../others-page/pages/auth\",\n        isOpen: true,\n        module: \"正方\"\n      }\n    ];\n    return AllSearhes;\n  }\n}\n"
  },
  {
    "path": "src/others-page/mixins/page-jump.js",
    "content": "import wepy from \"wepy\";\n\nexport default class allSearch extends wepy.mixin {\n  methods = {\n    toAssociationHome() {\n      /**\n       * 如果路由栈中，招新首页前面还有页面，就navigateBack到招新首页\n       * 如果路由栈中，不存在招新首页，或者路由栈最底层是招新首页，就reLaunch到招新首页\n       */\n      const routes = getCurrentPages();\n      const ASSOCIATION_PATH = \"others-page/pages/associationPages/association\";\n      const index = routes.findIndex(page => page.route === ASSOCIATION_PATH);\n      if (index > 0) {\n        const deps = routes.length - index - 1;\n        wepy.navigateBack({\n          delta: deps\n        });\n      } else {\n        wepy.reLaunch({ url: `/${ASSOCIATION_PATH}` });\n      }\n    }\n  };\n}\n"
  },
  {
    "path": "src/others-page/pages/advertisement.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <image src=\"{{ adDetail.adPicUrl }}\" class=\"head-image\">\n    <view class=\"news-title\">{{ adDetail.adTitle }}</view>\n    <view class=\"news-date\">\n      发布时间：{{ date }}\n      <view class=\"ads-tip\" wx-if=\"{{adType === 1}}\">推广资讯</view>\n    </view>\n    <view class=\"news-content\">\n      <rich-text nodes=\"{{ content }}\"></rich-text>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport filterWxs from \"../wxs/filter.wxs\";\nimport navigation from \"@/components/qy-navigation\";\nimport { getNewsAdvertisementDetail } from \"@/api/common\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"资讯详情\",\n    adDetail: {},\n    date: \"\",\n    content: \"\"\n  };\n\n  wxs = {\n    filterWxs\n  };\n\n  // TODO: 后端要记得改 url，前端之后要么删除这个方法要么把 http:// 改成 https://\n  formatImageUrl(url) {\n    return /https?:\\/\\//.test(url) ? url : `http://${url}`;\n  }\n\n  onLoad(option) {\n    let that = this;\n    getNewsAdvertisementDetail(option.adId).then(\n      ({ data: { data, success } }) => {\n        if (success) {\n          this.adDetail = data;\n          const weRich = require(\"we-rich\");\n          this.content = weRich.parse(data.adContent);\n          this.date = this.$parent.timeToDate(data.gmtCreate);\n          this.adDetail.adPicUrl = this.formatImageUrl(data.adPicUrl);\n          this.$apply();\n        }\n      }\n    );\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\npage\n  width 750rpx\n  min-height 1300rpx\n  .container\n    font-family 'SimHei'\n    overflow hidden\n    width 100%\n    min-height 1300rpx\n    .head-image\n      width 100%\n      height 400rpx\n    .news-title\n      font-size 40rpx\n      color #353535\n      padding 0 55rpx\n      text-align center\n      font-weight bold\n      margin 20rpx 0 0 0\n      font-family PingFangSC-Medium\n    .news-date\n      font-family PingFangSC-Regular\n      margin 40rpx 0\n      font-size 24rpx\n      color #888\n      text-align center\n      .ads-tip\n        width 120rpx\n        height 40rpx\n        text-align center\n        line-height 40rpx\n        border 2rpx solid #47CFF5\n        border-radius 40rpx\n        color #47CFF5\n        margin-left 8rpx\n    .news-content\n      font-size 30rpx\n      color #353535\n      line-height 63rpx\n      padding 0 46rpx\n      height fit-content\n      .news\n        height 100vh\n</style>\n"
  },
  {
    "path": "src/others-page/pages/associationPages/association-detail.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <BaseContainer :navTitle=\"navTitle\">\n      <view slot=\"qy-content\">\n        <view class=\"header\" animation=\"{{animation2}}\">\n          <view class=\"header-container\">\n            <view class=\"association-avatar\">\n              <image animation=\"{{animation4}}\" src=\"{{associationAvatar}}\">\n            </view>\n            <view class=\"association-info\">\n              <view animation=\"{{animation5}}\" class=\"association-name\">{{associationInfo.fullName}}</view>\n              <!-- <view class=\"association-hot\" animation=\"{{animation3}}\">\n                <image class=\"heat-icon\" src=\"https://static.airbob.org/under-graduate/hot.png\">\n                <view class=\"heat-degree\">校谈热度{{associationInfo.heat}}>></view>\n              </view> -->\n            </view>\n          </view>\n        </view>\n        <view animation=\"{{animation1}}\" class=\"{{buttonStatus}}\" @tap=\"signUp\">\n          <view>立即报名</view>\n        </view>\n        <view class=\"body\">\n          <!--校谈中无话题-->\n          <!-- <view class=\"school-talk-title\" style=\"margin:34px 0 10px 23px\">校谈在聊</view>\n          <view class=\"school-talk\">\n            <view class=\"school-talk-card\">\n              <view class=\"card-body card-body-background\" wx:if=\"{{topicLength === 0}}\"></view>\n              <view class=\"card-body\" wx:if=\"{{topicLength < 2}}\">\n                <navigator\n                  open-type=\"navigate\"\n                  hover-class=\"none\"\n                  path=\"/pages/index&token={{schoolTalkToken}}\"\n                  target=\"miniProgram\"\n                  app-id=\"wxa16acae9f9d131fb\"\n                  class=\"card-content\"\n                  wx:if=\"{{topicLength === 0}}\"\n                >\n                  <view style=\"font-weight:700\">快去校谈发起第一篇话题吧</view>\n                  <view>南邮事，校谈说</view>\n                </navigator>\n                <navigator\n                  open-type=\"navigate\"\n                  hover-class=\"none\"\n                  path=\"/other-pages/topic?id={{topicArray[0].id}}&token={{schoolTalkToken}}\"\n                  target=\"miniProgram\"\n                  app-id=\"wxa16acae9f9d131fb\"\n                  class=\"card-content\"\n                  wx:if=\"{{topicLength === 1}}\"\n                >\n                  <view style=\"padding-bottom:4px;font-weight:700\">{{topicArray[0].name}}</view>\n                  <view>{{topicArray[0].visitors}}人查看>></view>\n                </navigator>\n              </view>\n              <navigator\n                open-type=\"navigate\"\n                hover-class=\"none\"\n                path=\"/other-pages/topic?id={{topicArray[0].id}}&token={{schoolTalkToken}}\"\n                target=\"miniProgram\"\n                app-id=\"wxa16acae9f9d131fb\"\n                class=\"card-body-two\"\n                style=\"z-index:1\"\n                wx:if=\"{{topicLength >= 2}}\"\n              >\n                <view class=\"card-content-two\">\n                  <view style=\"padding-bottom:4px;font-weight:700\">{{topicArray[0].name}}</view>\n                  <view>{{topicArray[0].visitors}}人查看>></view>\n                </view>\n              </navigator>\n              <navigator\n                open-type=\"navigate\"\n                hover-class=\"none\"\n                path=\"/other-pages/topic?id={{topicArray[1].id}}&token={{schoolTalkToken}}\"\n                target=\"miniProgram\"\n                app-id=\"wxa16acae9f9d131fb\"\n                class=\"card-body-two card-body-background-two\"\n                style=\"z-index:0\"\n                wx:if=\"{{topicLength >= 2}}\"\n              >\n                <view class=\"card-content-two\">\n                  <view style=\"padding-bottom:4px;font-weight:700\">{{topicArray[1].name}}</view>\n                  <view>{{topicArray[1].visitors}}人查看>></view>\n                </view>\n              </navigator>\n            </view>\n          </view> -->\n          <!-- <navigator\n            open-type=\"navigate\"\n            hover-class=\"none\"\n            path=\"/other-pages/tag?id={{tagId}}&token={{schoolTalkToken}}\"\n            target=\"miniProgram\"\n            app-id=\"wxa16acae9f9d131fb\"\n            class=\"card-footer\"\n          >\n            <view>{{cardFooter}}</view>\n          </navigator> -->\n          <!--校谈中更多的话题-->\n          <view class=\"school-talk-more\" wx:if=\"{{false}}\"></view>\n          <view class=\"school-talk-title\">社团印象</view>\n          <view class=\"association-impression\">\n            <!--没有图片-->\n            <view class=\"no-photo\" wx:if=\"{{!photoWallStatus}}\">\n              <image src=\"https://static.airbob.org/under-graduate/notfound.png\">\n            </view>\n            <!--图片scroll-->\n            <scroll-view scroll-x class=\"photo-wall\" wx:if=\"{{photoWallStatus}}\">\n              <image\n                wx:for=\"{{impressionPhotos}}\"\n                wx:key=\"index\"\n                class=\"scroll-img\"\n                src=\"{{item}}\"\n                index=\"index\"\n                data-idx=\"{{index}}\"\n                @tap=\"previewImpressionImage\"\n              >\n            </scroll-view>\n          </view>\n          <view class=\"school-talk-title\">社团简介</view>\n          <view class=\"association-intro\">\n            <view class=\"no-photo\" wx:if=\"{{!introductionStatus}}\">\n              <image src=\"https://static.airbob.org/under-graduate/notfound.png\">\n            </view>\n            <view\n              class=\"description\"\n              wx:if=\"{{introductionStatus}}\"\n              wx:for=\"{{introArray}}\"\n              index=\"index\"\n              item=\"item\"\n              wx:key=\"index\"\n            >\n              <view>{{item}}</view>\n            </view>\n          </view>\n        </view>\n      </view>\n    </BaseContainer>\n  </view>\n\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport { associationDetail, associationMembers } from \"@/api/recruit\";\nimport CryptoJS from \"crypto-js\";\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"社团招新\"\n  };\n  components = {\n    BaseContainer\n  };\n  data = {\n    navTitle: \"社团招新\",\n    associationAvatar: ``,\n    associationInfo: {},\n    impressionPhotos: [],\n    topicArray: [],\n    topicLength: 0,\n    distance: 0,\n    animation1: {},\n    animation2: {},\n    animation3: {},\n    animation4: {},\n    animation5: {},\n    fixStatus: false,\n    associationIntro: ``,\n    photoWallStatus: false,\n    introductionStatus: false,\n    introArray: [],\n    tagId: 0,\n    schoolTalkToken: \"\"\n  };\n  computed = {\n    cardFooter() {\n      return this.topicLength <= 2\n        ? \"打开校谈,无需下载\"\n        : `还有${this.topicLength - 2}篇帖子，打开校谈查看更多`;\n    },\n    buttonStatus() {\n      return this.fixStatus === true\n        ? `sign-up-button-fixed`\n        : `sign-up-button`;\n    }\n  };\n  methods = {\n    signUp() {\n      this.$parent.globalData.associationUserTableInfo = this.associationInfo;\n      wepy.navigateTo({\n        url: `./association-register?avatar=${encodeURIComponent(\n          this.associationAvatar\n        )}`\n      });\n    },\n    previewImpressionImage(e) {\n      const index = e.currentTarget.dataset.idx;\n      wepy.previewImage({\n        current: this.impressionPhotos[index],\n        urls: this.impressionPhotos\n      });\n    }\n  };\n  // schoolTalkTopic(requestData) {\n  //   this.commandData = requestData.assoInfo;\n  //   schoolTaklAssociation(requestData.assoInfo.tagId).then(res => {\n  //     if (res.statusCode === 200 || res.code === 200) {\n  //       const requestData = res.data.data;\n  //       this.topicArray = requestData.topics;\n  //       this.associationInfo.heat =\n  //         requestData.heat === null ? 0 : requestData.heat;\n  //       this.topicLength = requestData.topics_count;\n  //       this.$apply();\n  //     }\n  //   });\n  // }\n  getAssociationInfo(requestData) {\n    this.commandData = requestData.assoInfo;\n    let impressionPhotos = [];\n    requestData.assoInfoDetails\n      .filter(x => x.type === 2)\n      .forEach(item => {\n        impressionPhotos.push(item.picUrl);\n      });\n    this.impressionPhotos = impressionPhotos;\n    if (this.impressionPhotos.length !== 0) {\n      this.photoWallStatus = true;\n    } else {\n      this.photoWallStatus = false;\n    }\n    // 社团简介\n\n    const associationIntro = requestData.assoInfoDetails.find(\n      item => item.type === 0\n    );\n    this.associationIntro =\n      associationIntro !== undefined ? associationIntro.message : \"\";\n    this.introArray = this.associationIntro\n      .replace(/^\"|\"$/g, \"\")\n      .trim()\n      .split(\"\\n\");\n    if (this.associationIntro.length) {\n      this.introductionStatus = true;\n    } else {\n      this.introductionStatus = false;\n    }\n\n    // 社团头像\n    const associationAvatar = requestData.assoInfoDetails.find(\n      item => item.type === 1\n    );\n    this.associationAvatar =\n      associationAvatar !== undefined ? associationAvatar.picUrl : undefined;\n\n    this.$apply();\n  }\n  async onLoad(option) {\n    let { scene, associationName, koulingStatus, command, fullname } = option;\n    if (scene) {\n      const words = CryptoJS.enc.Base64.parse(decodeURIComponent(option.scene));\n      associationName = CryptoJS.enc.Utf8.stringify(words);\n    }\n    this.associationInfo = { associationName };\n\n    this.$apply();\n\n    if (Boolean(koulingStatus) === true) {\n      // 通过口令获取热度\n      wepy.showLoading({\n        title: \"加载社团详情中...\"\n      });\n\n      try {\n        const associationDetailResponse = await associationDetail(command);\n        if (associationDetailResponse.data) {\n          const requestData = associationDetailResponse.data.data;\n          this.associationInfo.fullName = fullname;\n          this.getAssociationInfo(requestData);\n        }\n      } finally {\n        this.$apply();\n        wepy.hideLoading();\n      }\n    } else {\n      // 普通的获取信息\n      wepy.showLoading({\n        title: \"加载社团详情中...\"\n      });\n\n      try {\n        const associationMembersResponse = await associationMembers(\n          this.associationInfo.associationName\n        );\n        if (\n          associationMembersResponse.data &&\n          associationMembersResponse.data.data\n        ) {\n          const {\n            assoInfo: {\n              associationName,\n              fullname,\n              genDate,\n              id,\n              modifiedDate,\n              tagId\n            },\n            assoInfoDetails\n          } = associationMembersResponse.data.data;\n          this.associationInfo.associationName = associationName;\n          this.associationInfo.fullName = fullname;\n          this.tagId = tagId;\n          const requestData = associationMembersResponse.data.data;\n          this.getAssociationInfo(requestData);\n          this.$apply();\n        }\n      } finally {\n        wepy.hideLoading();\n      }\n    }\n  }\n  onPageScroll(e) {\n    // this.distance = e.scrollTop;\n    // if (this.distance >= 0) {\n    //   if (this.distance <= 104) {\n    //     this.fixStatus = false;\n    //     // 报名按钮的动画\n    //     const animation1 = wepy.createAnimation({\n    //       duration: 0\n    //     });\n    //     this.animation1 = animation1\n    //       .scale(1 - this.distance * 0.0022)\n    //       .right(`${23 - this.distance * 0.2}px`)\n    //       .step()\n    //       .export();\n    //     // 卡片宽度的动画\n    //     const animation2 = wepy.createAnimation({\n    //       duration: 0\n    //     });\n    //     this.animation2 = animation2\n    //       .height(`${136 - this.distance * 0.7}px`)\n    //       .step()\n    //       .export();\n    //     // 热度消失的动画\n    //     const animation3 = wepy.createAnimation({\n    //       duration: 0\n    //     });\n    //     this.animation3 = animation3\n    //       .scale(1 - this.distance * 0.01)\n    //       .opacity(1 - this.distance * 0.01)\n    //       .step()\n    //       .export();\n    //     // 社团头像的动画\n    //     const animation4 = wepy.createAnimation({\n    //       duration: 0\n    //     });\n    //     this.animation4 = animation4\n    //       .width(`${50 - this.distance * 0.15}px`)\n    //       .height(`${49 - this.distance * 0.15}px`)\n    //       .left(`${31 - this.distance * 0.15}px`)\n    //       .top(`${42 - this.distance * 0.27}px`)\n    //       .step()\n    //       .export();\n    //     // 社团名称的动画\n    //     const animation5 = wepy.createAnimation({\n    //       duration: 0\n    //     });\n    //     this.animation5 = animation5\n    //       .top(`${46 - this.distance * 0.27}px`)\n    //       .left(`${95 - this.distance * 0.3}px`)\n    //       .step()\n    //       .export();\n    //     this.$apply();\n    //   } else {\n    //     this.fixStatus = true;\n    //     this.$apply();\n    //   }\n    // }\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\n.container\n  .header\n    width 100%\n    height 136px\n    background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%), linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, rgba(0, 0, 0, 0.5) 100%)\n    background-blend-mode normal, normal\n    position relative\n    top 0\n    z-index 10\n  .header-container\n    height 136px\n    display flex\n    align-items center\n    .association-avatar\n      margin-right 15px\n      image\n        position absolute\n        top 42px\n        width 50px\n        height 49px\n        border 3px solid rgb(255, 255, 255)\n        border-radius 50%\n        left 31px\n    .association-info\n      display flex\n      flex-direction column\n      .association-name\n        position absolute\n        top 55px\n        left 95px\n        width 202px\n        height 28px\n        font-size 20px\n        font-family 'PingFangSC-Semibold'\n        font-weight 700\n        color rgb(53, 53, 53)\n      .association-hot\n        padding-top 25px\n        padding-left 50px\n        display flex\n        align-items center\n        .heat-icon\n          width 9px\n          height 12px\n          padding-right 2px\n        .heat-degree\n          margin-left 1px\n          font-family 'PingFangSC-Regular'\n          font-size 12px\n          color rgb(192, 196, 204)\n.sign-up-button-fixed\n  width 141px\n  height 49px\n  background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%)\n  box-shadow 0px 0px 44px 0px rgba(168, 168, 168, 0.5)\n  position fixed\n  top 10px !important\n  right 23px\n  border-radius 14px\n  display flex\n  justify-content center\n  align-items center\n  z-index 11\n  view\n    text-align center\n    font-family 'PingFangSC-Semibold'\n    font-size 18px\n    font-weight 700\n    color rgb(255, 255, 255)\n.sign-up-button\n  width 141px\n  height 49px\n  background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%)\n  box-shadow 0px 0px 44px 0px rgba(168, 168, 168, 0.5)\n  position relative\n  top -20px\n  float right\n  right 23px\n  border-radius 14px\n  display flex\n  justify-content center\n  align-items center\n  z-index 11\n  view\n    text-align center\n    font-family 'PingFangSC-Semibold'\n    font-size 18px\n    font-weight 700\n    color rgb(255, 255, 255)\n.body\n  margin-top 30px\n  .no-photo\n    width 329px\n    height 100px\n    display flex\n    flex-direction column\n    justify-content center\n    align-items center\n    background rgb(248, 248, 248)\n    image\n      width 166px\n      height 69px\n  .school-talk-title\n    width 73px\n    height 25px\n    font-family 'PingFangSC-Semibold'\n    font-size 18px\n    margin-left 23px\n    font-weight 700\n    margin-bottom 10px\n    background linear-gradient(135deg, rgb(167, 243, 213), rgb(69, 211, 251))\n    -webkit-background-clip text\n    -webkit-text-fill-color transparent\n  .school-talk\n    width 100%\n    display flex\n    justify-content center\n    align-items center\n    flex-direction column\n    .school-talk-card\n      width 339px\n      height 117px\n      position relative\n      .card-body-background\n        height 105px\n        width 339px\n        top 0 !important\n        z-index -1\n      .card-body-background-two\n        height 67px !important\n        width 339px\n        top 0 !important\n        z-index -1\n      .card-body-two\n        width 100%\n        height 55px\n        position absolute\n        top 58px\n        background-image linear-gradient(135deg, rgba(167, 243, 213, 0.4) 0%, rgba(69, 211, 251, 0.4) 100%), linear-gradient(#ffffff, #ffffff)\n        background-blend-mode normal, normal\n        box-shadow 0 -2px 7px 0 rgba(168, 168, 168, 0.5)\n        border-radius 6px 6px 0 0\n        overflow hidden\n        .card-content-two\n          // width 100%\n          height 100%\n          padding 11px 19px 0 19px\n          view:nth-child(1)\n            height 21px\n            font-size 15px\n            font-family 'PingFangSC-Semibold'\n            width 100%\n            overflow hidden\n            color rgb(96, 98, 102)\n          view:nth-child(2)\n            height 17px\n            font-family 'PingFangSC-Regular'\n            font-size 12px\n            width 100%\n            overflow hidden\n            color rgb(192, 196, 204)\n      .card-body\n        width 100%\n        height 112px\n        position absolute\n        top 7px\n        background-image linear-gradient(135deg, rgba(167, 243, 213, 0.4) 0%, rgba(69, 211, 251, 0.4) 100%), linear-gradient(#ffffff, #ffffff)\n        background-blend-mode normal, normal\n        box-shadow 0 -2px 7px 0 rgba(168, 168, 168, 0.5)\n        border-radius 6px 6px 0 0\n        overflow hidden\n        .card-content\n          width 100%\n          height 100%\n          display flex\n          justify-content center\n          align-items center\n          flex-direction column\n          view:nth-child(1)\n            height 21px\n            font-size 15px\n            font-family 'PingFangSC-Semibold'\n            color rgb(96, 98, 102)\n          view:nth-child(2)\n            height 17px\n            font-family 'PingFangSC-Regular'\n            font-size 12px\n            color rgb(192, 196, 204)\n  .card-footer\n    width 100%\n    height 28px\n    justify-content center\n    align-items center\n    display flex\n    view\n      padding 7px\n      text-align center\n      font-size 12px\n      font-family 'PingFangSC-Regular'\n      color rgb(69, 212, 251)\n  .association-impression\n    width 100%\n    display flex\n    align-items center\n    flex-direction column\n    margin-bottom 20px\n    .photo-wall\n      width 329px\n      height 100px\n      display flex\n      flex-direction column\n      white-space nowrap\n      image\n        display inline-block\n        width 133px\n        height 100px\n        margin-right 9px\n  .association-intro\n    width 100%\n    display flex\n    flex-direction column\n    align-items center\n    padding-bottom 46rpx\n    .description\n      font-family PingFangSC-Regular\n      font-size 14px\n      font-weight normal\n      font-stretch normal\n      letter-spacing 0px\n      color #9b9b9b\n      padding 0 23px 23px 23px\n      word-wrap break-word\n      word-break break-all\n      text-indent 2em\n      text-align justify\n</style>\n\n"
  },
  {
    "path": "src/others-page/pages/associationPages/association-register.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"社团报名\">\n    <view slot=\"qy-content\" class=\"container\" style=\"{{perfectInfoStatus === false ? 'height:100vh;overflow:hidden;' : ''}}\">\n      <view class=\"perfect-info\" wx:if=\"{{perfectInfoStatus === false}}\">\n        <view class=\"perfect-info-body\">\n          <view class=\"perfect-img\">\n            <image src=\"https://static.airbob.org/under-graduate/tip.png\" />\n          </view>\n          <view class=\"perfect-info-card\">\n            <view class=\"perfect-info-tip\">请先完善个人基本信息再进行报名哦</view>\n            <view class=\"submission\" style=\"width: 202px;height:49px;margin-bottom:0\" @tap=\"navigateToPersonal\">\n              <view>完善基本信息</view>\n            </view>\n          </view>\n        </view>\n      </view>\n      <view class=\"header\">\n        <view class=\"header-container\">\n          <view class=\"association-avatar\">\n          <image src=\"{{associationAvatar}}\" />\n        </view>\n        <view class=\"association-info\">\n          <view class=\"association-name\">{{associationInfo.fullname}}</view>\n        </view>\n        </view>\n      </view>\n      <view class=\"body\">\n        <view class=\"info-container\">\n          <view class=\"body-slogan\">你想要加入什么部门？</view>\n          <view class=\"apartment-selection\">\n            <picker mode = \"selector\" value=\"{{apartFirstIndex}}\" range=\"{{apartmentFirst}}\" range-key=\"departmentName\" @change=\"firstSelection\">\n              <view class=\"picker-container\">\n                <view>\n                  <text class=\"picker-content\">{{firstPicker}}</text>\n                </view>\n                <view class=\"picker-img\">\n                  <image src=\"{{firstArrow}}\" />\n                </view>\n              </view>\n            </picker>\n            <picker mode = \"selector\" value=\"{{apartSecondIndex}}\" range=\"{{apartmentSecond}}\" range-key=\"departmentName\" @change=\"secondSelection\">\n              <view class=\"picker-container\">\n                <view>\n                  <text class=\"picker-content\">{{secondPicker}}</text>\n                </view>\n                <view class=\"picker-img\">\n                  <image src=\"{{secondArrow}}\" />\n                </view>\n              </view>\n            </picker>\n          </view>\n          <view class=\"body-slogan\">让我们更深入地了解你：</view>\n          <view class=\"question-container\">\n            <view class=\"question\" wx:for=\"{{registerInfo}}\" wx:key=\"index\">\n              <view class=\"question-title\">{{index+1}}. {{item.question}}</view>\n              <view class=\"question-input\">\n                <view wx:if=\"{{perfectInfoStatus}}\">\n                  <textarea placeholder=\"请输入内容\" maxlength=\"5000\" data-idx=\"{{index}}\" bindinput=\"quesInput\" value=\"{{item.answer}}\" />\n                </view>\n                <view class=\"instead\" wx:else>\n                  {{item.answer}}\n                </view>\n              </view>\n            </view>\n          </view>\n        </view>\n        <view class=\"submission\" @tap=\"{{modifyStatus === true ? 'registerAssociation' : 'modifyAssociation'}}\">\n          <view>{{modifyOrSubmit}}</view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport {\n  associationAccept,\n  changeAssociationAccept,\n  getAssociationAccept,\n  associationUsers\n} from \"@/api/recruit\";\nimport BaseContainer from \"@/components/baseContainer\";\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"社团报名\"\n  };\n  components = {\n    BaseContainer\n  };\n  data = {\n    associationAvatar: ``,\n    apartmentFirst: [],\n    apartmentSecond: [],\n    apartFirstIndex: 0,\n    apartFirstStatus: false,\n    apartSecondIndex: 0,\n    apartSecondStatus: false,\n    registerInfo: [\n      {\n        question: ``,\n        answer: ``\n      },\n      {\n        question: ``,\n        answer: ``\n      },\n      {\n        question: ``,\n        answer: ``\n      }\n    ],\n    // 是否完善信息\n    associationInfo: {},\n    firstApartment: ``,\n    firstApartmentId: 0,\n    secondApartment: ``,\n    secondApartmentId: 0,\n    answerPostData: [``, ``, ``],\n    // 标记是不是从个人中心页面跳转过来\n    clubPersonalStatus: false,\n    modifyStatus: false,\n    formId: 0,\n    // 之前的申请表数据 => 检测\n    originData: [],\n    // 留到注册成功的页面用\n    tagId: 0\n  };\n  computed = {\n    perfectInfoStatus() {\n      return !wepy.getStorageSync(\"associationInfo\")\n        ? false\n        : Object.entries(wepy.getStorageSync(\"associationInfo\")).filter(\n            item => item[1] === \"\"\n          ).length === 0;\n    },\n    firstPicker() {\n      if (this.clubPersonalStatus) {\n        return this.firstApartment;\n      } else {\n        return this.apartFirstStatus\n          ? this.apartmentFirst[this.apartFirstIndex].departmentName\n          : `选择第一部门志愿`;\n      }\n    },\n    secondPicker() {\n      if (this.clubPersonalStatus) {\n        return this.secondApartment;\n      } else {\n        return this.apartSecondStatus\n          ? this.apartmentSecond[this.apartSecondIndex].departmentName\n          : `选择第二部门志愿`;\n      }\n    },\n    firstArrow() {\n      return \"\";\n      // return this.apartFirstStatus\n      //   ? `https://static.airbob.org/under-graduate/up.png`\n      //   : `https://static.airbob.org/under-graduate/down.png`;\n    },\n    secondArrow() {\n      return \"\";\n      // return this.apartSecondStatus\n      //   ? `https://static.airbob.org/under-graduate/up.png`\n      //   : `https://static.airbob.org/under-graduate/down.png`;\n    },\n    modifyOrSubmit() {\n      return this.modifyStatus === true ? `提交报名表` : `修改`;\n    }\n  };\n  methods = {\n    firstSelection(e) {\n      this.apartFirstIndex = e.detail.value;\n      this.apartFirstStatus = true;\n      if (this.apartFirstStatus) {\n        this.firstApartment = this.apartmentFirst[\n          this.apartFirstIndex\n        ].departmentName;\n        this.firstApartmentId = this.apartmentFirst[this.apartFirstIndex].id;\n      }\n    },\n    secondSelection(e) {\n      this.apartSecondIndex = e.detail.value;\n      this.apartSecondStatus = true;\n      if (this.apartSecondStatus) {\n        this.secondApartment = this.apartmentSecond[\n          this.apartSecondIndex\n        ].departmentName;\n        this.secondApartmentId = this.apartmentSecond[this.apartSecondIndex].id;\n      }\n    },\n    quesInput(e) {\n      const index = e.currentTarget.dataset.idx;\n      this.answerPostData[index] = e.detail.value;\n      // if()\n    },\n    navigateToPersonal() {\n      wepy.navigateTo({\n        url: `./club-personal?showPage=1`\n      });\n    },\n    registerAssociation() {\n      // if (this.firstApartmentId === this.secondApartmentId) {\n      //   wepy.showModal({\n      //     content: \"两个志愿的部门不能相同哦~\",\n      //     confirmText: \"知道了\",\n      //     showCancel: false,\n      //     confirmColor: \"#47CFF5\"\n      //   });\n      // } else\n      if (this.apartFirstStatus === false || this.apartSecondStatus === false) {\n        wepy.showModal({\n          content: \"要填两个部门哦~\",\n          confirmText: \"知道了\",\n          showCancel: false,\n          confirmColor: \"#47CFF5\"\n        });\n      } else {\n        if (this.answerPostData.some(x => x === null || x === \"\")) {\n          wepy.showModal({\n            content: \"问题回答不能为空~\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#47CFF5\"\n          });\n        } else {\n          associationAccept(\n            wepy.getStorageSync(\"userInfo\").studentId ||\n              wepy.getStorageSync(\"User\").studentId,\n            this.associationInfo.fullname,\n            Number(this.firstApartmentId),\n            Number(this.secondApartmentId),\n            this.answerPostData[0],\n            this.answerPostData[1],\n            this.answerPostData[2]\n          ).then(res => {\n            if (res.data) {\n              wepy.navigateTo({\n                url: `./register-success?modify=false&tagId=${this.tagId}`\n              });\n            } else {\n              wepy.showModal({\n                content: \"回答中不能有emoji表情🙄\",\n                confirmText: \"知道了\",\n                showCancel: false,\n                confirmColor: \"#47CFF5\"\n              });\n            }\n          });\n        }\n      }\n    },\n    modifyAssociation() {\n      if (\n        this.firstApartmentId !== this.originData[0] ||\n        this.secondApartmentId !== this.originData[1] ||\n        this.answerPostData[0] !== this.originData[2] ||\n        this.answerPostData[1] !== this.originData[3] ||\n        this.answerPostData[2] !== this.originData[4]\n      ) {\n        // if (this.firstApartmentId === this.secondApartmentId) {\n        //   wepy.showModal({\n        //     content: \"两个志愿的部门不能相同哦~\",\n        //     confirmText: \"知道了\",\n        //     showCancel: false,\n        //     confirmColor: \"#47CFF5\"\n        //   });\n        // } else\n        if (this.answerPostData.some(x => x === null || x === \"\")) {\n          wepy.showModal({\n            content: \"问题回答不能为空~\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#47CFF5\"\n          });\n        } else {\n          changeAssociationAccept(\n            this.formId,\n            wepy.getStorageSync(\"userInfo\").studentId ||\n              wepy.getStorageSync(\"User\").studentId,\n            this.associationInfo.fullname,\n            this.firstApartmentId,\n            this.secondApartmentId,\n            this.answerPostData[0],\n            this.answerPostData[1],\n            this.answerPostData[2]\n          ).then(res => {\n            if (res.data.errCode === null) {\n              wepy.navigateTo({\n                url: `./register-success?modify=true&tagId=${this.tagId}`\n              });\n            } else {\n              if (res.data.errCode === 54) {\n                wepy.showModal({\n                  content: \"未做修改\",\n                  confirmText: \"知道了\",\n                  showCancel: false,\n                  confirmColor: \"#47CFF5\"\n                });\n              }\n            }\n          });\n        }\n      } else {\n        wepy.showModal({\n          content: \"未做修改\",\n          confirmText: \"知道了\",\n          showCancel: false,\n          confirmColor: \"#47CFF5\"\n        });\n      }\n    }\n  };\n  async onLoad(option) {\n    let associationStatus = this.$parent.globalData.associationStatus.data;\n    const associationInfo = this.$parent.globalData.associationUserTableInfo;\n    this.associationInfo = associationInfo;\n    if (associationInfo.associationName !== undefined) {\n      this.associationInfo.fullname =\n        associationInfo.fullName || associationInfo.fullname;\n    }\n    this.associationAvatar = decodeURIComponent(option.avatar);\n    if (option.clubPersonalStatus) {\n      this.associationInfo.associationName = associationInfo.associationName;\n      this.apartFirstStatus = true;\n      this.apartSecondStatus = true;\n      this.apartmentFirst = associationInfo.departmentModelList;\n      this.apartmentSecond = associationInfo.departmentModelList;\n      this.associationAvatar = associationInfo.logo;\n      this.$apply();\n    }\n    if (associationStatus && associationStatus.success) {\n      const filterAssociationStatus = associationStatus.data.filter(\n        item => item.associationName === associationInfo.fullname\n      )[0];\n      if (filterAssociationStatus !== undefined) {\n        if (filterAssociationStatus.status !== 0) {\n          if (filterAssociationStatus.status === -1) {\n            // 第一志愿已拒绝\n            wepy\n              .showModal({\n                content: `报名信息已经开始处理，无法修改`,\n                confirmText: \"知道了\",\n                showCancel: false,\n                confirmColor: \"#47CFF5\"\n              })\n              .then(res => {\n                if (res.confirm) {\n                  wepy.navigateBack();\n                }\n              });\n          } else if (filterAssociationStatus.status > 0) {\n            wepy\n              .showModal({\n                content: `报名信息已经处理完毕，无法修改！`,\n                confirmText: \"知道了\",\n                showCancel: false,\n                confirmColor: \"#47CFF5\"\n              })\n              .then(res => {\n                if (res.confirm) {\n                  wepy.navigateBack();\n                }\n              });\n          } else if (filterAssociationStatus.status === -2) {\n            // 全部拒绝 || 第二志愿录取\n            wepy\n              .showModal({\n                content: `报名表已经处理完毕，无法修改`,\n                confirmText: \"知道了\",\n                showCancel: false,\n                confirmColor: \"#47CFF5\"\n              })\n              .then(res => {\n                if (res.confirm) {\n                  wepy.navigateBack();\n                }\n              });\n          }\n        }\n      }\n    }\n    wepy.showLoading({\n      title: \"加载报名信息中...\"\n    });\n    try {\n      if (!this.perfectInfoStatus) {\n        const {\n          data: { data: associationUserInfo }\n        } = await associationUsers(\n          wepy.getStorageSync(\"userInfo\").studentId ||\n            wepy.getStorageSync(\"User\").studentId\n        );\n        if (associationUserInfo.birthday === \"0000-00-00\") {\n          this.perfectInfoStatus = false;\n        } else {\n          wepy.setStorageSync(\"associationInfo\", associationUserInfo);\n          this.perfectInfoStatus = true;\n        }\n      }\n      const res = await getAssociationAccept(\n        wepy.getStorageSync(\"userInfo\").studentId ||\n          wepy.getStorageSync(\"User\").studentId,\n        this.associationInfo.associationName\n      );\n      if (res.data.errCode === 55) {\n        wepy\n          .showModal({\n            content: `该社团没有录入信息,暂时无法报名`,\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#47CFF5\"\n          })\n          .then(res => {\n            if (res.confirm) {\n              wepy.navigateBack();\n            }\n          });\n      }\n      const requestData = res.data.data;\n      // 获取校谈热度\n      this.tagId = requestData.tagId;\n      this.formId = requestData.applicationFormId;\n      let selectArr = [];\n      requestData.zxdepartmentModelSelected.forEach((item, index) => {\n        if (item.departmentName === requestData.first) {\n          selectArr[0] = index;\n        }\n        if (item.departmentName === requestData.second) {\n          selectArr[1] = index;\n        }\n      });\n      // 判断是修改申请表还是提交申请表\n      if (\n        requestData.answer1 === null ||\n        requestData.answer2 === null ||\n        requestData.answer3 === null\n      ) {\n        this.apartFirstStatus = false;\n        this.apartSecondStatus = false;\n        this.modifyStatus = true;\n      } else {\n        this.apartFirstIndex = selectArr[0];\n        this.apartSecondIndex =\n          selectArr[1] !== undefined ? selectArr[1] : this.apartFirstIndex;\n        this.firstApartmentId =\n          requestData.zxdepartmentModelSelected[this.apartFirstIndex].id;\n        this.secondApartmentId =\n          requestData.zxdepartmentModelSelected[this.apartSecondIndex].id;\n        this.apartFirstStatus = true;\n        this.apartSecondStatus = true;\n        this.modifyStatus = false;\n      }\n      for (let i = 1; i <= 3; i++) {\n        this.registerInfo[i - 1].question = requestData[`quest${i}`];\n        this.registerInfo[i - 1].answer = requestData[`answer${i}`];\n        this.answerPostData[i - 1] = requestData[`answer${i}`];\n      }\n      this.apartmentFirst = requestData.zxdepartmentModelSelected;\n      this.apartmentSecond = requestData.zxdepartmentModelSelected;\n      this.originData = [\n        this.apartmentFirst.length !== 0\n          ? this.apartmentFirst[this.apartFirstIndex].id\n          : -1,\n        this.apartmentSecond.length !== 0\n          ? this.apartmentSecond[this.apartSecondIndex].id\n          : -1,\n        this.answerPostData[0],\n        this.answerPostData[1],\n        this.answerPostData[2]\n      ];\n      this.$apply();\n    } finally {\n      wepy.hideLoading();\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.instead\n  width 572rpx\n  height 162rpx\n  padding 28rpx\n  font-family 'PingFangSC-Regular'\n  font-size 28rpx\n  line-height 28rpx\n  color #909399\n.container-hidden\n  width 100%\n  height 100vh\n  overflow hidden\n.container\n  width 100%\n  .submission\n    width 350px\n    height 49px\n    background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%)\n    box-shadow 0px 0px 25px 0px rgba(168, 168, 168, 0.5)\n    border-radius 14px\n    display flex\n    justify-content center\n    align-items center\n    margin-bottom 55px\n    view\n      font-family 'PingFangSC-Semibold'\n      font-size 18px\n      color #ffffff\n  .perfect-info\n    position relative\n    z-index 999\n    width 100%\n    height 100%\n    background rgba(0, 0, 0, 0.5)\n    display flex\n    justify-content center\n    .perfect-info-body\n      margin-top 118px\n      height 300px\n      .perfect-img\n        display flex\n        justify-content center\n        margin-bottom -18px\n        image\n          width 158px\n          height 140px\n      .perfect-info-card\n        width 250px\n        height 188px\n        background #ffffff\n        border-radius 9px\n        display flex\n        align-items center\n        flex-direction column\n        .perfect-info-tip\n          font-size 14px\n          color #606266\n          font-family 'PingFangSC-Regular'\n          width 158px\n          height 40px\n          text-align center\n          padding 43px 0 34px 0\n  .header\n    width 100%\n    height 136px\n    background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%), linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, rgba(0, 0, 0, 0.5) 100%)\n    background-blend-mode normal, normal\n    position relative\n    top 0\n    z-index -1\n    .header-container\n      width 100%\n      height 136px\n      margin-left 31px\n      display flex\n      align-items center\n      .association-avatar\n        margin-right 15px\n        image\n          width 50px\n          height 49px\n          border 3px solid rgb(255, 255, 255)\n          border-radius 50%\n      .association-info\n        display flex\n        flex-direction column\n        .association-name\n          width 202px\n          height 28px\n          font-size 20px\n          font-family 'PingFangSC-Semibold'\n          font-weight 700\n          color rgb(53, 53, 53)\n        .association-hot\n          display flex\n          align-items center\n          .heat-icon\n            width 9px\n            height 12px\n            padding-right 2px\n          .heat-degree\n            margin-left 1px\n            font-family 'PingFangSC-Regular'\n            font-size 12px\n            color rgb(192, 196, 204)\n  .body\n    display flex\n    justify-content center\n    flex-direction column\n    align-items center\n    .info-container\n      width 350px\n      background-color #ffffff\n      box-shadow 0px 0px 12px 0px rgba(168, 168, 168, 0.5)\n      border-radius 14px\n      margin-top 30px\n      // height 661px\n      margin-bottom 15px\n      .body-slogan\n        margin 21px 0 10px 19px\n        height 22px\n        font-family 'PingFangSC-Semibold'\n        font-size 16px\n        font-weight 700\n        color #353535\n        font-weight normal\n        font-stretch normal\n        letter-spacing 0px\n      .apartment-selection\n        display flex\n        justify-content center\n        align-items center\n        flex-direction column\n        height 90px\n        picker:first-child\n          margin-bottom 10px\n        picker\n          width 312px\n          height 40px\n          background-color #ffffff\n          border-radius 4px\n          border solid 1px #d7dce5\n          .picker-container\n            width 312px\n            height 40px\n            display flex\n            align-items center\n            justify-content space-between\n            .picker-content\n              padding-left 15px\n              font-family 'PingFangSC-Regular'\n              font-size 14px\n              color #909399\n              line-height 14px\n              width 112px\n              height 14px\n            .picker-img\n              margin-right 18rpx\n              image\n                width 16rpx\n                height 12rpx\n      .question-container\n        width 100%\n        .question\n          width 100%\n          margin-bottom 10px\n          .question-title\n            margin 0 19px 10px 19px\n            font-family 'PingFangSC-Medium'\n            font-size 14px\n            color rgb(155, 155, 155)\n          .question-input\n            display flex\n            justify-content center\n            view\n              width 312px\n              height 109px\n              border-radius 4px\n              border solid 1px #dcdfe5\n              textarea\n                width 286px\n                height 81px\n                padding 14px\n                font-family 'PingFangSC-Regular'\n                font-size 14px\n                line-height 14px\n                color #909399\n</style>\n"
  },
  {
    "path": "src/others-page/pages/associationPages/association.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\" :background.sync=\"backgroundStatus\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"container-bg\"></view>\n        <view class=\"{{headerStatus}}\">\n          <image @tap=\"scanQrcode\" class=\"scan\" src=\"https://static.airbob.org/under-graduate/scan.png\">\n          <image\n            style=\"{{changeAnimation}}\"\n            class=\"emoji\"\n            src=\"https://static.airbob.org/under-graduate/emoji.png\"\n          >\n          <image\n            style=\"{{changeAnimation}}\"\n            class=\"header-title\"\n            src=\"https://static.airbob.org/under-graduate/title.png\"\n          >\n          <view\n            style=\"{{changeAnimation}}\"\n            class=\"header-slogan\"\n          >目前全校有{{associationList.length}}个社团和学生组织入驻小程序，加入他们，和有意思的人，一起做有意义的事。</view>\n        </view>\n        <view class=\"info\">\n          <view class=\"avatar-bubble-container\" wx:if=\"{{bubbleDisplayStatus}}\">\n            <view\n              class=\"avatar-bubble\"\n              @tap=\"toPersonalPage\"\n              style=\"background-image:url({{bubbleColor}})\"\n            >\n              <text>{{bubbleText}}</text>\n            </view>\n          </view>\n          <view\n            class=\"avatar-container\"\n            @tap=\"toPersonalPage\"\n          >\n            <!-- <image\n              style=\"{{displaceAnimation}}\"\n              @tap=\"toPersonalPage\"\n              class=\"{{avatarStatus}}\"\n              src=\"{{userAvatar}}\"\n            > -->\n                <open-data type=\"userAvatarUrl\"/>\n          </view>\n          <view>\n            <view\n              style=\"{{leftAnimation}}\"\n              class=\"{{fixStatus === true ? 'user-name-fixed' : 'user-name'}}\"\n              @tap=\"toPersonalPage\"\n            >\n              {{name}}\n            </view>\n            <view\n              style=\"{{numAnimation}}\"\n              class=\"register-sum\"\n              @tap=\"toPersonalPage\"\n            >已报名{{registrationNum}}个社团，点击查看</view>\n          </view>\n        </view>\n        <view class=\"list\" style=\"{{fixStatus === true ? 'position:absolute;top:90rpx' : ''}}\">\n          <view class=\"list-container\">\n            <view class=\"list-slogan\">\n              挑选想要加入\n              或了解的社团吧\n            </view>\n            <view class=\"list-body\">\n              <view class=\"association-info\" wx:for=\"{{associationList}}\" wx:key=\"index\">\n                <view\n                  class=\"association-info-name\"\n                  data-id=\"{{index}}\"\n                  @tap=\"getAssociationDetail\"\n                >\n                  <text class=\"association-info-name-text\">{{item.fullname}}</text>\n                  <image class=\"association-info-name-image\" src=\"https://static.airbob.org/association-arrow/QjE2MDEyMzI3LeWbvuaghy5wbmc=\">\n                 </view>\n              </view>\n            </view>\n          </view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n<script>\nimport wepy from \"wepy\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport JudgeStatus from \"@/mixins/module\";\nimport {\n  associationUsers,\n  associationList,\n  associationStatus\n} from \"@/api/recruit\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"社团招新\",\n    navigationBarBackgroundColor: \"#45D3FB\"\n  };\n  mixins = [JudgeStatus];\n  components = {\n    BaseContainer\n  };\n  data = {\n    navTitle: \"社团招新\",\n    background: \"#45D3FB\",\n    associationSum: 0,\n    name: \"\",\n    registrationNum: 0,\n    associationList: [],\n    sid: \"\",\n    // 弹窗社团的口令,头像,名称\n    command: {},\n    // 社团口令数组\n    commands: [],\n    commandData: {},\n\n    // 动画\n    scrollAnimation: {},\n    talkAnimation: {},\n    distance: 0,\n    talkColorIndex: 0,\n    fixStatus: false,\n    userAvatar: \"\",\n    schoolTalkToken: ``,\n    // 是否完善信息\n    userInfoCompleted: false,\n    xh: \"\",\n    bubbleDisplayStatus: true,\n    visitorModeStatus: false,\n    backgroundStatus: \"transparent\"\n  };\n  methods = {\n    getAssociationDetail(e) {\n      const targetId = e.currentTarget.dataset.id;\n      const soloAssociation = this.associationList[targetId];\n      const {\n        associationName,\n        fullname,\n        genDate,\n        id,\n        modifiedDate,\n        tagId\n      } = soloAssociation;\n      wepy.navigateTo({\n        url: `./association-detail?associationName=${associationName}`\n      });\n    },\n    // 跳转到个人中心\n    toPersonalPage() {\n      wepy.navigateTo({\n        url: `./club-personal?showPage=${\n          this.userInfoCompleted === false ? 1 : 2\n        }`\n      });\n    },\n    // 扫描二维码\n    scanQrcode() {\n      wepy.scanCode().then(res => {\n        wepy.navigateTo({\n          url: \"../../../\" + res.path\n        });\n      });\n    }\n  };\n  computed = {\n    numAnimation() {\n      if (this.distance < 348) {\n        return `transform: scale(${1 - this.distance * 0.003});\n              opacity: ${1 - this.distance * 0.003};`;\n      }\n    },\n    leftAnimation() {\n      if (this.distance < 348 && 216 - this.distance * 0.3 >= 54) {\n        return `left: ${216 - this.distance * 0.3}rpx`;\n      }\n    },\n    displaceAnimation() {\n      if (this.distance < 348 && 118 - this.distance * 0.2 >= 54) {\n        return `left:${78 - this.distance * 0.15}rpx;\n                width:${118 - this.distance * 0.2}rpx;\n                height:${118 - this.distance * 0.2}rpx`;\n      }\n    },\n    changeAnimation() {\n      if (this.distance < 348 && 1 - this.distance * 0.002 >= 0) {\n        return `transform: scale(${1 - this.distance * 0.001});\n                opacity:${1 - this.distance * 0.001}`;\n      }\n    },\n    talkColorStatus() {\n      return this.distance < 250\n        ? \"color:rgb(34,209,224)\"\n        : `color:rgb(255,255,255)`;\n    },\n    avatarStatus() {\n      return this.fixStatus === true ? `avatar-fixed` : `avatar`;\n    },\n    userNameStatus() {\n      return this.fixStatus === true ? `user-name-fixed` : `user-name`;\n    },\n    toSchoolStatus() {\n      return this.fixStatus === true\n        ? `to-school-talk-fixed`\n        : `to-school-talk`;\n    },\n    headerStatus() {\n      return this.fixStatus === true ? `header-img-fixed` : `header-img`;\n    },\n    containerStatus() {\n      return this.fixStatus === true ? `container-fixed` : `container`;\n    },\n    listStatus() {\n      return this.fixStatus === true\n        ? \"position:fixed;top:45px;z-index:999;background:white;overflow:scroll;border-radius:14px;box-shadow 0 -6px 11px 0 rgba(218, 218, 218, 0.5)\"\n        : \"\";\n    },\n    userInfoCompleted() {\n      return !wepy.getStorageSync(\"associationInfo\")\n        ? false\n        : Object.entries(wepy.getStorageSync(\"associationInfo\")).filter(\n            item => item[1] === \"\"\n          ).length === 0;\n    },\n    bubbleText() {\n      return this.userInfoCompleted ? `查看个人信息` : `快去完善信息`;\n    },\n    bubbleColor() {\n      return this.userInfoCompleted\n        ? `https://static.airbob.org/under-graduate/green.png`\n        : `https://static.airbob.org/under-graduate/yellow.png`;\n    }\n  };\n  async onLoad(option) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    if (!this.visitorModeStatus) {\n      this.judgeStatus(option.name).then(async () => {\n        this.xh =\n          wepy.getStorageSync(\"userInfo\").studentId ||\n          wepy.getStorageSync(\"User\").studentId;\n\n        wepy.showLoading({\n          title: \"加载社团列表中...\"\n        });\n        const {\n          data: { data: assoicationListData }\n        } = await associationList();\n        this.associationList = assoicationListData;\n        const {\n          data: { data: associationUserInfo }\n        } = await associationUsers(this.xh);\n\n        wepy.setStorageSync(\"associationInfo\", associationUserInfo);\n        this.userAvatar = wepy.getStorageSync(\"User\").nativeInformation.avatar;\n        this.registrationNum = option.associationNum;\n        const userInfo = wepy.getStorageSync(\"userInfo\");\n        this.name = userInfo.name;\n        try {\n          const associationStatusReponse = await associationStatus();\n          this.$parent.globalData.associationStatus = associationStatusReponse;\n          if (associationStatusReponse.data) {\n            const requestData = associationStatusReponse.data.data;\n            this.registrationNum = requestData.length;\n            this.$apply();\n          }\n        } finally {\n          wepy.hideLoading();\n        }\n        this.$apply();\n      });\n    } else {\n      this.$redirect({\n        url: \"../../../others-page/pages/close\"\n      });\n    }\n  }\n  onPageScroll(e) {\n    const { scrollTop: distance } = e;\n    const boundary = 383;\n    const BACKGROUND_COLOR_1 = \"transparent\";\n    const BACKGROUND_COLOR_2 = \"#fff\";\n\n    if (distance > boundary && this.backgroundStatus === \"transparent\") {\n      this.backgroundStatus = \"#fff\";\n      this.$apply();\n    } else if (distance <= boundary && this.backgroundStatus === \"#fff\") {\n      this.backgroundStatus = \"transparent\";\n      this.$apply();\n    }\n\n    // this.distance = e.scrollTop;\n    // if (this.distance === 0) {\n    //   this.bubbleDisplayStatus = true;\n    //   this.$apply();\n    // }\n    // if (this.distance > 0) {\n    //   this.bubbleDisplayStatus = false;\n    //   this.$apply();\n    //   // 颜色改变\n    //   if (this.distance >= 348) {\n    //     this.fixStatus = true;\n    //   } else {\n    //     this.fixStatus = false;\n    //   }\n    //   this.$apply();\n    // }\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\n.container\n  .container-bg\n    height 448px\n    width 100%\n    background-image url('https://static.airbob.org/under-graduate/bg_wuwu.png')\n    background-size 100%\n    position absolute\n    z-index -1\n    top 0px\n  .perfect-info\n    position absolute\n    z-index 999\n    width 100%\n    height 100%\n    background rgba(0, 0, 0, 0.5)\n    display flex\n    justify-content center\n    .perfect-info-body\n      margin-top 111px\n      height 300px\n      .perfect-img\n        display flex\n        justify-content center\n        margin-bottom -18px\n        image\n          width 186px\n          height 152px\n      .perfect-info-card\n        width 250px\n        height 188px\n        background #ffffff\n        border-radius 9px\n        display flex\n        align-items center\n        flex-direction column\n        position relative\n        .command-avatar\n          position absolute\n          top -20px\n          view\n            background-image url('https://static.airbob.org/under-graduate/face.png')\n            background-size 100%\n            width 50px\n            height 49px\n            display flex\n            justify-content center\n            align-items center\n            .command-avatar-img\n              width 46px\n              height 45px\n              background-color #ffffff\n              border-radius 50%\n        .submission\n          width 202px\n          height 49px\n          margin-bottom 0\n          background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%)\n          box-shadow 0px 0px 25px 0px rgba(168, 168, 168, 0.5)\n          border-radius 14px\n          display flex\n          justify-content center\n          align-items center\n          view\n            font-family 'PingFangSC-Semibold'\n            font-size 18px\n            color #ffffff\n        .command-name\n          height 28px\n          font-family 'PingFangSC-Semibold'\n          font-size 20px\n          color #606266\n          padding-bottom 22px\n        .perfect-info-tip\n          font-size 14px\n          color #606266\n          font-family 'PingFangSC-Regular'\n          height 20px\n          text-align center\n          padding 43px 0 3px 0\n  .header-img-fixed\n    height 45px\n    width 100%\n    background-image url('https://static.airbob.org/under-graduate/bg_wuwu.png')\n    background-size 100%\n    position fixed\n    z-index 10\n    top 0px\n    overflow hidden\n  .header-img\n    height 448px\n    width 100%\n    background-image url('https://static.airbob.org/under-graduate/bg_wuwu.png')\n    background-size 100%\n    // position absolute\n    z-index 3\n    // top 0px\n  .scan\n    width 30px\n    height 28.5px\n    position absolute\n    top 93px\n    z-index 100\n    right 27px\n  .emoji\n    width 180px\n    height 330px\n    position absolute\n    right 10px\n    // bottom 104px\n    top 103px\n  .header-title\n    width 145px\n    height 80px\n    position absolute\n    left 31px\n    top 95px\n  .header-slogan\n    width 149px\n    height 65px\n    font-family PingFangSC-Regular\n    font-size 12px\n    color rgb(96, 98, 102)\n    position absolute\n    top 210px\n    left 36px\n    line-height align-self auto\n    text-align justify\n  .info\n    // margin-top 355px\n    margin-left 10px\n    display flex\n    z-index 80\n    position absolute\n    transform translateY(-180rpx)\n    // top 550px\n    .avatar-bubble-container\n      // position absolute\n      z-index 100\n      // left 63px\n      // top 380px\n      width 40px\n      .avatar-bubble\n        width 91px\n        height 31px\n        background-repeat no-repeat\n        background-size 100%\n        text-align center\n        transform translate(50px,-35px)\n        padding-top 6rpx\n        text\n          font-size 12px\n          font-family 'PingFangSC-Regular'\n          color #ffffff\n    .avatar-container\n      width 118rpx\n      height 118rpx\n      margin-right 20rpx\n      z-index 11\n      border-radius 50%\n      overflow hidden\n      .avatar\n        width 118rpx\n        height 118rpx\n        border-radius 50%\n        box-sizing border-box\n        border 6rpx solid rgb(255, 255, 255)\n        // position absolute\n        z-index 11\n      .avatar-fixed\n        width 118rpx\n        height 118rpx\n        border-radius 50%\n        box-sizing border-box\n        border 6rpx solid rgb(255, 255, 255)\n        position fixed\n        top 16rpx\n        z-index 11\n    .user-name\n      margin-top 4rpx\n      margin-bottom 10rpx\n      height 50rpx\n      font-family PingFangSC-Semibold\n      font-size 36rpx\n      font-weight 700\n      color rgb(53, 53, 53)\n      // position absolute\n      // left 216rpx\n      z-index 11\n    .user-name-fixed\n      font-weight 700\n      margin-top 4rpx\n      margin-bottom 10rpx\n      height 50rpx\n      font-family PingFangSC-Semibold\n      font-size 36rpx\n      color rgb(53, 53, 53)\n      position fixed\n      top 16rpx\n      left 216rpx\n      z-index 11\n    .userinfo-complete\n      display inline-block\n      width 124rpx\n      height 50rpx\n      line-height 50rpx\n      text-align center\n      border-radius 18rpx\n      background #f5a523\n      span\n        color #fff\n        font-size 24rpx\n    .userinfo-completed\n      background #7ed321\n    .register-sum\n      // position absolute\n      // top 459px\n      font-family PingFangSC-Regular\n      font-size 24rpx\n      color rgb(155, 155, 155)\n      z-index 11\n  .to-school-talk\n    position absolute\n    right 19px\n    top 428px\n    margin 0 19px 1px 0\n    width 144px\n    height 20px\n    font-family 'PingFangSC-Semibold'\n    font-size 14px\n    font-weight 700\n    float right\n  .to-school-talk-fixed\n    position fixed\n    top 24rpx !important\n    right 114rpx\n    margin 0 19px 1px 0\n    width 144px\n    height 20px\n    font-weight 700\n    font-family 'PingFangSC-Semibold'\n    font-size 14px\n    z-index 11 !important\n  .list\n    width 100%\n    border-radius 14px\n    box-shadow 0 -6px 11px 0 rgba(218, 218, 218, 0.5)\n    background-color rgb(255, 255, 255)\n    margin-top -27px\n    z-index -1\n    transform translateY(-70rpx)\n    .list-container\n      width 100%\n      height 100%\n      // position relative\n      .list-slogan\n        width 113px\n        height 44px\n        font-family 'PingFangSC-Semibold'\n        font-size 16px\n        background linear-gradient(to right, rgb(167, 243, 213), rgb(69, 211, 251))\n        -webkit-background-clip text\n        -webkit-text-fill-color transparent\n        padding 90rpx 0 8px 20px\n      .list-body\n        margin-left 21px\n        .association-info\n          width 90vw\n          height 67px\n          box-sizing border-box\n          border-top 1px solid rgba(218, 218, 218, 0.5)\n          position relative\n          display flex\n          // justify-content center\n          align-items center\n          .association-info-name\n            font-weight 700\n            // margin 10px 0 3px 6px\n            // height 25px\n            font-family 'PingFangSC-Semibold'\n            font-size 18px\n            color rgb(53, 53, 53)\n            display flex\n            width 88vw\n            align-items center\n            flex-wrap nowrap\n            .association-info-name-text\n              width 84vw\n            .association-info-name-image\n              display inline-block\n              width 25px\n              height 25px\n        .association-heat\n          margin-left 8px\n          display flex\n          align-items center\n          .heat-icon\n            width 9px\n            height 12px\n            padding-right 2px\n          .heat-degree\n            width 98px\n            height 17px\n            font-family 'PingFangSC-Regular'\n            font-size 12px\n            color rgb(192, 196, 204)\n          .hot-talk\n            font-family 'PingFangSC-Regular'\n            font-size 12px\n            color rgb(192, 196, 204)\n</style>\n"
  },
  {
    "path": "src/others-page/pages/associationPages/club-personal.wpy",
    "content": "<template>\n    <BaseContainer :navTitle=\"navTitle\" :background.sync=\"backgroundStatus\">\n        <view slot=\"qy-content\" class=\"container\">\n          <view class=\"container-top column\">\n              <image class=\"bg-index\" style=\"height:{{showPage==1?'calc(80vh + 20rpx)':'calc(35vh + 20rpx)'}};\" src=\"https://static.airbob.org/under-graduate/bg_index.png\" />\n              <view class=\"club-header row\">\n                  <view class=\"user-container row\" @tap=\"changePage\" data-page=\"1\">\n                      <view class=\"user-container-avatar\">\n                        <open-data type=\"userAvatarUrl\"/>\n                      </view>\n                      <!-- <image class=\"user-avatar\" mode=\"aspectFit\" src=\"{{avatar}}\" /> -->\n                      <view class=\"user-name\">{{ username }}</view>\n                      <view class=\"userinfo-complete {{userInfoCompleted?'userinfo-completed':''}}\"><span>{{userInfoCompleted?'已完善':'完善信息'}}</span></view>\n                  </view>\n                  <image @tap=\"scanQrcode\" class=\"scan-icon\" src=\"https://static.airbob.org/under-graduate/scan.png\" />\n              </view>\n              <view class=\"club-line\"></view>\n          </view>\n          <scroll-view class=\"club-scroll\" scroll-y=\"true\">\n              <view class=\"club-move\">\n                  <!-- <navigator open-type=\"navigate\" hover-class=\"none\" path=\"/pages/index?token={{schoolTalkToken}}\" target=\"miniProgram\" app-id=\"wxa16acae9f9d131fb\" class=\"xiaotan row\">\n                      <image class=\"xiaotan-logo\" mode=\"aspectFit\" src=\"https://static.airbob.org/under-graduate/xtlogo.png\" />\n                      <view class=\"xiaotan-text\">\n                          <span>南邮事,校谈说</span>\n                          <view>去校谈聊聊社团吧>></view>\n                      </view>\n                  </navigator> -->\n                  <view class=\"club-num\" @tap=\"changePage\" data-page=\"2\">\n                      <view class=\"number\"><span>{{ clubNum }}</span>个</view>\n                      <span>已报名社团</span>\n                  </view>\n              </view>\n              <view class=\"info-container\" wx:if=\"{{ showPage==1 }}\">\n                  <view class=\"questionnaire\">\n                      <view class=\"personal-info\">\n                          <view class=\"questionnaire-title\">个人信息</view>\n                          <view class=\"questionnaire-row row\">\n                              <input class=\"club-box user-name\" placeholder=\"{{username}}\" disabled=\"true\" />\n                              <picker class=\"club-box user-gender\" value=\"{{gIndex}}\" range=\"{{genderArr}}\" @change=\"setInformation\" data-type=\"gIndex\">\n                                <view class=\"picker-gender\">{{gIndex===null?\"性别\":genderArr[gIndex]}}</view>\n                                <view class=\"picker-arrow\"></view>\n                              </picker>\n                          </view>\n                          <view class=\"questionnaire-row row\">\n                              <picker class=\"club-box user-birth-year\" value=\"{{yIndex}}\" range=\"{{yearArr}}\" @change=\"setInformation\" data-type=\"yIndex\">\n                                  <view class=\"picker-year\">{{yIndex==null?\"生日\":yearArr[yIndex]}}</view>\n                                  <view class=\"picker-arrow\"></view>\n                              </picker>\n                              <picker class=\"club-box user-birth-month\" value=\"{{mIndex}}\" range=\"{{monthArr}}\" @change=\"setInformation\" data-type=\"mIndex\">\n                                  <view class=\"picker-month\">{{mIndex==null?\"月\":monthArr[mIndex]}}</view>\n                                  <view class=\"picker-arrow\"></view>\n                              </picker>\n                              <picker class=\"club-box user-birth-day\" value=\"{{dIndex}}\" range=\"{{dateArr}}\" @change=\"setInformation\" data-type=\"dIndex\">\n                                  <view class=\"picker-day\">{{dIndex==null?\"日\":dateArr[dIndex]}}</view>\n                                  <view class=\"picker-arrow\"></view>\n                              </picker>\n                          </view>\n                          <view class=\"questionnaire-row row\">\n                              <picker class=\"club-box user-college\" disabled=\"true\">\n                                  <view class=\"picker-college\">{{college}}</view>\n                                  <view class=\"picker-arrow\"></view>\n                              </picker>\n                              <picker class=\"club-box user-major\" disabled=\"true\">\n                                  <view class=\"picker-major\">{{major}}</view>\n                                  <view class=\"picker-arrow\"></view>\n                              </picker>\n                          </view>\n                          <input class=\"club-box user-highschool\" placeholder=\"中学学校\" value=\"{{highschool}}\" @input=\"setInformation\" data-type=\"highschool\"/>\n                          <input class=\"club-box user-dorm\" placeholder=\"宿舍(格式:xx-xxx-x)\" value=\"{{dorm}}\" @input=\"setInformation\" data-type=\"dorm\"/>\n                      </view>\n                      <view class=\"personal-contact\">\n                          <view class=\"questionnaire-title\">联系方式</view>\n                          <input class=\"club-box user-phonenumber\" placeholder=\"电话号码\" value=\"{{phonenumber}}\" @input=\"setInformation\" data-type=\"phonenumber\"/>\n                          <input class=\"club-box user-qq\" placeholder=\"QQ号\" value=\"{{qq}}\" @input=\"setInformation\" data-type=\"qq\"/>\n                          <input class=\"club-box user-email\" placeholder=\"邮箱\" value=\"{{email}}\" @input=\"setInformation\" data-type=\"email\"/>\n                      </view>\n                      <view class=\"club-des column\">\n                          <view>使用南邮小程序招新系统报名社团与线下填写</view>\n                          <view>纸质表具有相同报名效力。</view>\n                          <view>且线上报名更加方便、快捷、环保。</view>\n                      </view>\n                  </view>\n                <button class=\"save-btn\" @tap=\"submitInformation\"><span>保存</span></button>\n              </view>\n              <view class=\"club-container\" wx:if=\"{{ showPage==2 }}\">\n                  <view wx:if=\"{{ nojoin }}\">\n                      <view class=\"card-container\">\n                          <view class=\"club-card column\" style=\"align-items:center;\">\n                              <image class=\"nojoin-pic\" mode=\"aspectFit\" src=\"https://static.airbob.org/under-graduate/nojoin.png\" />\n                          </view>\n                          <view class=\"card-line\"></view>\n                      </view>\n                      <view class=\"card-container\">\n                          <view class=\"club-card column\"></view>\n                          <view class=\"card-line\"></view>\n                      </view>\n                  </view>\n                  <view wx:if=\"{{ !nojoin }}\">\n                      <repeat for=\"{{clubs}}\" index=\"index\" key=\"key\" item=\"item\">\n                          <view class=\"card-container\">\n                              <view class=\"club-card column\">\n                                  <view class=\"card-header row\">\n                                      <view class=\"card-info row\">\n                                          <image class=\"club-avatar\" mode=\"as1pectFit\" src=\"{{item.logo}}\" />\n                                          <view class=\"card-name column\">\n                                              <view class=\"club-name\">{{item.fullname}}</view>\n                                              <view class=\"card-key row\" @tap=\"copyKey\" data-code=\"{{item.kouling}}\" data-name=\"{{ item.associationName }}\">\n                                                  <span>招新口令</span>\n                                                  <view class=\"club-key\">{{item.kouling}}</view>\n                                                  <span>点击复制分享</span>\n                                              </view>\n                                          </view>\n                                      </view>\n                                      <view class=\"card-detail\">\n                                          <view class=\"club-date\">{{item.lastModifiedDate}}</view>\n                                          <view class=\"club-status\">{{ item.status }}</view>\n                                      </view>\n                                  </view>\n                                  <view class=\"card-choice row\">\n                                      <view class=\"club-first-choice column\">\n                                          <view style=\"font-weight:bold;\">{{item.departmentModelList[0].departmentName?item.departmentModelList[0].departmentName:'无'}}</view>\n                                          <span>第一志愿</span>\n                                      </view>\n                                      <view class=\"club-second-choice column\">\n                                          <view style=\"font-weight:bold;\">{{item.departmentModelList[1].departmentName?item.departmentModelList[1].departmentName:'无'}}</view>\n                                          <span>第二志愿</span>\n                                      </view>\n                                  </view>\n                                  <view class=\"card-footer row\">\n                                      <span @tap=\"toClubPage\" data-idx=\"{{index}}\">了解社团信息</span>\n                                      <span @tap=\"toFormPage\" data-idx=\"{{index}}\">查看报名表</span>\n                                  </view>\n                              </view>\n                              <view class=\"card-line\"></view>\n                          </view>\n                      </repeat>\n                      <view class=\"card-container\" @tap=\"toHomePage\">\n                          <view class=\"club-card row\" style=\"align-items:center;\">\n                              <span class=\"card-nomore\">没有更多了，去首页看看？</span>\n                          </view>\n                          <view class=\"card-line\"></view>\n                      </view>\n                  </view>\n              </view>\n              <view class=\"footer-container\" wx:if=\"{{ showPage==2 }}\">\n                  <view class=\"club-footer\">\n                      <view class=\"club-des column\">\n                          <view>使用南邮小程序招新系统报名社团与线下填写</view>\n                          <view>纸质表具有相同报名效力。</view>\n                          <view>且线上报名更加方便、快捷、环保。</view>\n                      </view>\n                      <view class=\"xiaotan-btn\" @tap.stop=\"toAssociationHome\"><span>去社团广场看看</span></view>\n                  </view>\n              </view>\n          </scroll-view>\n          <view class=\"club-toast  {{showToast?'club-toast-fadeInUp':''}}\">\n            <view>口令复制成功！快去QQ/微信中粘贴给同学</view>\n            <view>一起报名这个社团吧</view>\n          </view>\n      </view>\n    </BaseContainer>\n</template>\n<script>\nimport wepy from \"wepy\";\nimport { associationUpdate, getAssociationStatus } from \"@/api/recruit\";\nimport { educationSystemInformation } from \"@/api/education\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport pageJump from \"@/others-page/mixins/page-jump.js\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"社团报名\",\n    navigationBarBackgroundColor: \"#45d3fb\",\n    disableScroll: true\n  };\n  components = {\n    BaseContainer\n  };\n  data = {\n    navTitle: \"社团报名\",\n    background: \"#45d3fb\",\n    userInfoCompleted: false,\n    clubNum: 0,\n    showPage: 2,\n    nojoin: true,\n    username: \"\",\n    avatar: \"\",\n    college: \"\",\n    major: \"\",\n    xh: \"\",\n    genderArr: [\"男\", \"女\"],\n    yearArr: [],\n    monthArr: [],\n    dateArr: [],\n    gIndex: null,\n    yIndex: null,\n    mIndex: null,\n    dIndex: null,\n    highschool: \"\",\n    dorm: \"\",\n    phonenumber: \"\",\n    qq: \"\",\n    email: \"\",\n    clubs: [],\n    showToast: false,\n    schoolTalkToken: \"\",\n    backgroundStatus: \"transparent\"\n  };\n  computed = {\n    userInfoCompleted() {\n      return !wepy.getStorageSync(\"associationInfo\")\n        ? false\n        : Object.entries(wepy.getStorageSync(\"associationInfo\")).filter(\n            item => item[1] === \"\"\n          ).length === 0;\n    }\n  };\n  mixins = [pageJump];\n  methods = {\n    changePage(e) {\n      const { page } = e.currentTarget.dataset;\n      if (this.userInfoCompleted && 1 === Number(page) && this.showPage === 1) {\n        this.showPage = 2;\n      } else {\n        this.showPage = Number(page);\n      }\n    },\n    setInformation(e) {\n      let type = e.currentTarget.dataset.type;\n      this[type] = e.detail.value;\n      this.$apply();\n    },\n    // 扫描二维码\n    scanQrcode() {\n      wepy.scanCode().then(res => {\n        wepy.navigateTo({\n          url: \"../../../\" + res.path\n        });\n      });\n    },\n    async submitInformation() {\n      let that = this;\n      const data = {\n        name: that.username,\n        college: that.college,\n        major: that.major,\n        sex: Number(that.gIndex) === 0 ? 1 : 2,\n        xh: that.xh,\n        qq: that.qq,\n        mail: that.email,\n        phone: that.phonenumber,\n        birthday:\n          that.yearArr[that.yIndex] +\n          \"-\" +\n          that.monthArr[that.mIndex] +\n          \"-\" +\n          that.dateArr[that.dIndex],\n        gaozhong: that.highschool,\n        dorm: that.dorm\n      };\n      if (Object.entries(data).filter(item => item[1] === \"\").length !== 0) {\n        return wepy.showToast({\n          title: \"信息未填全\",\n          icon: \"none\",\n          duration: 1500\n        });\n      }\n      let response = await associationUpdate(data);\n      if (response.data.success) {\n        wepy.setStorageSync(\"associationInfo\", data);\n        wepy\n          .showToast({\n            title: \"保存成功\",\n            icon: \"none\",\n            duration: 1500\n          })\n          .then(() => {\n            this.showPage = 2;\n            this.$apply();\n          });\n      } else if (response.data.errCode === 53) {\n        wepy.showToast({\n          title: \"用户信息未更改\",\n          icon: \"none\",\n          duration: 1500\n        });\n        if (response.data.success) {\n          wepy.showToast({\n            title: \"保存成功\",\n            icon: \"none\",\n            duration: 1500\n          });\n        } else if (response.data.errCode === 53) {\n          wepy.showToast({\n            title: \"用户信息未更改\",\n            icon: \"none\",\n            duration: 1500\n          });\n        } else {\n          wepy.showToast({\n            title: \"保存失败，请重试\",\n            icon: \"none\",\n            duration: 1500\n          });\n        }\n      } else {\n        wepy.showToast({\n          title: \"信息填写不完整\",\n          icon: \"none\",\n          duration: 1500\n        });\n      }\n    },\n    toHomePage() {\n      wepy.navigateTo({\n        url: `./association?associationNum=${this.clubNum}`\n      });\n    },\n    toClubPage(e) {\n      const index = e.currentTarget.dataset.idx;\n      let postData = this.clubs[index];\n      postData.description = postData.associationName;\n      wepy.navigateTo({\n        url: `./association-detail?associationName=${postData.associationName}`\n      });\n    },\n    toFormPage(e) {\n      const index = e.currentTarget.dataset.idx;\n      let postData = this.clubs[index];\n      postData.description = postData.associationName;\n      this.$parent.globalData.associationUserTableInfo = postData;\n      wepy.navigateTo({\n        url: `./association-register?clubPersonalStatus=true`\n      });\n    },\n    async copyKey(e) {\n      let code = e.currentTarget.dataset.code;\n      let name = e.currentTarget.dataset.name;\n      let res = await wepy.setClipboardData({\n        data:\n          \"长按复制这段文字，打开👉南邮小程序👈立即加入【\" +\n          name +\n          \"】€\" +\n          code +\n          \"€\"\n      });\n      if (res.errMsg === \"setClipboardData:ok\") {\n        this.showToast = true;\n        this.$apply();\n        setTimeout(() => {\n          this.showToast = false;\n          this.$apply();\n        }, 5000);\n      }\n      this.$apply();\n    }\n  };\n  async getUserInfo() {\n    let that = this;\n    let response = wepy.getStorageSync(\"associationInfo\");\n    const userInfo = wepy.getStorageSync(\"userInfo\");\n    if (response) {\n      let birthday =\n        response.birthday !== \"0000-00-00\"\n          ? response.birthday.split(\"-\")\n          : `${userInfo.birthday.slice(0, 4)}-${userInfo.birthday.slice(\n              4,\n              6\n            )}-${userInfo.birthday.slice(6, 8)}`.split(\"-\");\n      that.username = response.name ? response.name : userInfo.name;\n      that.gIndex = response.sex\n        ? response.sex === 1\n          ? 0\n          : 1\n        : userInfo.gender === \"男\"\n        ? 0\n        : 1;\n      that.yIndex =\n        that.yearArr.indexOf(birthday[0]) === -1\n          ? null\n          : that.yearArr.indexOf(birthday[0]);\n      that.mIndex =\n        that.monthArr.indexOf(birthday[1]) === -1\n          ? null\n          : that.monthArr.indexOf(birthday[1]);\n      that.dIndex =\n        that.dateArr.indexOf(birthday[2]) === -1\n          ? null\n          : that.dateArr.indexOf(birthday[2]);\n      that.highschool = response.gaozhong;\n      that.dorm = response.dorm;\n      that.phonenumber = Number(response.phone) === 0 ? \"\" : response.phone;\n      that.qq = Number(response.qq) === 0 ? \"\" : response.qq;\n      that.email = response.mail;\n    } else {\n      that.username = userInfo.name;\n      that.gIndex = userInfo.gender === \"男\" ? 0 : 1;\n      that.yIndex = that.yearArr.indexOf(userInfo.birthday.slice(0, 4));\n      that.mIndex = that.monthArr.indexOf(userInfo.birthday.slice(4, 6));\n      that.dIndex = that.dateArr.indexOf(userInfo.birthday.slice(6, 8));\n    }\n    this.$apply();\n  }\n  async getClubInfo() {\n    let that = this;\n    let response = await getAssociationStatus(that.xh);\n    if (response.data.success) {\n      if (response.data.data.length) {\n        that.clubNum = response.data.data.length;\n        that.nojoin = false;\n        response.data.data.map(item => {\n          item.lastModifiedDate = item.lastModifiedDate\n            .slice(0, 10)\n            .replace(/-/g, \".\");\n          if (item.status <= 0 && item.status !== -2) {\n            item.status = \"审核中\";\n          } else if (item.status === -2) {\n            item.status = \"未通过\";\n          } else if (item.status > 0) {\n            for (let i = 0; i < item.departmentModelList.length; i++) {\n              if (item.status === item.departmentModelList[i].id) {\n                if (i === 0) {\n                  item.status = \"第一志愿通过\";\n                } else if (i === 1) {\n                  item.status = \"第二志愿通过\";\n                }\n              }\n            }\n          }\n          that.clubs.push(item);\n        });\n      } else {\n        that.nojoin = true;\n      }\n    } else {\n      await wepy.showToast({\n        title: \"获取社团信息失败,请重试\",\n        icon: \"none\",\n        duration: 1500\n      });\n    }\n    this.$apply();\n  }\n  async init() {\n    for (let i = 2018; i >= 1990; i--) {\n      this.yearArr.push(String(i));\n    }\n    for (let i = 1; i <= 12; i++) {\n      if (i < 10) {\n        this.monthArr.push(String(\"0\" + i));\n      } else {\n        this.monthArr.push(String(i));\n      }\n    }\n    for (let i = 1; i <= 31; i++) {\n      if (i < 10) {\n        this.dateArr.push(String(\"0\" + i));\n      } else {\n        this.dateArr.push(String(i));\n      }\n    }\n    try {\n      wepy.showLoading({ title: \"加载个人信息中\" });\n      await this.getUserInfo();\n      await this.getClubInfo();\n    } finally {\n      wepy.hideLoading();\n    }\n  }\n  async onLoad(options) {\n    this.schoolTalkToken = wepy.getStorageSync(\"token\");\n    let showPage = options.showPage;\n    if (showPage) {\n      this.showPage = showPage;\n    }\n    if (\n      wepy.getStorageSync(\"token\") &&\n      wepy.getStorageSync(\"User\").enabled\n      // wepy.getStorageSync(\"userInfo\")\n    ) {\n      const userInfoCache = wepy.getStorageSync(\"userInfo\");\n\n      if (!userInfoCache || !userInfoCache.studentId) {\n        await educationSystemInformation().then(res => {\n          if (res.data && res.data.data) {\n            wepy.setStorageSync(\"userInfo\", res.data.data);\n          }\n        });\n      }\n\n      this.college = wepy.getStorageSync(\"userInfo\").college;\n      this.major = wepy.getStorageSync(\"userInfo\").major;\n      this.avatar = wepy.getStorageSync(\"User\").nativeInformation.avatar;\n      this.xh =\n        wepy.getStorageSync(\"userInfo\").studentId ||\n        wepy.getStorageSync(\"User\").studentId;\n    } else {\n      wepy.reLaunch({\n        url: \"../../pages/login\"\n      });\n    }\n    this.init();\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n@import '../../../css/loading'\n\n.container\n  height 100%\n  min-height 100vh\n  font-family PingFangSC-Regular\n  margin-top 40px\n  .container-top\n    position absolute\n    top 0\n    right 0\n    left 0\n    background transparent\n    .bg-index\n      z-index -1\n      width 100%\n      position fixed\n      top -20rpx\n      left 0\n      right 0\n  .club-header\n    justify-content space-between\n    align-items center\n    margin-top 90px\n    .user-container\n      align-items center\n      height 100rpx\n      .user-container-avatar\n        overflow hidden\n        border-radius 50%\n        height 56rpx\n        margin-left 30rpx\n        width 56rpx\n      .user-avatar\n        height 56rpx\n        width 56rpx\n        border 4rpx solid #fff\n        border-radius 50%\n        margin-left 30rpx\n      .user-name\n        margin-right 4rpx\n        font-size 36rpx\n        font-weight 700\n        color #353535\n        margin 0 8rpx 0 18rpx\n      .userinfo-complete\n        display flex\n        flex-direction row\n        justify-content space-between\n        align-items center\n        justify-content center\n        width 124rpx\n        height 38rpx\n        border-radius 18rpx\n        background #f5a523\n        span\n          color #fff\n          font-size 24rpx\n      .userinfo-completed\n        background #7ed321\n    .scan-icon\n      height 28.5px\n      width 30px\n      margin-right 30rpx\n      z-index 10000\n  .club-line\n    margin 0 auto\n    height 2rpx\n    width calc(100vw - 60rpx)\n    background rgba(218, 218, 218, 0.5)\n  .club-move\n    padding 0 30rpx\n    height 150rpx\n    display flex\n    align-items center\n    justify-content space-between\n    position relative\n    flex-direction row-reverse\n    .xiaotan\n      align-items center\n      .xiaotan-logo\n        height 54rpx\n        width 90rpx\n        margin-right 10rpx\n      .xiaotan-text\n        view\n          color #fff\n          font-size 22rpx\n          font-family PingFangSC-Regular\n        span\n          color #606266\n          font-size 30rpx\n    .club-num\n      color #606266\n      font-size 22rpx\n      line-height 34rpx\n      .number\n        text-align right\n        color #353535\n        span\n          font-size 52rpx\n  .info-container\n    padding 0 30rpx 10rpx 30rpx\n    height 1600rpx\n    .questionnaire\n      background #fff\n      box-shadow 0rpx 0rpx 24rpx 0rpx rgba(168, 168, 168, 0.5)\n      border-radius 40rpx\n      .personal-info\n        padding 40rpx 50rpx\n      .personal-contact\n        padding 0 50rpx 40rpx 50rpx\n        border-bottom solid 2rpx rgba(218, 218, 218, 0.8)\n      .club-des\n        padding 40rpx\n  .club-container\n    .card-container\n      overflow hidden\n      padding 0 30rpx\n      .club-card\n        padding 30rpx\n        height 300rpx\n        border-radius 28rpx\n        background #fff\n        box-shadow 0rpx 0rpx 24rpx 0rpx rgba(168, 168, 168, 0.5)\n        justify-content space-around\n        position relative\n        .card-header\n          justify-content space-between\n          .card-info\n            .club-avatar\n              height 64rpx\n              width 64rpx\n              border solid 4rpx #e7e7e7\n              border-radius 50%\n              margin-right 20rpx\n            .card-name\n              .club-name\n                font-weight bold\n                font-size 32rpx\n                color #45d4fb\n              .card-key\n                span, view\n                  font-family PingFangSC-Regular\n                  font-size 22rpx\n                  color #9b9b9b\n                .club-key\n                  margin 0 10rpx\n          .card-detail\n            .club-date\n              font-size 32rpx\n              color #606266\n            .club-status\n              font-weight bold\n              font-size 28rpx\n              color #45d4fb\n              float right\n        .card-choice\n          justify-content space-around\n          .club-first-choice\n            border-right solid 2rpx rgba(218, 218, 218, 0.8)\n          .club-first-choice, .club-second-choice\n            width 50%\n            align-items center\n            span\n              font-size 28rpx\n              color #c0c4cc\n              font-family PingFangSC-Regular\n            view\n              overflow hidden\n              text-overflow ellipsis\n              white-space nowrap\n              max-width 220rpx\n              font-size 52rpx\n              color #353535\n        .card-footer\n          justify-content space-between\n          span\n            font-size 24rpx\n            color #9b9b9b\n            font-family PingFangSC-Regular\n        .card-nomore\n          font-size 32rpx\n          color #9b9b9b\n          position absolute\n          top 24rpx\n          display none\n        .nojoin-pic\n          width 350rpx\n      .card-line\n        height 2rpx\n        width calc(100% - 44rpx)\n        margin 0 auto\n        background-image linear-gradient(to right, #dadada, #dadada 15rpx, transparent 15rpx, transparent)\n        background-size 30rpx 100%\n    .card-container:first-of-type\n      overflow visible\n    .card-container:last-child\n      overflow visible\n      .club-card\n        .card-nomore\n          display block\n      .card-line\n        display none\n  .footer-container\n    overflow hidden\n    z-index 2\n    padding-top 30rpx\n    position relative\n    bottom 290rpx\n    .club-footer\n      height 370rpx\n      padding 0 20rpx\n      background #fff\n      box-shadow 0rpx 0rpx 24rpx 0rpx rgba(168, 168, 168, 0.5)\n      .club-des\n        padding 60rpx 0 20rpx 0\n.club-des\n  align-items center\n  view\n    font-family PingFangSC-Regular\n    color #9b9b9b\n    font-size 24rpx\n.save-btn, .xiaotan-btn\n  width 100%\n  height 100rpx\n  margin 40rpx 0 60rpx 0\n  display flex\n  align-items center\n  justify-content center\n  background linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%)\n  box-shadow 0rpx 0rpx 50rpx 0rpx rgba(168, 168, 168, 0.5)\n  border-radius 30rpx\n  span\n    font-size 36rpx\n    color #fff\n.questionnaire-title\n  font-size 32rpx\n  color #353535\n  margin-bottom 30rpx\n.club-box\n  height 80rpx\n  width 100%\n  border-radius 8rpx\n  border solid 1px #dcdfe5\n  background #fff\n  margin 0 20rpx 20rpx 0\n  font-size 28rpx\n  padding-left 30rpx\n  box-sizing border-box\n  font-family PingFangSC-Regular\n  display flex\n  align-items center\n.club-box:last-child\n  margin-right 0\n.questionnaire-row\n  justify-content space-between\n  .user-name, .user-college, .user-major\n    background #f4f6f9\n  picker\n    color #909399\n    position relative\n    display inline-block\n    view\n      display inline-block\n      max-width 190rpx\n      overflow hidden\n      text-overflow ellipsis\n      white-space nowrap\n      line-height 80rpx\n    .picker-arrow\n      margin-right 30rpx\n      position absolute\n      right 0\n      top 50%\n      transform translateY(-50%)\n      height 0\n      width 0\n      border-top 16rpx solid #8f9299\n      border-left 10rpx solid transparent\n      border-right 10rpx solid transparent\nbutton:after\n  border none\n.club-scroll\n  height calc(100vh - 272rpx)\n  position absolute\n  top 280rpx\n  // padding-top 45rpx\n.row\n  display flex\n  flex-direction row\n.column\n  display flex\n  flex-direction column\n.club-toast\n  margin 0 auto\n  background rgba(0, 0, 0, 0.5)\n  z-index 3\n  position absolute\n  right 40rpx\n  left 40rpx\n  bottom -120rpx\n  opacity 0\n  color #fff\n  font-size 26rpx\n  padding 20rpx 60rpx\n  font-family PingFangSC-Regular\n  border-radius 10rpx\n  transition 0.2s ease-in 0s\n  view\n    text-align center\n.club-toast-fadeInUp\n  bottom 80rpx\n  opacity 1\n  transition 0.2s ease-in 0s\n</style>\n"
  },
  {
    "path": "src/others-page/pages/associationPages/register-success.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"header\"></view>\n    <view class=\"body-container\">\n      <view class=\"body\">\n        <view class=\"register-result\">\n          <image src=\"https://static.airbob.org/association-success/QjE2MDEyMzI3LeaKpeWQjeeVjOmdoi5wbmc=\">\n        </view>\n        <!-- <view class=\"advertisement\">\n          <image src=\"https://static.airbob.org/under-graduate/advertise_asso.jpg\">\n        </view> -->\n        <view class=\"cut-line\"></view>\n        <view class=\"footer\">\n          使用南邮小程序招新系统报名社团与线下填写纸质表具有相同报名效力。\n          且线上报名更加方便、快捷、环保。\n        </view>\n      </view>\n      <view\n        @tap.stop=\"toAssociationHome\"\n        class=\"submission\"\n      >\n        <view>查看更多社团</view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\nimport pageJump from \"@/others-page/mixins/page-jump.js\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"社团报名\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"社团报名\",\n    modify: false,\n    tagId: 0,\n    schoolTalkToken: \"\"\n  };\n  mixins = [pageJump];\n  computed = {\n    modifyStatus() {\n      return this.modify === \"true\"\n        ? `https://static.airbob.org/under-graduate/xgcg.png`\n        : `https://static.airbob.org/under-graduate/ok.png`;\n    }\n  };\n  onLoad(option) {\n    this.schoolTalkToken = wepy.getStorageSync(\"token\");\n    this.modify = option.modify;\n    this.tagId = Number(option.tagId);\n    this.$apply();\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\n.container\n  width 100%\n  height 100vh\n  .header\n    width 100%\n    height 136px\n    background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%), linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, rgba(0, 0, 0, 0.5) 100%)\n    background-blend-mode normal, normal\n    position fixed\n    top 0\n    z-index -1\n  .body-container\n    width 100%\n    display flex\n    flex-direction column\n    align-items center\n    .body\n      margin 14px 12.5px 16px 12.5px\n      // width 350px\n      // height 536px\n      width 90vw\n      background-color #ffffff\n      box-shadow 0px 0px 12px 0px rgba(168, 168, 168, 0.5)\n      border-radius 14px\n      display flex\n      flex-direction column\n      align-items center\n      .register-result\n        margin-top 15px\n        margin-bottom 17px\n        image\n          width 85vw\n          height 120vw\n      .advertisement\n        margin-bottom 39px\n        image\n          width 319px\n          height 136px\n      .cut-line\n        width 100%\n        height 1px\n        background rgba(218, 218, 218, 0.5)\n      .footer\n        width 246px\n        height 51px\n        text-align center\n        font-family 'PingFangSC-Regular'\n        font-size 12px\n        color #9b9b9b\n        margin 10px 0px 10px 0px\n    .submission\n      width 90vw\n      height 49px\n      background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%)\n      box-shadow 0px 0px 25px 0px rgba(168, 168, 168, 0.5)\n      border-radius 14px\n      display flex\n      justify-content center\n      align-items center\n      margin-bottom 38px\n      view\n        font-family 'PingFangSC-Semibold'\n        font-size 18px\n        color #ffffff\n</style>\n"
  },
  {
    "path": "src/others-page/pages/auth.wpy",
    "content": "<template>\n  <view class=\"auth\">\n    <qy-navigation :title=\"navTitle\" :background=\"background\"></qy-navigation>\n    <view id=\"login-cloak\">\n      <view class=\"left-pane {{ isOthersOpen ? 'open' : '' }}\">\n        <view class=\"keyhole\" @tap=\"scanCode\">\n          <view class=\"outer-circle\">\n            <view class=\"inner-circle\">\n              <view class=\"rect {{ isHoleOpen ? 'open' : '' }}\"></view>\n            </view>\n          </view>\n        </view>\n      </view>\n      <view class=\"middle-pane {{ isOthersOpen ? 'open' : '' }}\" @tap=\"toggle\"></view>\n      <view class=\"right-pane {{ isOthersOpen ? 'open' : '' }}\"></view>\n    </view>\n    <view class=\"content\">\n      <p class=\"header\">WELCOME</p>\n      <image class=\"pomelo\" src=\"https://static.airbob.org/report-2018-06/logo-min.png\"/>\n    </view>\n  </view>\n</template>\n\n\n<script>\nimport wepy from \"wepy\";\nimport Crypto from \"../../utils/Crypto.js\";\nimport { ME } from \"@/api/common\";\nimport navigation from \"@/components/qy-navigation\";\n\nconst KEY = Crypto.utf8Encode(\"75564012e1db214d\");\nconst IV = Crypto.utf8Encode(\"ee3e54c80a55628d\");\nconst crypto = new Crypto(KEY, IV);\n\nexport default class Auth extends wepy.page {\n  config = {\n    navigationBarTitleText: \"认证\",\n    navigationBarBackgroundColor: \"#45D3FB\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    background: \"#45D3FB\",\n    navTitle: \"认证\",\n    open: false,\n    isHoleOpen: false,\n    isOthersOpen: false\n  };\n\n  handleCodeRes(path) {\n    const params = path\n      .split(\"?\")[1]\n      .split(\"&\")\n      .map(item => ({\n        key: item.split(\"=\")[0],\n        value: item.split(\"=\")[1]\n      }));\n    this.handleScene(params.find(({ key }) => key === `scene`).value);\n  }\n\n  async handleScene(authid) {\n    if (authid === `undefined`) {\n      return;\n    }\n    const sessionid = wepy.getStorageSync(\"token\");\n    const timestamp = Math.floor(Date.now() / 1000).toString();\n    const {\n      data: { data, success, ...err }\n    } = await ME(\n      crypto.jsonEncrypt({\n        sessionid,\n        timestamp,\n        authid\n      })\n    );\n    if (success) {\n      const status = crypto.jsonDecrypt(data.encrypted).status;\n      if (status) {\n        this.handleOpen();\n      }\n    } else {\n      console.error(err);\n    }\n  }\n\n  methods = {\n    scanCode() {\n      wepy\n        .scanCode()\n        .then(res => {\n          this.handleCodeRes(res.path);\n        })\n        .catch(err => console.error(err));\n    },\n    toggle() {\n      if (!this.open) {\n        this.handleOpen();\n      } else {\n        this.handleClose();\n      }\n    }\n  };\n\n  handleOpen() {\n    this.open = true;\n    this.isHoleOpen = true;\n    setTimeout(() => {\n      this.isOthersOpen = true;\n      this.$apply();\n    }, 1000);\n  }\n\n  handleClose() {\n    this.open = false;\n    setTimeout(() => {\n      this.isHoleOpen = false;\n      this.$apply();\n    }, 1000);\n    this.isOthersOpen = false;\n  }\n\n  onLoad(options) {\n    const scene = decodeURIComponent(options.scene);\n    this.handleScene(scene);\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\nvendors = official\nflexbox()\n  display flex\nflex($values)\n  flex $values\nflexdiretion($direction = 'column')\n  flex-direction $direction\norder($val)\n  order $val\n#login-cloak\n  position absolute\n  top 0\n  bottom 0\n  left 0\n  right 0\n  z-index 100\n  flexbox()\n  .left-pane\n    position relative\n    background rgb(246, 246, 246)\n    border-right 15px solid rgb(250, 250, 250)\n    width 50%\n    // min-width 300px\n    flex(1 auto)\n    order(0)\n    transition-duration 700ms\n    &.open\n      width 0\n      transition-duration 700ms\n      min-width 0\n      margin-left -200px\n    &:after\n      position absolute\n      content ' '\n      top 0\n      bottom 0\n      right 0\n      width 1px\n      background rgb(178, 178, 178)\n    .keyhole\n      width 150px\n      height 150px\n      border 1px solid rgb(178, 178, 178)\n      border-radius 50%\n      background #fff\n      position absolute\n      top 40%\n      right -90px\n      z-index 100\n      flexbox()\n      justify-content center\n      .outer-circle\n        flex(1 auto)\n        order(0)\n        max-width 125px\n        height 125px\n        margin auto\n        border 1px solid rgb(178, 178, 178)\n        border-radius 50%\n        flexbox()\n        justify-content center\n        background rgb(40, 215, 255)\n        background linear-gradient(to bottom, rgba(40, 215, 255, 1) 19%, rgba(43, 163, 215, 1) 52%, rgb(60, 139, 194) 90%)\n        .inner-circle\n          flex(1 100%)\n          order(0)\n          max-width 100px\n          height 100px\n          background rgb(246, 246, 246)\n          margin auto\n          border 1px solid rgb(178, 178, 178)\n          border-radius 50%\n          flexbox()\n          justify-content center\n          .rect\n            position relative\n            flex(1 auto)\n            order(0)\n            max-width 20px\n            height 70px\n            background rgb(102, 102, 102)\n            margin auto\n            box-shadow inset 0 0 10px rgba(0, 0, 0, 0.8)\n            &:after\n              content ' '\n              position absolute\n              top 20px\n              left 0\n              width 0\n              height 0\n              border 5px solid rgba(0, 0, 0, 0)\n              border-left-color #F6F6F6\n            &:before\n              content ' '\n              position absolute\n              bottom 25px\n              right 0\n              width 0\n              height 0\n              border 5px solid rgba(0, 0, 0, 0)\n              border-right-color #F6F6F6\n            transition-duration 1s\n            &.open\n              transform rotate(180deg)\n              transition-duration 1s\n  .middle-pane\n    width 0\n    max-width 0\n    background rgba(0, 0, 0, 0)\n    border-left 1px solid rgb(178, 178, 178)\n    border-right 1px solid rgb(178, 178, 178)\n    flex(1 auto)\n    order(1)\n    transition-duration 700ms\n    &.open\n      width 150%\n      max-width 150%\n      transition-duration 700ms\n  .right-pane\n    background rgb(246, 246, 246)\n    border-left 15px solid rgb(250, 250, 250)\n    position relative\n    width 50%\n    flex(1 auto)\n    order(2)\n    transition-duration 700ms\n    &.open\n      transition-duration 700ms\n      width 0\n      margin-right -200px\n    &:before\n      position absolute\n      top 0\n      bottom 0\n      left 0\n      width 1px\n      content ' '\n      background rgb(178, 178, 178)\n.content\n  display flex\n  position relative\n  width 100vw\n  height 100vh\n  justify-content center\n  align-items center\n  background #f6f6f6\n  .header\n    position absolute\n    font-size 60rpx\n    top 20vh\n  .pomelo\n    width 150rpx\n    height 150rpx\n    animation rotating 5s linear infinite\n    @keyframes rotating\n      from\n        transform rotate(0deg)\n      to\n        transform rotate(360deg)\n</style>\n"
  },
  {
    "path": "src/others-page/pages/close.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"container\">\n      <view>\n        <view class=\"image-container\">\n          <image\n            src=\"https://static.airbob.org/under-graduate/pic_stop%20service.png\"\n            style=\"width:400rpx;height:244rpx\"\n            mode=\"aspecfFit\"\n          >\n        </view>\n        <view class=\"words\">该功能暂时暂停服务，若有不便请见谅！</view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\nexport default class Course extends wepy.page {\n  config = {\n    navigationBarTitleText: \"暂停服务\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"暂停服务\"\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  height 80vh\n  display flex\n  flex-direction column\n  align-items center\n  justify-content center\n  .image-container\n    width 400rpx\n    height 244rpx\n    margin 0 auto\n  .words\n    margin-top 60rpx\n    text-align center\n    font-family PingFangSC-Regular\n    font-size 28rpx\n    color #999CA0\n    letter-spacing 0.11rpx\n</style>\n"
  },
  {
    "path": "src/others-page/pages/display-webview.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <block wx:hidden=\"{{token === ''}}\">\n      <web-view class=\"webview\" src=\"{{REQUEST_URL}}?token={{token}}\"></web-view>\n    </block>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"\",\n    token: \"\",\n    REQUEST_URL: \"\"\n  };\n\n  onLoad(option) {\n    this.REQUEST_URL = option.link;\n    this.token = wepy.getStorageSync(\"token\");\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.webview\n  width 100vw\n  height 100vh\n</style>\n"
  },
  {
    "path": "src/others-page/pages/feedbackPages/feedback.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <view style=\"width:750rpx;margin-bottom:120rpx;\">\n        <view class=\"feedback-container\">\n          <view class=\"main-title\">近期热门话题</view>\n          <repeat for=\"{{titles}}\" index=\"index\" item=\"item\">\n            <view class=\"detail-title\" @tap=\"showDetail\" data-index=\"{{index}}\" animation=\"{{showOff[index]}}\">{{item.title}}\n              <view class=\"arrow-image\" animation=\"{{arrowAnimation[index]}}\"></view>\n              <view class=\"main-info\" id=\"hidden{{index}}\">{{Para[index]}}</view>\n            </view>\n            <view class=\"main-title\" wx:if=\"{{item.change}}\">{{item.next}}</view>\n          </repeat>\n        </view>\n      </view>\n      <view class=\"bottom\">\n        <view class=\"to-feedback\" @tap=\"myFeedback\">我要反馈</view>\n        <view class=\"history-feedback\" @tap=\"historyFeedback\">历史反馈</view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"帮助与反馈\"\n  };\n  components = {\n    BaseContainer\n  };\n  data = {\n    navTitle: \"帮助与反馈\",\n    titles: [\n      {\n        title: \"图书馆功能为什么暂停服务？\",\n        show: false\n      },\n      {\n        title: \"为什么食堂刷卡机上余额与小程序上不一致\",\n        show: false\n      },\n      {\n        title: \"小程序显示充值成功但刷卡时仍然余额不足？\",\n        show: false\n      },\n      {\n        title: \"水控无法自动扣费/扣费异常\",\n        show: false\n      },\n      {\n        title: \"无法在小程序上更新正方密码\",\n        show: false\n      },\n      {\n        title: \"需要更新自主化学分系统密码\",\n        show: false\n      },\n      {\n        title: \"需要更新体育部密码\",\n        show: false\n      },\n      {\n        title: \"成绩排名是从0开始还是1开始排？\",\n        show: false,\n        change: true,\n        next: \"南邮小程序相关问题\"\n      },\n      {\n        title: \"南邮小程序如何获取我的信息？\",\n        show: false\n      },\n      {\n        title: \"为什么我的反馈没有回复？\",\n        show: false\n      },\n      {\n        title: \"为什么我进入小程序后所有功能都不能使用？\",\n        show: false\n      },\n      {\n        title: \"为什么我进入小程序后部分功能都不能使用？\",\n        show: false,\n        change: true,\n        next: \"课表功能相关问题\"\n      },\n      {\n        title: \"课表为什么是空的？\",\n        show: false\n      },\n      {\n        title: \"课表为什么部分课程没有显示？\",\n        show: false\n      },\n      {\n        title: \"课表为什么不显示实习周的安排？\",\n        show: false\n      },\n      {\n        title: \"如何查看其它学期/周的课程？\",\n        show: false,\n        change: true,\n        next: \"成绩查询功能相关问题\"\n      },\n      {\n        title: \"为什么绩点排名和辅导员给的的不一致？\",\n        show: false\n      },\n      {\n        title: \"成绩显示的是最新的吗？\",\n        show: false,\n        change: true,\n        next: \"考试/重修和辅导课功能相关问题\"\n      },\n      {\n        title: \"为什么部分科目的考试安排看不到？\",\n        show: false\n      },\n      {\n        title: \"为什么部分科目的重修辅导课看不到？\",\n        show: false\n      },\n      {\n        title: \"体育部密码忘记了怎么办？\",\n        show: false,\n        change: true,\n        next: \"图书馆功能相关问题\"\n      },\n      {\n        title: \"图书借期到了怎么办？\",\n        show: false\n      },\n      {\n        title: \"图书馆的座位查询准确吗？\",\n        show: false\n      },\n      {\n        title: \"图书馆页显示我欠费是怎么回事？\",\n        show: false,\n        change: true,\n        next: \"校园卡相关问题\"\n      },\n      {\n        title: \"充值后显示到账，为什么圈存机显示依然没有？\",\n        show: false\n      },\n      {\n        title: \"我捡到别人校卡后怎么办？\",\n        show: false\n      },\n      {\n        title: \"我丢了校卡后怎么办？\",\n        show: false,\n        change: true,\n        next: \"跑操相关问题\"\n      },\n      {\n        title: \"为什么我某一天的跑操记录只有一次？\",\n        show: false\n      },\n      {\n        title: \"为什么我跑完操后次数没有立即更新？\",\n        show: false\n      },\n      {\n        title: \"小程序里面显示的跑操记录准确吗？\",\n        show: false\n      }\n    ],\n    arrowAnimation: [],\n    translateHeight: 30,\n    winWidth: 0,\n    Para: [\n      \"由于学校的原因，我们获取图书馆信息时出现问题，无法正常提供图书馆小程序服务，不得不暂停，还请谅解。青柚工作室致力于带给柚子们更好的南邮校园小程序服务，正在竭力修复图书馆功能，敬请期待。\",\n      \"因为有时部分刷卡机未联网，暂时无法同步充值记录，请到图书馆大学生事务中心一卡通窗口校对余额，或者在圈存机上再充值1元使余额恢复正常。\",\n      \"因为有时部分刷卡机未联网，暂时无法同步充值记录，请到图书馆大学生事务中心一卡通窗口校对余额，或者在圈存机上再充值1元使余额恢复正常。\",\n      \"水控与南邮小程序无关，相关问题需联系南邮水控解决。若无法扣费，可以先确认一卡通有无充足余额，如果有则水控坏了，请找宿管阿姨报修，或者直接联系南邮水控18951691953 学校的技术老师来处理。\",\n      \"发起小程序反馈或者加青柚官方QQ2092313702，发送新的正方密码附上学生证等身份证明申请人工更新密码。\",\n      \"自主化学分系统密码即http://202.119.225.55/zzxff/ 网站的密码，初始账号密码均为大写的学号，请及时登陆该网站在右下方“个人学分查询”中修改密码并牢记，返回小程序自主学分页面输入更改后的密码即可正常使用。\",\n      \"体育部密码即http://180.209.98.44 体质管理系统iFit网站的密码，初始账号密码均为大写的学号，请及时登陆该网站修改密码并牢记，返回小程序体育部页面根据提示输入更改后的密码即可正常使用。若忘记密码，请发起小程序反馈、加青柚官方QQ2092313702，发送学号附上学生证等身份证明申重置密码。\",\n      \"2019年起，从1开始排，成绩排名数字即排名位次。（2019年之前是从0开始排，排名数字＋1才是真实位次）肖辰旭提醒您不要过分在意自己的名次，不断超越往日的自己就很好了。\",\n      \"南邮小程序由青柚工作室开发，其直属于南邮信息办，故南邮小程序的所有用户信息直接来自南邮信息办。\",\n      \"反馈区的反馈需要人工回复，我们的所有运营成员均为南邮在校生且义务为大家服务，因此，同学们的反馈内容可能无法得到及时的回复，但会尽快处理告知情况。如果有紧急情况，请联系青柚官Q：2092313702.\",\n      `造成小程序所有功能都无法使用的原因可能有：\n1.微信版本过低，当前小程序不支持。解决：升级微信版本\n2.你更新了正方系统的密码，小程序密码未更新。解决：根据小程序弹出的更新正方密码提示输入新的正方密码，或者发起小程序反馈、加青柚官方QQ2092313702，发送新的正方密码附上学生证等身份证明申请人工更新密码\n3.部分未知原因。解决：尝试在后台中退出南邮小程序和微信App，然后重新进入。如果仍有问题请进行反馈或联系官Q2092313702.`,\n      `造成小程序所有功能都无法使用的原因可能有：\n1.微信版本过低，当前小程序不支持。解决：升级微信版本\n2.你更新了正方系统的密码，小程序密码未更新。解决：根据小程序弹出的更新正方密码提示输入新的正方密码，或者发起小程序反馈、加青柚官方QQ2092313702，发送新的正方密码附上学生证等身份证明申请人工更新密码\n3.部分未知原因。解决：尝试在后台中退出南邮小程序和微信App，然后重新进入。如果仍有问题请进行反馈或联系官Q2092313702.`,\n      \"请参见“南邮小程序相关问题”——“为什么我进入小程序后部分功能不能使用？”一问。\",\n      \"课表同步是正方教务系统的课表，没有显示可能是因为：老师尚未更新课表内容，如有相关问题，请联系该课任课老师了解。\",\n      \"课表同步是正方教务系统的课表，正方教务系统中没有对实习周的安排内容，了解相关安排请联系老师或班委。另，在实习周期间，课表仍然正常显示该周课程内容，并会在首页提醒。\",\n      \"进入“课表”后，点击左上角“齿轮”图标，选择学期和周次即可查看。\",\n      \"小程序上的绩点排名根据你专业使用小程序人数进行排序，若你班有同学未使用小程序则不计入排名。小程序上排名仅供参考，实际以辅导员给出为准。\",\n      \"小程序上的排名是正方教务系统的数据，所有数据和更新情况均与正方系统同步。\",\n      \"考试安排根据教务处文件更新，不同考试科目安排的更新时间不同，故有些科目可以查到有些科目尚未更新。但小程序上所查询到的均为教务处最新安排情况。\",\n      \"辅导课安排根据教务处文件更新，不同补考科目辅导课安排的更新时间不同，故有些科目可以查到有些科目尚未更新。但小程序上所查询到的均为教务处最新安排情况。\",\n      \"体育部默认密码为个人学号，如果更改过且遗忘则无法通过个人重置，请前往体育部联系相关老师。\",\n      \"第一次续借到期后可以点击“一键续借”进行延期，第二次续借到期后需要向图书馆归还书籍，否则将产生欠款。\",\n      \"图书馆座位查询显示的数据来自图书馆管理系统，但不完全代表当前图书馆剩余位置数量，仅供参考。\",\n      \"当书籍超过时间未归还且未续借则会产生欠费。欠费满10元将在还书时自动扣款结算；未满10元，欠费将在毕业之前结清。你也可以自行前往图书馆结算。\",\n      \"校园卡充值显示成功且银行卡扣款后，卡上会立即到账。但是，由于学校的部分刷卡终端未进行联网故无法同步最新的数据。当遇到此类情况时，请前往刷卡机进行一次消费，这时，最新余额数据将会写入卡中，即可正常使用。\",\n      \"你可以在“一卡通”功能中找到“校园卡挂失”选项，选择“捡到饭卡”即可提交所拾饭卡信息。如果对方也在使用南邮小程序，则将收到相关信息。\",\n      \"你可以在“一卡通”功能中找到“校园卡挂失”选项，填写信息后提交，即可出现在挂失信息中。如果有人捡到你的校园卡且也在使用南邮小程序，并且上传校园卡信息，则将推送给你。在收回校园卡后可以选择解挂失。\",\n      `某天的跑操记录只有一次可能原因是：\n1.个人失误：自己在起点或者终点处未成功打卡（需要打卡机提示成功打卡信息）。\n2.时间原因：打卡的时间为：6:40~7:20，且两次打卡时间不能超过十分钟，若超过或不在该时间区间则无法成功打卡。\n3.系统原因：部分打卡机出现问题，导致大批量同学没有成功打卡。如遇此类情况请与体育部老师反映，或者告知青柚官Q2092313702，若大范围出现此类情况，我们会帮助反馈。\n4.体育部老师联系方式：体育馆106室王东海老师，邮箱：wangdonghai1998@126.com`,\n      \"跑操的记录并不是在打卡后即时更新的，只有当体育部老师上传打卡记录后方可查询。一般在每天九点钟之后可以成功查到。\",\n      \"小程序所显示的跑操记录来自体育部官方系统，与之同步。\"\n    ],\n    showOff: [],\n    visitorModeStatus: false\n  };\n  methods = {\n    showDetail(e) {\n      this.$apply();\n      let index = e.currentTarget.dataset.index;\n      this.titles[index].show = !this.titles[index].show;\n      let arrowAnimation = wepy.createAnimation({\n        duration: 300\n      });\n      if (this.titles[index].show === true) {\n        arrowAnimation.rotate(-180).step();\n        this.getHeight(index, true);\n      } else {\n        arrowAnimation.rotate(0).step();\n        this.getHeight(index, false);\n      }\n      this.arrowAnimation[index] = arrowAnimation.export();\n      this.$apply();\n    },\n    myFeedback() {\n      if (this.visitorModeStatus) {\n        return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n      }\n      this.$navigate({\n        url: \"myfeedback\"\n      });\n    },\n    historyFeedback() {\n      if (this.visitorModeStatus) {\n        return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n      }\n      this.$navigate({\n        url: \"historyfeedback\"\n      });\n    }\n  };\n  getHeight(index, pulldown) {\n    let that = this;\n    let query = wepy.createSelectorQuery();\n    let Ind = \"#\" + \"hidden\" + index.toString();\n    query.select(Ind).boundingClientRect();\n    query.exec(function(res) {\n      let transHeight = pulldown\n        ? (750 / that.winWidth) * res[0].height + 30\n        : 30;\n      let showOff = wepy.createAnimation({\n        duration: 300,\n        timingFunction: \"ease\"\n      });\n      showOff.height(transHeight + \"rpx\").step();\n      that.showOff[index] = showOff.export();\n      that.$apply();\n    });\n  }\n  onLoad() {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    wepy.getSystemInfo().then(res => {\n      this.winWidth = parseInt(res.windowWidth);\n      this.winHeight = parseInt(res.windowHeight);\n    });\n    for (let i = 0; i < this.titles.length; i++) {\n      this.arrowAnimation.push({});\n    }\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.feedback-container\n  position relative\n  width 700rpx\n  margin 0 auto\n  color #353535\n  padding-bottom 100rpx\n  .main-title\n    font-size 34rpx\n    font-weight bold\n    padding 30rpx 0\n    border-bottom 1rpx solid #E3E3E3\n  .detail-title\n    position relative\n    font-size 30rpx\n    height 35rpx\n    line-height 35rpx\n    padding 30rpx 0\n    border-bottom 1rpx solid #E3E3E3\n    overflow hidden\n    .arrow-image\n      position absolute\n      right 30rpx\n      top 30rpx\n      width 30rpx\n      height 30rpx\n      background-image url('https://static.airbob.org/under-graduate/feedback/button_down.png')\n      background-position center\n      background-size contain\n      background-repeat no-repeat\n    .main-info\n      position relative\n      font-size 24rpx\n      color #888888\n      padding 30rpx 0 0 0\n.bottom\n  position fixed\n  bottom 0rpx\n  width 750rpx\n  height 100rpx\n  color #ffffff\n  font-size 36rpx\n  font-weight bold\n  text-align center\n  .to-feedback\n    position relative\n    display inline-block\n    width 375rpx\n    line-height 100rpx\n    height 100rpx\n    background linear-gradient(-45deg, #ABDCFF 0%, #6AE4FF 100%)\n  .history-feedback\n    position relative\n    display inline-block\n    width 375rpx\n    line-height 100rpx\n    height 100rpx\n    background linear-gradient(-225deg, #A8F7E2 0%, #5EDEB4 100%)\n</style>\n"
  },
  {
    "path": "src/others-page/pages/feedbackPages/historyfeedback.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <qy-tip :content.sync=\"errMsg\" :on.sync=\"errRequest\"/>\n    <view style=\"width:750rpx;\">\n      <view hidden=\"{{shown}}\">\n        <repeat for=\"{{allFeedback}}\" index=\"index\" key=\"key\" item=\"item\">\n          <view\n            class=\"feedback-status\"\n            style=\"border-top:{{index === 0 ? '1rpx solid #E3E3E3' : ''}}\"\n            @tap=\"showDetail\"\n            data-id=\"{{item.id}}\"\n            data-status=\"{{item.status}}\"\n          >\n            <view\n              class=\"feedback-status-image\"\n              style=\"background-image:url({{(item.status !== 2 && item.status !== '2') ? 'https://static.airbob.org/under-graduate/feedback/pic_todo.png' : 'https://static.airbob.org/under-graduate/feedback/pic_finish.png'}})\"\n            ></view>\n            <view class=\"feedback-status-detail\">\n              <view\n                class=\"{{(item.status !== 2 && item.status !== '2') ? 'status' : 'status-done'}}\"\n              >{{(item.status !== 2 && item.status !== '2') ? '处理中' : '处理完成'}}</view>\n              <view>{{item.question}}</view>\n              <view class=\"last-word\">{{item.lastWord}}</view>\n            </view>\n            <view class=\"feedback-status-time\">{{item.time}}</view>\n          </view>\n        </repeat>\n      </view>\n      <view hidden=\"{{!shown}}\">\n        <view class=\"my-feedback\">\n          <view style=\"margin-bottom:300rpx;\">\n            <repeat for=\"{{myFeed}}\" index=\"index\" key=\"key\" item=\"item\">\n              <view\n                wx:if=\"{{item.status === 'user'}}\"\n                class=\"my-content\"\n                animation=\"{{animationPush}}\"\n                style=\"min-height:{{item.feedtype === 'image' ? '600rpx' : '100rpx'}};\"\n              >\n                <view class=\"my-content-container\">\n                  <view class=\"my-content-detail\">\n                    <view class=\"loading-area\">\n                      <view wx:if=\"{{!LoadingHide[index]}}\">\n                        <i class=\"weui-loading\"></i>\n                      </view>\n                      <view wx:if=\"{{sendErr[index]}}\">\n                        <image\n                          style=\"width:40rpx;height:40rpx;\"\n                          src=\"https://static.airbob.org/under-graduate/more/icon_fail.png\"\n                          mode=\"aspectFit\"\n                        />\n                      </view>\n                    </view>\n                    <view wx:if=\"{{item.feedtype === 'content'}}\">{{item.content}}</view>\n                    <view wx:if=\"{{item.feedtype === 'image'}}\">\n                      <image\n                        wx:if=\"{{item.feedtype === 'image'}}\"\n                        class=\"feed-image\"\n                        src=\"{{item.content}}\"\n                        mode=\"aspectFit\"\n                      />\n                    </view>\n                    <view class=\"my-content-arrow\"></view>\n                  </view>\n                </view>\n                <view class=\"my-portrait\">\n                  <open-data type=\"userAvatarUrl\"></open-data>\n                </view>\n                <!-- <image class=\"my-portrait\" mode=\"aspectFit\" src=\"{{portrait}}\"/> -->\n              </view>\n              <view\n                wx:if=\"{{item.status === 'manage'}}\"\n                class=\"my-content\"\n                style=\"min-height:{{item.feedtype === 'image' ? '600rpx' : '100rpx'}};left:0;\"\n              >\n                <view class=\"my-content-container\">\n                  <view class=\"my-content-detail-left\">\n                    <view wx:if=\"{{item.feedtype === 'content'}}\">{{item.content}}</view>\n                    <view wx:if=\"{{item.feedtype === 'image'}}\">\n                      <image\n                        wx:if=\"{{item.feedtype === 'image'}}\"\n                        class=\"feed-image\"\n                        src=\"{{item.content}}\"\n                        mode=\"aspectFit\"\n                      />\n                    </view>\n                    <view class=\"my-content-arrow\"></view>\n                  </view>\n                </view>\n                <view class=\"my-portrait-left\"></view>\n              </view>\n            </repeat>\n            <view\n              class=\"close-feedback\"\n              hidden=\"{{feedbackFinish || feedbackClosed}}\"\n              style=\"z-index:100;\"\n              @tap.stop=\"closeFeedback\"\n            >关闭工单</view>\n            <view\n              class=\"close-feedback\"\n              hidden=\"{{feedbackFinish || !feedbackClosed}}\"\n              id=\"close\"\n              animation=\"{{animation_1}}\"\n              @tap.stop=\"confirmClose\"\n            >关闭</view>\n            <view\n              class=\"close-feedback\"\n              hidden=\"{{feedbackFinish || !feedbackClosed}}\"\n              id=\"cancel\"\n              animation=\"{{animation_2}}\"\n              @tap.stop=\"closeFeedback\"\n            >取消</view>\n            <view class=\"finish\" hidden=\"{{!feedbackFinish}}\">\n              <view class=\"finish-line\"></view>工单处理完成\n              <view class=\"finish-line\"></view>\n            </view>\n          </view>\n          <view class=\"type-in\">\n            <view class=\"type-in-image\" @tap=\"chooseImage\"></view>\n            <textarea\n              value=\"{{content}}\"\n              class=\"type-in-word\"\n              cursor-spacing=\"8\"\n              placeholder=\"编辑好按Enter键直接发送哦\"\n              placeholder-style=\"color:#888888;font-size:28rpx;\"\n              @input=\"inputWord\"\n              @confirm=\"searchSubmit\"\n              focus={{inputFocus}}\n              auto-height=\"{{true}}\"\n              fixed=\"{{true}}\"\n            />\n          </view>\n        </view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport tip from \"@/components/qy-tip\";\nimport {\n  feedbackReactionIDdetail,\n  feedbackReactionContent,\n  feedbackClose,\n  feedback\n} from \"@/api/feedback\";\nimport { REQUEST_URL } from \"@/api/url\";\nimport navigation from \"@/components/qy-navigation\";\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"历史反馈\"\n  };\n  data = {\n    navTitle: \"历史反馈\",\n    allFeedback: [],\n    shown: false,\n    animationTop: {},\n    winWidth: 0,\n    winHeight: 0,\n    myFeed: [],\n    content: \"\",\n    animationPush: {},\n    feedbackFinish: true,\n    LoadingHide: [],\n    sendErr: [],\n    feedbackId: \"\",\n    errRequest: false,\n    errMsg: \"\",\n    // portrait: \"\",\n    feedbackClosed: false,\n    animation_1: {},\n    animation_2: {},\n    inputFocus: false\n  };\n  components = {\n    \"qy-tip\": tip,\n    \"qy-navigation\": navigation\n  };\n  methods = {\n    async showDetail(e) {\n      let that = this;\n      this.shown = !this.shown;\n      let id = e.currentTarget.dataset.id;\n      this.feedbackId = id;\n      if (\n        e.currentTarget.dataset.status === 1 ||\n        e.currentTarget.dataset.status === 0\n      ) {\n        that.feedbackFinish = false;\n      } else {\n        that.feedbackFinish = true;\n      }\n      that.$apply();\n      feedbackReactionIDdetail(this.feedbackId).then(res => {\n        let response = res.data;\n        if (response.success) {\n          response.data.forEach((element, index) => {\n            that.sendErr[index] = false;\n            that.LoadingHide[index] = true;\n            that.myFeed.push({\n              content:\n                element.contentType === 0 ? element.message : element.picUrl,\n              feedtype: element.contentType === 0 ? \"content\" : \"image\",\n              status: element.createUser === 0 ? \"user\" : \"manage\"\n            });\n          });\n          setTimeout(() => {\n            let animation = wepy.createAnimation({\n              duration: 0\n            });\n            animation.translate(-this.winWidth, 0).step();\n            that.animationPush = animation.export();\n            that.$apply();\n            that.animationPush = {};\n          }, 0);\n          this.inputFocus = true;\n          that.$apply();\n        }\n      });\n    },\n    chooseType(e) {\n      let index = e.currentTarget.dataset.index;\n      this.titles[index].show = true;\n      let animation = wepy.createAnimation({\n        duration: \"500\",\n        delay: \"300\"\n      });\n      animation.translate(0, -this.winHeight).step();\n      this.animationTop = animation.export();\n      setTimeout(() => {\n        this.pullUp = true;\n        this.navTitle = \"我要反馈\";\n        this.$apply();\n      }, 800);\n      this.$apply();\n    },\n    inputWord(e) {\n      this.content = e.detail.value;\n    },\n    async chooseImage() {\n      let that = this;\n      if (!this.feedbackFinish) {\n        await wepy\n          .chooseImage({\n            count: 1\n          })\n          .then(e => {\n            let tempFilePaths = e.tempFilePaths[0];\n            that.LoadingHide[this.LoadingHide.length] = false;\n            that.sendErr[this.sendErr.length] = false;\n            that.myFeed.push({\n              content: tempFilePaths,\n              feedtype: \"image\",\n              status: \"user\"\n            });\n            wepy\n              .uploadFile({\n                url: `${REQUEST_URL}/feedback/${this.feedbackId}/detail/pic`,\n                filePath: tempFilePaths,\n                name: \"file\",\n                data: {\n                  file: tempFilePaths\n                },\n                header: {\n                  Cookie: \"session_id=\" + wepy.getStorageSync(\"token\")\n                }\n              })\n              .then(res => {\n                let response = JSON.parse(res.data);\n                if (!response.success) {\n                  that.errRequest = true;\n                  that.errMsg = response.errMsg;\n                  that.LoadingHide[that.LoadingHide.length - 1] = true;\n                  that.sendErr[this.sendErr.length - 1] = true;\n                  that.$apply();\n                } else {\n                  that.LoadingHide[that.LoadingHide.length - 1] = true;\n                  that.$apply();\n                }\n              });\n            that.$apply();\n            setTimeout(() => {\n              let animation = wepy.createAnimation({\n                duration: 200\n              });\n              animation.translate(-this.winWidth, 0).step();\n              that.animationPush = animation.export();\n              that.$apply();\n              that.animationPush = {};\n            }, 0);\n            wepy.pageScrollTo({\n              scrollTop: 9999999\n            });\n          });\n      }\n    },\n    async searchSubmit() {\n      if (!this.feedbackFinish) {\n        if (this.content !== \"\") {\n          this.LoadingHide[this.LoadingHide.length] = false;\n          this.sendErr[this.sendErr.length] = false;\n          this.myFeed.push({\n            content: this.content,\n            feedtype: \"content\",\n            status: \"user\"\n          });\n        }\n        let that = this;\n        feedbackReactionContent(this.feedbackId, this.content).then(res => {\n          let response = res.data;\n          if (!response.success) {\n            that.errRequest = true;\n            that.errMsg = response.errMsg;\n            that.LoadingHide[that.LoadingHide.length - 1] = true;\n            that.sendErr[this.sendErr.length - 1] = true;\n            that.$apply();\n          } else {\n            that.LoadingHide[that.LoadingHide.length - 1] = true;\n          }\n        });\n        this.content = \"\";\n        wepy.pageScrollTo({\n          scrollTop: 9999999\n        });\n        setTimeout(() => {\n          let animation = wepy.createAnimation({\n            duration: 200\n          });\n          animation.translate(-this.winWidth, 0).step();\n          this.animationPush = animation.export();\n          this.$apply();\n          this.animationPush = {};\n        }, 0);\n      }\n    },\n    closeFeedback(e) {\n      let that = this;\n      let flag = this.feedbackClosed;\n      if (!this.feedbackClosed) {\n        this.feedbackClosed = true;\n        this.$apply();\n      } else {\n        setTimeout(() => {\n          that.feedbackClosed = false;\n          that.$apply();\n        }, 300);\n      }\n      let animation = wepy.createAnimation({\n        duration: 300\n      });\n      let animation2 = wepy.createAnimation({\n        duration: 300\n      });\n      animation\n        .right(flag ? \"20rpx\" : \"200rpx\")\n        .width(flag ? \"260rpx\" : \"140rpx\")\n        .step();\n      animation2.width(flag ? \"260rpx\" : \"140rpx\").step();\n      this.animation_1 = animation.export();\n      this.animation_2 = animation2.export();\n      this.$apply();\n    },\n    async confirmClose() {\n      let that = this;\n      let response = await feedbackClose(this.feedbackId, 2);\n      if (response.data.success) {\n        let animation = wepy.createAnimation({\n          duration: 300\n        });\n        let animation2 = wepy.createAnimation({\n          duration: 300\n        });\n        animation.right(\"-400rpx\").step();\n        animation2.right(\"-400rpx\").step();\n        this.animation_1 = animation.export();\n        this.animation_2 = animation2.export();\n        this.$apply();\n        setTimeout(() => {\n          that.feedbackFinish = true;\n          that.$apply();\n        }, 300);\n      }\n    }\n  };\n  async onLoad() {\n    // this.portrait = wepy.getStorageSync(\"User\").nativeInformation.avatar;\n    let that = this;\n    wepy.showLoading({\n      title: \"正在加载中\"\n    });\n    await wepy.getSystemInfo().then(res => {\n      this.winWidth = parseInt(res.windowWidth);\n      this.winHeight = parseInt(res.windowHeight);\n    });\n    await feedback().then(res => {\n      let response = res.data;\n      if (response.success) {\n        response.data.forEach(element => {\n          if (element.lastDetailModel !== null) {\n            that.allFeedback.push({\n              time: element.lastDetailModel.gmtCreate,\n              status: element.status,\n              lastWord:\n                element.lastDetailModel.contentType === 0\n                  ? element.lastDetailModel.message\n                  : \"【图片】\",\n              question: element.tag,\n              id: element.id\n            });\n          }\n        });\n      }\n    });\n    setTimeout(() => {\n      wepy.hideLoading();\n      let animation = wepy.createAnimation({\n        duration: 200\n      });\n      animation.translate(-this.winWidth, 0).step();\n      that.animationPush = animation.export();\n      that.$apply();\n      that.animationPush = {};\n    }, 0);\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n.loading-area\n  position absolute\n  left -75rpx\n  top 5rpx\n.weui-loading\n  margin 0 5px\n  width 20px\n  height 20px\n  display inline-block\n  vertical-align middle\n  animation spin 1s steps(12) infinite\n  background transparent url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=') no-repeat\n  background-size 100%\n  @keyframes spin\n    0%\n      transform rotate(0deg)\n    to\n      transform rotate(1turn)\n.feedback-status\n  position relative\n  width 730rpx\n  margin 0 auto\n  border-bottom 1rpx solid #E3E3E3\n  height 120rpx\n  display flex\n  padding 14rpx 0\n  .feedback-status-image\n    display inline-block\n    width 100rpx\n    height 100rpx\n    position relative\n    background-repeat no-repeat\n    background-size contain\n    background-position center\n    margin-top 10rpx\n    margin-right 30rpx\n  .feedback-status-detail\n    position relative\n    display flex\n    flex-direction column\n    .status\n      font-size 24rpx\n      color #10AEFF\n    .status-done\n      font-size 24rpx\n      color #09BB07\n    .last-word\n      max-width 300rpx\n      overflow hidden\n      text-overflow ellipsis\n      white-space nowrap\n      font-size 24rpx\n      color #888888\n  .feedback-status-time\n    position absolute\n    right 0rpx\n    font-size 24rpx\n    line-height 120rpx\n    color #999CA0\n.feedback-container\n  position absolute\n  z-index 5\n  width 700rpx\n  padding-left 25rpx\n  padding-right 25rpx\n  color #353535\n  background #fff\n  min-height 90vh\n  .main-title\n    font-size 34rpx\n    font-weight bold\n    padding 30rpx 0\n    border-bottom 1rpx solid #E3E3E3\n  .detail-title\n    position relative\n    font-size 30rpx\n    height 35rpx\n    line-height 35rpx\n    padding 30rpx 0\n    border-bottom 1rpx solid #E3E3E3\n    overflow hidden\n    .arrow-image\n      position absolute\n      right 30rpx\n      top 30rpx\n      width 30rpx\n      height 30rpx\n      background-position center\n      background-size contain\n      background-repeat no-repeat\n    .main-info\n      position relative\n      font-size 24rpx\n      color #888888\n      padding 30rpx 0 0 0\n.my-feedback\n  position absolute\n  z-index -1\n  width 750rpx\n  border-top 1rpx solid #E3E3E3\n  min-height 90vh\n  background #FCFCFC\n  .my-content\n    position relative\n    width 750rpx\n    margin-top 30rpx\n    left 750rpx\n    .my-portrait\n      position absolute\n      top 0\n      right 30rpx\n      width 100rpx\n      height 100rpx\n      border-radius 50%\n      box-shadow 0 0 10rpx 0 rgba(56, 138, 255, 0.15)\n      overflow hidden\n    .my-portrait-left\n      position absolute\n      top 0\n      width 100rpx\n      height 100rpx\n      left 30rpx\n      border-radius 50%\n      box-shadow 0 0 10rpx 0 rgba(56, 138, 255, 0.15)\n      background-image url('https://static.airbob.org/under-graduate/pic_photo_xcx.png')\n      background-position center\n      background-size contain\n      background-repeat no-repeat\n    .my-content-container\n      display flex\n      justify-content flex-end\n      position relative\n      .my-content-detail-left\n        position relative\n        margin-left 180rpx\n        margin-right auto\n        background #F5F5F5\n        max-width 300rpx\n        top 25rpx\n        padding 14rpx 24rpx\n        font-size 30rpx\n        line-height 40rpx\n        color #353535\n        word-wrap break-word\n        border-radius 20rpx\n        .feed-image\n          width 300rpx\n          height 550rpx\n        .my-content-arrow\n          position absolute\n          top 15rpx\n          left -15rpx\n          border-top 15rpx solid transparent\n          border-bottom 15rpx solid transparent\n          border-right 20rpx solid #F5F5F5\n      .my-content-detail\n        position relative\n        margin-right 180rpx\n        background #D0F5FF\n        max-width 300rpx\n        top 25rpx\n        padding 14rpx 24rpx\n        font-size 30rpx\n        line-height 30rpx\n        color #353535\n        word-wrap break-word\n        border-radius 20rpx\n        .feed-image\n          width 300rpx\n          height 550rpx\n        .my-content-arrow\n          position absolute\n          top 15rpx\n          right -15rpx\n          border-top 15rpx solid transparent\n          border-bottom 15rpx solid transparent\n          border-left 20rpx solid #D0F5FF\n  .close-feedback\n    position absolute\n    margin-top 30rpx\n    color #fff\n    width 260rpx\n    height 75rpx\n    line-height 75rpx\n    font-size 30rpx\n    text-align center\n    right 20rpx\n    background-image linear-gradient(-180deg, #ADECFD 1%, #65DEF7 98%)\n    box-shadow 0 0 20rpx 0 rgba(0, 211, 255, 0.3)\n    border-radius 100rpx\n  #close\n    z-index 90\n    background-image linear-gradient(-180deg, #FFBDBD 5%, #F28383 100%)\n    box-shadow 0 0 18rpx 0 rgba(243, 135, 135, 0.3)\n  #cancel\n    z-index 80\n    background-image linear-gradient(-180deg, #ADF4AA 8%, #5BD575 100%)\n    box-shadow 0 0 18rpx 0 rgba(105, 219, 126, 0.3)\n    border-radius 100rpx\n.type-in\n  position fixed\n  z-index 300\n  background #ffffff\n  display flex\n  width 750rpx\n  padding 10px 0\n  border-top 1rpx solid #E3E3E3\n  bottom 0\n  align-items center\n  .type-in-image\n    display inline-block\n    width 120rpx\n    height 50rpx\n    background-image url('https://static.airbob.org/under-graduate/feedback/icon_camera.png')\n    background-repeat no-repeat\n    background-size contain\n    background-position center\n  .type-in-word\n    display inline-block\n    width 570rpx\n    padding 5px\n    border-radius 20rpx\n    border 1rpx solid #888888\n    font-size 28rpx\n.finish\n  width 750rpx\n  font-size 24rpx\n  height 101rpx\n  line-height 101rpx\n  color #999ca0\n  text-align center\n  .finish-line\n    display inline-block\n    background #999ca0\n    width 250rpx\n    height 1rpx\n    margin-top 50rpx\n</style>\n"
  },
  {
    "path": "src/others-page/pages/feedbackPages/myfeedback.wpy",
    "content": "<template>\n  <view>\n    <qy-tip :content.sync=\"errMsg\" :on.sync=\"errRequest\"/>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view>\n      <view class=\"feedback-container\" animation=\"{{animationTop}}\">\n        <view class=\"main-title\">选择反馈类型</view>\n        <repeat for=\"{{titles}}\" index=\"index\" item=\"item\">\n          <view class=\"detail-title\" data-index=\"{{index}}\" @tap=\"chooseType\">\n            {{item.title}}\n            <view\n              class=\"arrow-image\"\n              style=\"background-image:url({{item.show ? 'https://static.airbob.org/under-graduate/feedback/btu_highlight.png' : 'https://static.airbob.org/under-graduate/feedback/btu_disable.png'}})\"\n            ></view>\n          </view>\n        </repeat>\n      </view>\n      <view class=\"my-feedback\">\n        <view style=\"margin-bottom:300rpx;\">\n          <repeat for=\"{{myFeed}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view\n              class=\"my-content\"\n              animation=\"{{animationPush}}\"\n              style=\"min-height:{{item.feedtype === 'image' ? '600rpx' : '100rpx'}};\"\n            >\n              <view class=\"my-content-container\">\n                <view class=\"my-content-detail\">\n                  <view class=\"loading-area\">\n                    <view wx:if=\"{{!LoadingHide[index]}}\">\n                      <i class=\"weui-loading\"></i>\n                    </view>\n                    <view wx:if=\"{{sendErr[index]}}\">\n                      <image\n                        style=\"width:40rpx;height:40rpx;\"\n                        src=\"https://static.airbob.org/under-graduate/more/icon_fail.png\"\n                        mode=\"aspectFit\"\n                      >\n                    </view>\n                  </view>\n                  <view wx:if=\"{{item.feedtype === 'content'}}\">{{item.content}}</view>\n                  <view wx:if=\"{{item.feedtype === 'image'}}\">\n                    <image\n                      wx:if=\"{{item.feedtype === 'image'}}\"\n                      class=\"feed-image\"\n                      src=\"{{item.content}}\"\n                      mode=\"aspectFit\"\n                    >\n                  </view>\n                  <view class=\"my-content-arrow\"></view>\n                </view>\n              </view>\n              <view class=\"my-portrait\">\n                <open-data type=\"userAvatarUrl\"></open-data>\n              </view>\n              <!-- <image class=\"my-portrait\" mode=\"aspectFit\" src=\"{{portrait}}\"/> -->\n            </view>\n          </repeat>\n        </view>\n        <view class=\"type-in\">\n          <view class=\"type-in-image\" @tap=\"chooseImage\"></view>\n          <textarea\n            value=\"{{content}}\"\n            class=\"type-in-word\"\n            style=\"min-height:36rpx;line-height:36rpx;\"\n            cursor-spacing=\"8\"\n            placeholder=\"{{placeholder}}\"\n            placeholder-style=\"color:#888888;font-size:28rpx;\"\n            @input=\"inputWord\"\n            @confirm=\"searchSubmit\"\n            focus=\"{{inputFocus}}\"\n            auto-height=\"{{true}}\"\n            fixed=\"{{true}}\"\n          />\n        </view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport tip from \"@/components/qy-tip\";\nimport { feedbackReactionContent, feedbackChooseType } from \"@/api/feedback\";\nimport { REQUEST_URL } from \"@/api/url\";\nimport navigation from \"@/components/qy-navigation\";\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"帮助与反馈\"\n  };\n  data = {\n    navTitle: \"历史反馈\",\n    errRequest: false,\n    errMsg: \"\",\n    feedbackId: \"\",\n    titles: [\n      {\n        title: \"账号问题\",\n        show: false\n      },\n      {\n        title: \"功能反馈\",\n        show: false\n      },\n      {\n        title: \"建议反馈\",\n        show: false\n      },\n      {\n        title: \"使用帮助\",\n        show: false\n      },\n      {\n        title: \"其他\",\n        show: false\n      }\n    ],\n    animationTop: {},\n    winWidth: 0,\n    winHeight: 0,\n    pullUp: false,\n    myFeed: [],\n    content: \"\",\n    animationPush: {},\n    tag: \"\",\n    LoadingHide: [],\n    sendErr: [],\n    // portrait: \"\",\n    placeholder: \"\",\n    inputFocus: false,\n    typeChosed: false\n  };\n  components = {\n    \"qy-tip\": tip,\n    \"qy-navigation\": navigation\n  };\n  methods = {\n    chooseType(e) {\n      if (!this.typeChosed) {\n        this.typeChosed = true;\n        wepy.showLoading({\n          title: \"正在加载中\"\n        });\n        let index = e.currentTarget.dataset.index;\n        this.titles[index].show = true;\n        this.tag = this.titles[index].title;\n        feedbackChooseType(this.tag).then(res => {\n          let response = res.data;\n          if (response.success) {\n            this.feedbackId = response.data.id;\n            let animation = wepy.createAnimation({\n              duration: \"500\",\n              delay: \"300\"\n            });\n            animation.translate(0, -this.winHeight).step();\n            this.animationTop = animation.export();\n            setTimeout(() => {\n              wepy.hideLoading();\n              this.pullUp = true;\n              this.placeholder = \"编辑好按enter键直接发送哦\";\n              this.navTitle = \"我要反馈\";\n              this.$apply();\n              this.inputFocus = true;\n              this.$apply();\n            }, 800);\n            this.$apply();\n          } else {\n            wepy.hideLoading();\n            this.errRequest = true;\n            this.errMsg = response.errMsg;\n            this.titles.forEach(element => {\n              element.show = false;\n            });\n            this.$apply();\n          }\n        });\n      }\n    },\n    inputWord(e) {\n      this.content = e.detail.value;\n    },\n    async chooseImage() {\n      await wepy\n        .chooseImage({\n          count: 1\n        })\n        .then(e => {\n          let tempFilePaths = e.tempFilePaths[0];\n          this.LoadingHide[this.LoadingHide.length] = false;\n          this.sendErr[this.sendErr.length] = false;\n          this.myFeed.push({\n            content: tempFilePaths,\n            feedtype: \"image\",\n            status: \"user\"\n          });\n          wepy\n            .uploadFile({\n              url: `${REQUEST_URL}/feedback/${this.feedbackId}/detail/pic`,\n              filePath: tempFilePaths,\n              name: \"file\",\n              data: {\n                file: tempFilePaths\n              },\n              header: {\n                cookie: \"session_id=\" + wepy.getStorageSync(\"token\")\n              }\n            })\n            .then(res => {\n              let response = JSON.parse(res.data);\n              if (!response.success) {\n                this.errRequest = true;\n                this.errMsg = response.errMsg;\n                this.LoadingHide[this.LoadingHide.length - 1] = true;\n                this.sendErr[this.sendErr.length - 1] = true;\n                this.$apply();\n              } else {\n                this.LoadingHide[this.LoadingHide.length - 1] = true;\n                this.$apply();\n              }\n            });\n          this.$apply();\n          setTimeout(() => {\n            let animation = wepy.createAnimation({\n              duration: 200\n            });\n            animation.translate(-this.winWidth, 0).step();\n            this.animationPush = animation.export();\n            this.$apply();\n            this.animationPush = {};\n          }, 0);\n          wepy.pageScrollTo({\n            scrollTop: 9999999\n          });\n        });\n    },\n    async searchSubmit() {\n      if (this.content !== \"\") {\n        this.LoadingHide[this.LoadingHide.length] = false;\n        this.sendErr[this.sendErr.length] = false;\n        this.myFeed.push({\n          content: this.content,\n          feedtype: \"content\",\n          status: \"user\"\n        });\n      }\n      await feedbackReactionContent(this.feedbackId, this.content).then(res => {\n        let response = res.data;\n        if (!response.success) {\n          this.errRequest = true;\n          this.errMsg = response.errMsg;\n          this.LoadingHide[this.LoadingHide.length - 1] = true;\n          this.sendErr[this.sendErr.length - 1] = true;\n          this.$apply();\n        } else {\n          this.LoadingHide[this.LoadingHide.length - 1] = true;\n        }\n      });\n      this.content = \"\";\n      wepy.pageScrollTo({\n        scrollTop: 9999999\n      });\n      setTimeout(() => {\n        let animation = wepy.createAnimation({\n          duration: 200\n        });\n        animation.translate(-this.winWidth, 0).step();\n        this.animationPush = animation.export();\n        this.$apply();\n        this.animationPush = {};\n      }, 0);\n    }\n  };\n  async onLoad() {\n    await wepy.getSystemInfo().then(res => {\n      // this.portrait = wepy.getStorageSync(\"User\").nativeInformation.avatar;\n      this.winWidth = parseInt(res.windowWidth);\n      this.winHeight = parseInt(res.windowHeight);\n    });\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n.loading-area\n  position absolute\n  left -75rpx\n  top 5rpx\n.weui-loading\n  margin 0 5px\n  width 20px\n  height 20px\n  display inline-block\n  vertical-align middle\n  animation spin 1s steps(12) infinite\n  background transparent url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=') no-repeat\n  background-size 100%\n  @keyframes spin\n    0%\n      transform rotate(0deg)\n    to\n      transform rotate(1turn)\n.feedback-container\n  position absolute\n  z-index 5\n  width 700rpx\n  padding-left 25rpx\n  padding-right 25rpx\n  color #353535\n  background #fff\n  min-height 100vh\n  .main-title\n    font-size 34rpx\n    font-weight bold\n    padding 30rpx 0\n    border-bottom 1rpx solid #E3E3E3\n  .detail-title\n    position relative\n    font-size 30rpx\n    height 35rpx\n    line-height 35rpx\n    padding 30rpx 0\n    border-bottom 1rpx solid #E3E3E3\n    overflow hidden\n    .arrow-image\n      position absolute\n      right 30rpx\n      top 30rpx\n      width 30rpx\n      height 30rpx\n      background-position center\n      background-size contain\n      background-repeat no-repeat\n    .main-info\n      position relative\n      font-size 24rpx\n      color #888888\n      padding 30rpx 0 0 0\n.my-feedback\n  position absolute\n  z-index -1\n  width 750rpx\n  border-top 1rpx solid #E3E3E3\n  min-height 90vh\n  background #FCFCFC\n  .my-content\n    position relative\n    width 750rpx\n    margin-top 30rpx\n    left 750rpx\n    .my-portrait\n      position absolute\n      top 0\n      right 30rpx\n      width 100rpx\n      height 100rpx\n      overflow hidden\n      border-radius 50%\n      box-shadow 0 0 10rpx 0 rgba(56, 138, 255, 0.15)\n    .my-content-container\n      display flex\n      justify-content flex-end\n      position relative\n      .my-content-detail\n        float right\n        position relative\n        margin-right 180rpx\n        background #D0F5FF\n        max-width 300rpx\n        top 25rpx\n        padding 14rpx 24rpx\n        font-size 30rpx\n        line-height 40rpx\n        color #353535\n        word-wrap break-word\n        border-radius 20rpx\n        .feed-image\n          width 300rpx\n          height 550rpx\n        .my-content-arrow\n          position absolute\n          top 15rpx\n          right -15rpx\n          border-top 15rpx solid transparent\n          border-bottom 15rpx solid transparent\n          border-left 20rpx solid #D0F5FF\n.type-in\n  position fixed\n  background #ffffff\n  width 750rpx\n  padding 10px 0\n  border-top 1rpx solid #E3E3E3\n  display flex\n  bottom 0\n  align-items center\n  .type-in-image\n    display inline-block\n    width 120rpx\n    height 50rpx\n    background-image url('https://static.airbob.org/under-graduate/feedback/icon_camera.png')\n    background-repeat no-repeat\n    background-size contain\n    background-position center\n  .type-in-word\n    text-align center\n    display inline-block\n    width 570rpx\n    padding 5px\n    border-radius 20rpx\n    border 1rpx solid #888888\n    font-size 28rpx\n</style>\n"
  },
  {
    "path": "src/others-page/pages/information-box.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <view class=\"box-container\" hidden=\"{{isLoading}}\">\n        <view class=\"box-hide\" hidden=\"{{!noInfo}}\">\n          <view class=\"box-hide-content\">目前还没有收到消息哦</view>\n        </view>\n        <view class=\"box-information-category\" wx:if=\"{{!noInfo}}\">\n          <view class=\"bottom-bar\" animation=\"{{animationData}}\"/>\n          <repeat for=\"{{category}}\" key=\"index\" index=\"index\" item=\"item\">\n            <view\n              class=\"category-container {{currentCategoryIndex === index ? 'current-category' : ''}}\"\n              @tap=\"changeCategory\"\n              data-category=\"{{index}}\"\n            >\n              {{item.text}}\n              <view class=\"red-dot\" wx:if=\"{{item.unreadCount !== 0}}\">{{item.unreadCount}}</view>\n            </view>\n          </repeat>\n        </view>\n        <view class=\"box-top\" hidden=\"{{noInfo}}\">\n          <view class=\"box-container-top\">\n            <view style=\"color: #b4b4b4;font-weight: 600;width: 20%;text-align: center\">消息列表</view>\n            <view class=\"all-read\" @tap=\"allRead\"></view>\n            <view class=\"delete\" @tap=\"Delete\"></view>\n          </view>\n        </view>\n        <view class=\"info-wrapper-container\" wx:if=\"{{!noInfo}}\">\n          <swiper class=\"swiper-container\" current=\"{{lastCategoryIndex}}\" @change=\"handleSwiperChange\">\n            <repeat for=\"{{category}}\" key=\"index\" index=\"index\" item=\"item\">\n              <swiper-item @touchstart=\"handleTouchStart\" @touchmove=\"handleTouchMove\" @touchend=\"handleTouchEnd\">\n                <InfoCard :info.sync=\"item.info\" :id.sync=\"item.tag\" />\n              </swiper-item>\n            </repeat>\n          </swiper>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport {\n  getNotification,\n  getOwnMessageAlready,\n  getOwnMessageClear,\n  noClassConfirm,\n  noClassConfirmNext,\n  setMessageRead\n} from \"@/api/notification\";\nimport {\n  mockGetNotification,\n  mockMarkAllAsRead,\n  mockDeleteAll\n} from \"@/mock/notification\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport InfoCard from \"../components/information-card\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"消息盒子\"\n  };\n  components = {\n    BaseContainer,\n    InfoCard\n  };\n  data = {\n    navTitle: \"消息盒子\",\n    noInfo: true,\n    background: [\n      \"https://static.airbob.org/under-graduate/un-read.png\",\n      \"https://static.airbob.org/under-graduate/read.png\",\n      \"https://static.airbob.org/under-graduate/already-read.png\"\n    ],\n    tapType: [5, 6, 7, 8], //5:反馈,6:无课表,7:问卷,8:跑操\n    visitorModeStatus: false,\n    category: [\n      {\n        text: \"全部通知\",\n        tag: 0,\n        info: [],\n        unreadCount: 0\n      },\n      {\n        text: \"系统通知\",\n        tag: 1,\n        info: [],\n        unreadCount: 0\n      },\n      {\n        text: \"授权通知\",\n        tag: 2,\n        info: [],\n        unreadCount: 0\n      },\n      {\n        text: \"活动通知\",\n        tag: 3,\n        info: [],\n        unreadCount: 0\n      }\n    ],\n    currentCategoryIndex: 0,\n    lastCategoryIndex: 0,\n    animation: null,\n    animationData: null,\n    moveRatio: 0,\n    touchDot: 0,\n    pageWidth: 0,\n    isLoading: true\n  };\n  methods = {\n    allRead() {\n      wepy\n        .showModal({\n          title: \"全标为已读\",\n          content: \"将所有消息标记为已读\",\n          confirmColor: \"#47CFF5\"\n        })\n        .then(response => {\n          if (response.confirm) {\n            this.judgeNotification(\"allRead\").then(res => {\n              if (res.data) {\n                this.category.forEach(item => {\n                  item.unreadCount = 0;\n                  item.info.forEach(msg => {\n                    msg.read = true;\n                    msg.ontap = false;\n                  });\n                });\n                wepy.showToast({\n                  title: \"已全部已读\",\n                  icon: \"success\",\n                  duration: 2000\n                });\n                this.$apply();\n              } else {\n                wepy.showToast({\n                  title: \"不知道为什么失败了呢\",\n                  icon: \"none\",\n                  duration: 2000\n                });\n              }\n            });\n          }\n        });\n    },\n    Delete() {\n      wepy\n        .showModal({\n          title: \"清空消息列表\",\n          content: \"消息列表将被清空\",\n          confirmColor: \"#47CFF5\"\n        })\n        .then(response => {\n          if (response.confirm) {\n            this.judgeNotification(\"deleteAll\").then(res => {\n              if (res.data) {\n                wepy.showToast({\n                  title: \"已清空\",\n                  icon: \"success\",\n                  duration: 2000\n                });\n                this.category.forEach(item => {\n                  item.unreadCount = 0;\n                  item.info = [];\n                });\n                this.noInfo = true;\n                this.$apply();\n              } else {\n                wepy.showToast({\n                  title: \"不知道为什么失败了呢\",\n                  icon: \"none\",\n                  duration: 2000\n                });\n              }\n            });\n          }\n        });\n    },\n    changeCategory(e) {\n      const { category: index } = e.currentTarget.dataset;\n      if (this.currentCategoryIndex !== index) {\n        this.animationData = this.animation\n          .left(`${25 * index}%`)\n          .step()\n          .export();\n        this.currentCategoryIndex = this.lastCategoryIndex = index;\n        this.$apply();\n      }\n    },\n    handleTouchMove(e) {\n      const touchMove = e.touches[0].pageX;\n      //  左滑负， 右滑正\n      this.moveRatio = Number(\n        (touchMove - this.touchDot) / this.pageWidth\n      ).toFixed(2);\n      if (this.lastCategoryIndex === 0 && this.moveRatio < 0) {\n        this.animationData = this.animation\n          .left(`${Math.abs(this.moveRatio) * 25}%`)\n          .step()\n          .export();\n        if (\n          this.moveRatio <= -0.5 &&\n          this.lastCategoryIndex === this.currentCategoryIndex\n        ) {\n          this.currentCategoryIndex = this.currentCategoryIndex + 1;\n        } else if (\n          this.moveRatio > -0.5 &&\n          this.lastCategoryIndex !== this.currentCategoryIndex\n        ) {\n          this.currentCategoryIndex = this.currentCategoryIndex - 1;\n        }\n      } else if (this.lastCategoryIndex === 3 && this.moveRatio > 0) {\n        this.animationData = this.animation\n          .left(`${(this.lastCategoryIndex - this.moveRatio) * 25}%`)\n          .step()\n          .export();\n        if (\n          this.moveRatio >= 0.5 &&\n          this.lastCategoryIndex === this.currentCategoryIndex\n        ) {\n          this.currentCategoryIndex = this.currentCategoryIndex - 1;\n        } else if (\n          this.moveRatio < 0.5 &&\n          this.lastCategoryIndex !== this.currentCategoryIndex\n        ) {\n          this.currentCategoryIndex = this.currentCategoryIndex - 1;\n        }\n      } else if (this.lastCategoryIndex !== 0 && this.lastCategoryIndex !== 3) {\n        this.animationData = this.animation\n          .left(`${(this.lastCategoryIndex - this.moveRatio) * 25}%`)\n          .step()\n          .export();\n        if (\n          (this.moveRatio >= 0.5 || this.moveRatio <= -0.5) &&\n          this.lastCategoryIndex === this.currentCategoryIndex\n        ) {\n          this.currentCategoryIndex =\n            this.moveRatio > 0\n              ? this.currentCategoryIndex - 1\n              : this.currentCategoryIndex + 1;\n        } else if (\n          this.moveRatio < 0.5 &&\n          this.moveRatio > -0.5 &&\n          this.lastCategoryIndex !== this.currentCategoryIndex\n        ) {\n          this.currentCategoryIndex =\n            this.moveRatio > 0\n              ? this.currentCategoryIndex + 1\n              : this.currentCategoryIndex - 1;\n        }\n      }\n    },\n    handleTouchStart(e) {\n      this.touchDot = e.touches[0].pageX;\n      this.moveRatio = 0;\n      this.lastCategoryIndex = this.currentCategoryIndex;\n    },\n    handleTouchEnd() {\n      this.animationData = this.animation\n        .left(`${this.currentCategoryIndex * 25}%`)\n        .step()\n        .export();\n      this.lastCategoryIndex = this.currentCategoryIndex;\n      this.touchDot = -1;\n      this.moveRatio = 0;\n    }\n  };\n  events = {\n    tapCard(dataset) {\n      const { taptype: type, id, ontap, read, title } = dataset;\n      const asso = title.split(\" \")[0];\n      if (type === 5 && ontap) {\n        wepy.navigateTo({\n          url: \"./feedbackPages/historyfeedback\"\n        });\n      } else if (type === 6 && ontap) {\n        wepy\n          .showModal({\n            title: \"授权\",\n            content: \"该授权将获取您的无课表\",\n            confirmColor: \"#47CFF5\"\n          })\n          .then(res => {\n            if (res.confirm) {\n              noClassConfirm(2, asso).then(res => {\n                if (res.data) {\n                  noClassConfirmNext(id).then(res => {\n                    if (res.data) {\n                      this.init();\n                    }\n                  });\n                  wepy.showToast({\n                    title: \"已授权\",\n                    icon: \"success\",\n                    duration: 2000\n                  });\n                } else {\n                  wepy.showToast({\n                    title: \"授权失败\",\n                    icon: \"none\",\n                    duration: 2000\n                  });\n                }\n              });\n            }\n          });\n      } else if (type === 7 && ontap) {\n        wepy.navigateTo({\n          url: \"./questionnairePages/questionnaire-homepage\"\n        });\n      } else if (type === 8 && ontap) {\n        wepy.showLoading({\n          title: \"正在跳转...\"\n        });\n        setMessageRead(id).then(res => {\n          if (res.data && res.data.data) {\n            wepy.hideLoading();\n            this.init();\n            wepy.navigateTo({ url: \"./run?showPoster=true\" });\n          }\n        });\n      } else if (!read) {\n        wepy\n          .showModal({\n            content: \"是否将这条消息标为已读？\",\n            showCancel: true,\n            confirmColor: \"#3CC51F\"\n          })\n          .then(res => {\n            if (res.confirm) {\n              setMessageRead(id).then(res => {\n                if (res.data && res.data.data) {\n                  wepy.showToast({\n                    title: \"已读~\",\n                    icon: \"success\",\n                    duration: 1000,\n                    mask: true\n                  });\n                  this.init();\n                } else {\n                  wepy.showToast({\n                    title: \"不知道为什么失败了呢\",\n                    icon: \"none\",\n                    duration: 2000\n                  });\n                }\n              });\n            }\n          });\n      }\n    }\n  };\n  dealTheDate(time) {\n    time = time / 1000;\n    if (time <= 0) return;\n    if (time < 60) {\n      return ~~time + \" 秒前\";\n    } else if (time < 3600) {\n      return ~~(time / 60) + \" 分钟前\";\n    } else if (time < 86400) {\n      return ~~(time / 3600) + \" 小时前\";\n    } else {\n      return ~~(time / 86400) + \" 天前\";\n    }\n  }\n  judgeNotification(cmd) {\n    switch (cmd) {\n      case \"allRead\":\n        return this.visitorModeStatus\n          ? mockMarkAllAsRead()\n          : getOwnMessageAlready();\n        break;\n      case \"deleteAll\":\n        return this.visitorModeStatus ? mockDeleteAll() : getOwnMessageClear();\n        break;\n      default:\n        break;\n    }\n  }\n  handleSwiperChange(e) {\n    const {\n      detail: { current }\n    } = e;\n    this.currentCategoryIndex = this.lastCategoryIndex = current;\n    this.animationData = this.animation\n      .left(`${current * 25}%`)\n      .step()\n      .export();\n  }\n  async init() {\n    let res = !this.visitorModeStatus\n      ? await getNotification()\n      : await mockGetNotification();\n    let info = [];\n    let read = [];\n    if (res.data) {\n      let data = [];\n      for (let i of res.data.data) {\n        i.creatDate = this.dealTheDate(Date.now() - i.createDate);\n        i.content = i.content.trim().split(\"\\n\");\n        if (this.tapType.indexOf(i.type) !== -1 && !i.read) {\n          i.ontap = true;\n        }\n        if (i.enable) {\n          if (!i.read) {\n            info.unshift(i);\n            data.unshift(i);\n          } else {\n            read.unshift(i);\n          }\n        }\n      }\n      info = info.concat(read);\n    }\n    if (info.length !== 0) {\n      this.noInfo = false;\n      this.pageWidth = wepy.getSystemInfoSync().windowWidth;\n      this.category.forEach(item => {\n        item.info =\n          item.tag === 0 ? info : info.filter(msg => msg.tag === item.tag);\n        item.unreadCount = item.info.filter(msg => !msg.read).length;\n      });\n    }\n    this.$apply();\n  }\n  async onLoad() {\n    wepy.showLoading({\n      title: \"加载中\"\n    });\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.pageWidth = wepy.getSystemInfoSync().windowWidth;\n    this.animation = wepy.createAnimation({ duration: 300 });\n    this.animationData = this.animation\n      .left(\"0%\")\n      .step()\n      .export();\n    await this.init();\n    wepy.hideLoading();\n    this.isLoading = false;\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.box-hide\n  position relative\n  width 500rpx\n  height 400rpx\n  top 250rpx\n  background-image url('https://static.airbob.org/under-graduate/%E7%BC%BA%E7%9C%81%E9%A1%B5_%E7%A9%BA.png')\n  background-position center\n  background-repeat no-repeat\n  background-size contain\n  margin 0 auto\n  .box-hide-content\n    position relative\n    width 500rpx\n    text-align center\n    top 400rpx\n    font-size 30rpx\n    color #E3E3E3\n.box-information-category\n  width 710rpx\n  height 80rpx\n  display flex\n  justify-content space-around\n  align-items center\n  margin 0 auto\n  border-bottom 2rpx solid #e3e3e3\n  position relative\n  .bottom-bar\n    position absolute\n    border-bottom 3px solid #cc4545\n    width 90rpx\n    bottom 0\n    transform translateX(50%)\n  .category-container\n    display flex\n    justify-content center\n    align-items center\n    position relative\n    font-size 30rpx\n    font-weight 600\n    color #474747\n    width 25%\n    height 100%\n    .red-dot\n      width 30rpx\n      height 30rpx\n      border-radius 50%\n      background-color #e33c3c\n      position absolute\n      top 15%\n      right 3%\n      color #fff\n      font-size 24rpx\n      font-weight 500\n      line-height 30rpx\n      display flex\n      justify-content center\n    &.current-category\n      color #cc4545\n.box-top\n  width 710rpx\n  margin 0 auto\n  border-bottom 2rpx solid #E3E3E3\n  padding 20rpx 0\n  .box-container-top\n    display flex\n    align-items center\n    font-size 30rpx\n    padding-left 20rpx\n    .all-read\n      position absolute\n      right 125rpx\n      width 40rpx\n      height 40rpx\n      background-image url('https://static.airbob.org/under-graduate/already-read.png')\n      background-position center\n      background-repeat no-repeat\n      background-size contain\n    .delete\n      position absolute\n      right 45rpx\n      width 40rpx\n      height 40rpx\n      background-image url('https://static.airbob.org/under-graduate/%E6%B8%85%E7%A9%BA.png')\n      background-position center\n      background-repeat no-repeat\n      background-size contain\n.info-wrapper-container\n  width 100vw\n  height calc(100vh - 64px - 160rpx)\n  .swiper-container\n    width 100%\n    height 100%\n    white-space nowrap\n</style>\n"
  },
  {
    "path": "src/others-page/pages/libraryPages/library-history.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <repeat for=\"{{historyBook}}\" key=\"index\" index=\"index\" item=\"item\">\n          <view class=\"hist-container\">\n            <view class=\"hist-header-container\" @tap=\"{{check[index]? 'checkDetails' : 'hideDetails'}}\" data-index=\"{{index}}\">\n              <view class=\"hist-title\">{{item.name}}</view>\n              <image class=\"button-down\" src=\"https://static.airbob.org/under-graduate/image/score/button_down.png\" animation=\"{{spin[index]}}\">\n            </view>\n            <view class=\"hist-info-container\" id=\"histbook{{index}}\" animation=\"{{show[index]}}\">\n              <view class=\"hist-item\">借书日期：{{item.borrowDate}}</view>\n                <view class=\"hist-item\">还书日期：{{item.returnDate }}</view>\n                <view class=\"hist-item\">借书地点：{{item.location}}</view>\n              </view>\n          </view>\n        </repeat>\n        <view class=\"hist-pic-container\" wx:if=\"{{noHist}}\">\n          <image class=\"hist-emptyPic\" src=\"https://static.airbob.org/under-graduate/pic_empty.png\">\n          <view>你好像从未借书，快去图书馆淘一淘！</view>\n        </view>\n      </view>\n   </view>\n  </BaseContainer>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  import BaseContainer from \"@/components/baseContainer\";\n  import { checkBookHistory } from \"@/api/library\";\n  import { mockCheckBookHistory } from \"@/mock/library\";\n  export default class LibraryRecommened extends wepy.page {\n    config = {\n      navigationBarTitleText: \"历史借阅\"\n    };\n    data = {\n      navTitle: \"历史借阅\",\n      historyBook: [],\n      check: [],\n      spin: [],\n      show: [],\n      noHist: false,\n      visitorModeStatus: false\n    };\n    components = {\n      BaseContainer\n    };\n    methods = {\n      checkDetails(e) {\n        let index = e.currentTarget.dataset.index;\n        this.check[index] = false;\n        let show = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        let spin = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        show.height(\"135rpx\").step();\n        spin.rotate(-90).step();\n        this.show[index] = show;\n        this.spin[index] = spin;\n        this.$apply();\n      },\n      hideDetails(e) {\n        const index = e.currentTarget.dataset.index;\n        this.check[index] = true;\n        let show = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        let spin = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        show.height(0).step();\n        spin.rotate(0).step();\n        this.spin[index] = spin.export();\n        this.show[index] = show.export();\n        this.$apply();\n      }\n    };\n    init() {\n      wepy.showLoading({\n        title: \"加载中\"\n      });\n      let ifCheckBookHistory = this.visitorModeStatus\n        ? mockCheckBookHistory()\n        : checkBookHistory();\n      ifCheckBookHistory.then(res => {\n        if (res.data && res.data.data) {\n          this.historyBook = res.data.data;\n          if (!this.historyBook.length) {\n            this.noHist = true;\n          }\n          for (let i = 0; i < this.historyBook.length; i++) {\n            this.check.push(true);\n            this.show.push({});\n            this.spin.push({});\n          }\n          this.$apply();\n        }\n        wepy.hideLoading();\n      });\n    }\n    onLoad() {\n      this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n      this.init();\n    }\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  width 100vw\n  height 100%\n  color #353535\n  .hist-container\n    padding 26rpx 30rpx\n    width 665rpx\n    box-shadow 0rpx 0rpx 10rpx 0rpx rgba(0, 0, 0, 0.05)\n    margin 0 auto\n    margin-top 30rpx\n    box-sizing border-box\n    border-radius 20rpx\n    .hist-header-container\n      display flex\n      flex-direction row\n      justify-content space-between\n      align-items center\n      .hist-title\n        font-size 30rpx\n        font-weight bold\n        width 570rpx\n        overflow hidden\n        text-overflow ellipsis\n        white-space nowrap\n      .button-down\n        width 31rpx\n        height 16rpx\n    .hist-info-container\n      width 665rpx\n      height 0\n      font-size 24rpx\n      overflow hidden\n      .hist-item\n        line-height 45rpx\n  .hist-pic-container\n    height 100vh\n    width 100vw\n    position absolute\n    display flex\n    flex-direction column\n    align-items center\n    justify-content center\n    font-size 28rpx\n    color #999CA0\n\n</style>\n"
  },
  {
    "path": "src/others-page/pages/libraryPages/library-recommened.wpy",
    "content": "<template>\n  <view>\n    <!-- <view slot=\"qy-content\"> -->\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"divide-line\"></view>\n    <view class=\"recommened-container\">\n      <form class=\"recommened-form\" @submit=\"submitRecomened\">\n        <view class=\"recommened-title\">书名（必填）</view>\n        <input\n          type=\"text\"\n          class=\"recommened-input\"\n          name=\"bookname\"\n          placeholder=\"输入书名\"\n          placeholder-style=\"color: #999CA0\"\n          bindinput=\"inputBookName\"\n        >\n        <view class=\"recommened-title\">作者（必填）</view>\n        <input\n          type=\"text\"\n          class=\"recommened-input\"\n          name=\"author\"\n          placeholder=\"输入作者名字\"\n          placeholder-style=\"color: #999CA0\"\n          bindinput=\"inputAuthor\"\n        >\n        <view class=\"recommened-title\">出版社</view>\n        <input\n          type=\"text\"\n          class=\"recommened-input\"\n          name=\"publisher\"\n          placeholder=\"输入出版社\"\n          placeholder-style=\"color: #999CA0\"\n        >\n        <view class=\"recommened-title\">出版年份</view>\n        <input\n          type=\"text\"\n          class=\"recommened-input\"\n          name=\"publishtime\"\n          placeholder=\"输入出版年份\"\n          placeholder-style=\"color: #999CA0\"\n        >\n        <view class=\"recommened-title\">ISBN</view>\n        <input\n          type=\"text\"\n          class=\"recommened-input\"\n          name=\"ISBN\"\n          placeholder=\"输入该书的ISBN号，如978-7-121-16072-1\"\n          placeholder-style=\"color: #999CA0\"\n        >\n        <view class=\"radio-group\">\n          <label class=\"recommened-title-inline\">语种</label>\n          <label class=\"radio\" wx:for=\"{{languages}}\" wx:for-item=\"lang\" wx:key=\"key\">\n            <icon type=\"success\" wx:if=\"{{lang.checked}}\" color=\"#000\" size=\"{{(winWidth/750)*30}}\"></icon>\n            <icon type=\"circle\" wx:else size=\"{{(winWidth/750)*30}}\"></icon>\n            <text\n              class=\"radio-group-text\"\n              data-lang-name=\"{{lang.name}}\"\n              @tap=\"selectLanguage\"\n            >{{lang.value}}</text>\n          </label>\n        </view>\n        <button\n          class=\"recommened-button\"\n          form-type=\"submit\"\n          style=\"background-image:url({{necessary?submitbtn.highlight:submitbtn.disabled}});\"\n          disabled=\"{{!necessary}}\"\n        >荐购</button>\n      </form>\n    </view>\n  </view>\n  <!-- </view> -->\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\nimport { recommendBook } from \"@/api/library\";\n\nexport default class LibraryRecommened extends wepy.page {\n  config = {\n    navigationBarTitleText: \"读者荐购\"\n  };\n  data = {\n    navTitle: \"读者荐购\",\n    winWidth: 0,\n    winHeight: 0,\n    languages: [\n      {\n        name: \"Chinese\",\n        value: \"中文\",\n        checked: true\n      },\n      {\n        name: \"Foreign\",\n        value: \"西文\",\n        checked: false\n      }\n    ],\n    lang: \"Chinese\",\n    submitbtn: {\n      highlight:\n        \"https://static.airbob.org/under-graduate/btn_next_highlight.png\",\n      disabled: \"https://static.airbob.org/under-graduate/btn_next_disable.png\"\n    },\n    hasBookName: false,\n    hasAuthor: false,\n    necessary: false,\n    bookname: \"\",\n    recommenedHistory: []\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  methods = {\n    selectLanguage(e) {\n      let checkedLang = e.target.dataset.langname;\n      var that = this;\n      for (var i = 0; i < this.languages.length; i++) {\n        if (that.languages[i].name === checkedLang) {\n          that.languages[i].checked = true;\n          that.lang = that.languages[i].name;\n        } else {\n          that.languages[i].checked = false;\n        }\n      }\n      that.$apply();\n    },\n    async submitRecomened(e) {\n      const that = this;\n      that.necessary = \"true\";\n      e.detail.value.language = that.lang;\n      that.bookname = e.detail.value.bookname;\n      if (that.recommenedHistory.indexOf(that.bookname) === -1) {\n        that.recommenedHistory.unshift(that.bookname);\n        wepy.setStorageSync(\"recommenedHistory\", that.recommenedHistory);\n        // 发送请求;\n        let data = {\n          bookName: e.detail.value.bookname,\n          authorName: e.detail.value.author,\n          press: e.detail.value.publisher,\n          year: e.detail.value.publishtime,\n          ISBN: e.detail.value.ISBN,\n          language: e.detail.value.language\n        };\n        recommendBook(data).then(res => {\n          if (res.data) {\n            wepy.navigateBack().then(res => {\n              wepy.showToast({\n                title: \"荐购成功\",\n                icon: \"success\",\n                duration: 2000\n              });\n            });\n          } else if (res.data.errMsg === \"荐购失败\") {\n            wepy.navigateBack().then(res => {\n              wepy.showToast({\n                title: \"荐购失败\",\n                duration: 2000\n              });\n            });\n          }\n        });\n      } else {\n        wepy.showToast({\n          title: \"请勿重复提交\",\n          icon: \"none\",\n          duration: 1000\n        });\n      }\n      that.$apply();\n    },\n    inputBookName(e) {\n      if (e.detail.value !== \"\") {\n        this.hasBookName = true;\n      } else {\n        this.hasBookName = false;\n      }\n    },\n    inputAuthor(e) {\n      if (e.detail.value !== \"\") {\n        this.hasAuthor = true;\n      } else {\n        this.hasAuthor = false;\n      }\n    }\n  };\n  watch = {};\n  computed = {\n    necessary() {\n      return this.hasBookName && this.hasAuthor;\n    }\n  };\n  onLoad() {\n    wepy.getSystemInfo().then(res => {\n      this.winWidth = parseInt(res.windowWidth);\n      this.winHeight = parseInt(res.windowHeight);\n    });\n    if (!wepy.getStorageSync(\"recommenedHistory\"))\n      wepy.setStorageSync(\"recommenedHistory\", []);\n    else this.recommenedHistory = wepy.getStorageSync(\"recommenedHistory\");\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.divide-line\n  width 750rpx\n  height 1rpx\n  background-color #999CA0\n.recommened-container\n  width 750rpx\n  .recommened-form\n    width 630rpx\n    margin 60rpx auto\n    font-size 30rpx\n    display flex\n    flex-direction column\n    justify-content flex-start\n    .recommened-title\n      width 630rpx\n      line-height 30rpx\n      height 30rpx\n      color #888888\n      font-weight bolder\n      margin-bottom 30rpx\n    .recommened-title-inline\n      color #888888\n      height 30rpx\n      line-height 30rpx\n      font-weight bolder\n    .recommened-input\n      width 630rpx\n      height 30rpx\n      color #353535\n      border-bottom 1px solid #999CA0\n      margin-bottom 70rpx\n    .radio-group\n      .radio\n        margin 0 40rpx\n        .radio-group-text\n          color #353535\n          margin 0 20rpx\n    .recommened-button\n      background-repeat no-repeat\n      background-position top center\n      background-size 605rpx 80rpx\n      width 605rpx\n      height 80rpx\n      font-size 30rpx\n      text-align center\n      line-height 80rpx\n      color #fff\n      margin 50rpx auto 0 auto\n      border transparent\n    .recommened-button::after\n      display none\n</style>\n"
  },
  {
    "path": "src/others-page/pages/libraryPages/library.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"图书馆\" :passwordModelOptions.sync=\"passwordModelOptions\">\n    <view slot=\"qy-content\">\n      <view class=\"cover\" hidden=\"{{!showModal}}\" animation=\"{{coverAnimation}}\"></view>\n      <view class=\"cover-modal\" hidden=\"{{!showModal}}\">\n        <view style=\"color:#353535;margin:40rpx 25rpx 20rpx 25rpx\">当欠费满10元时还书自动扣款，若欠费未满10元将在毕业前结清。你也可以前往图书馆自行缴费。</view>\n        <view style=\"height:2rpx;width:540rpx;background:#E3E3E3;margin-left:-20rpx\"></view>\n        <view style=\"color:#39C9FF;margin-top:5rpx;padding-top:30rpx\" @tap=\"understandTip\">知道了</view>\n      </view>\n      <view class=\"swiper-tab\">\n        <view class=\"swiper-tab-list {{currentTab==0?'active':''}}\" data-current=\"0\" @tap=\"switchNav\">已借书目</view>\n        <view class=\"swiper-tab-list {{currentTab==1?'active':''}}\" data-current=\"1\" @tap=\"switchNav\">书目检索</view>\n        <view class=\"swiper-tab-list {{currentTab==2?'active':''}}\" data-current=\"2\" @tap=\"switchNav\">座位查询</view>\n        <view animation=\"{{animationNav}}\" class=\"swiper-line\"></view>\n      </view>\n      <swiper id=\"hhh\" class=\"swiper-box\" current=\"{{currentTab}}\" duration=\"500\" display-multiple-items=\"1\" style=\"height:{{winHeight-38}}px\" bindchange=\"changeTab\">\n        <!-- 已借书目 -->\n        <swiper-item>\n          <view class=\"books-container\">\n            <scroll-view scroll-y=\"true\" enable-back-to-top=\"true\" style=\"height:{{winHeight-38}}px\">\n              <view class=\"books-head\" style=\"margin-bottom:{{arrears==0?'80rpx':'0'}}\">\n                <view class=\"books-num\">{{totalBooksNumber}}</view>\n                <view class=\"books-cnt\">次</view>\n              </view>\n              <view wx:if=\"{{arrears!=0}}\" class=\"books-tip\" @tap=\"showBooksTip\">\n                你已欠费{{arrears}}元\n                <image class=\"books-question\" src=\"https://static.airbob.org/under-graduate/library_pic_why.png\">\n              </view>\n              <view class=\"hist-container\" @tap=\"checkHistory\">\n                <view class=\"hist-title\">\n                  <span>历史借阅</span>\n                </view>\n                <image class=\"button-right\" src=\"https://static.airbob.org/under-graduate/image/score/button_down.png\">\n              </view>\n              <view wx:if=\"{{curBooksNum==0}}\" class=\"books-none-container\">\n                <image class=\"books-none-img\" src=\"https://static.airbob.org/under-graduate/pic_empty.png\">\n                  <view>你当前没有借书，快去图书馆淘一淘！</view>\n              </view>\n              <view class=\"books-list\" wx:if=\"{{curBooksNum>0}}\">\n                <repeat for=\"{{lendBooks}}\" key=\"key\" index=\"index\" item=\"item\">\n                  <view class=\"book-container\" style=\"border-bottom-left-radius:{{isTapIndex[index]? '0rpx' : '20rpx'}};border-bottom-right-radius:{{isTapIndex[index]? '0rpx' : '20rpx'}};\">\n                    <view class=\"book-info-all\">\n                      <view class=\"book-name\">{{item.bookname}}</view>\n                      <view class=\"book-info\">已续借{{item.renew}}次</view>\n                      <view class=\"book-info\" style=\"white-space:nowrap\">\n                        应还日期：{{item.DDL}}\n                        <span style=\"color:#FFB737\" wx:if=\"{{item.leftDDL<=10&&item.leftDDL>=0}}\">据归还还有{{item.leftDDL}}天，请及时归还！</span>\n                      </view>\n                    </view>\n                    <image data-index=\"{{index}}\" data-name=\"{{item.marc_no}}\" class=\"button-updown\" src=\"https://static.airbob.org/under-graduate/image/score/button_down.png\" @tap=\"{{hide[index]? 'showBookDetails' : 'hideBookDetails'}}\" animation=\"{{spin[index]}}\">\n                  </view>\n                  <view class=\"book-detail-container\" animation=\"{{showOff[index]}}\">\n                    <view class=\"book-detail-info-all\" id=\"lendbook{{index}}\">\n                      <view class=\"book-info\">书名: {{item.bookname}}</view>\n                      <view class=\"book-info\">作者: {{item.author}}</view>\n                      <view class=\"book-info\">出版社: {{item.publishers}}</view>\n                      <view class=\"book-info\">所属分类: {{item.category}}</view>\n                      <view class=\"book-info\">ISBN: {{item.ISBN}}</view>\n                      <view class=\"book-info\">价格: {{item.price}}</view>\n                      <view class=\"book-info\">简介: {{item.summary}}</view>\n                    </view>\n                  </view>\n                </repeat>\n              </view>\n              <view wx:if=\"{{curBooksNum>0}}\" class=\"button-renew\" style=\"background-image:url({{renewAll?renewbtn.highlight:renewbtn.disabled}});\" @tap=\"renewBooks\">一键续借</view>\n            </scroll-view>\n          </view>\n        </swiper-item>\n        <!-- 书目检索 -->\n        <swiper-item>\n          <view class=\"search-container\">\n            <scroll-view scroll-y=\"true\" enable-back-to-top=\"true\" style=\"height:{{winHeight-38}}px\" bindscrolltolower=\"loadMoreBooks\">\n              <view class=\"search-bar-container\">\n                <view class=\"search-bar\">\n                  <view class=\"search-placeholder-all\" hidden=\"{{hasInput}}\" @tap=\"clearPlaceHolder\">\n                    <image src=\"https://static.airbob.org/under-graduate/%E6%90%9C%E7%B4%A2.png\" class=\"search-icon\">\n                      <view class=\"search-placeholder\">输入书名/作者/关键词</view>\n                  </view>\n                  <input type=\"text\" class=\"search-input\" confirm-type=\"search\" focus=\"{{hasInput}}\" @input=\"search\" value=\"{{key}}\" bindconfirm=\"confirmSearch\">\n                </view>\n              </view>\n              <view class=\"search-recommend\" hidden=\"{{emptyResult||hasResult}}\">\n                <view class=\"search-recommend-title\">热门推荐</view>\n                <view class=\"search-recommend-content\">\n                  <repeat for=\"{{recomends}}\" key=\"key\" index=\"index\" item=\"book\">\n                    <view class=\"search-recommend-book\" @tap=\"quickSearch\" data-name=\"{{book.name}}\">{{book.name}}</view>\n                  </repeat>\n                </view>\n              </view>\n              <view class=\"search-no-result\" style=\"display:{{emptyResult?'flex':'none'}};flex-direction column;\">\n                <image class=\"search-no-result-pic\" src=\"https://static.airbob.org/under-graduate/pic_empty.png\">\n                  <view class=\"search-no-result-tips\">没有找到这本书，你可以推荐图书馆购买哦</view>\n                  <view class=\"search-no-result-recom\" @tap=\"goToRecomened\">进行读者荐购</view>\n              </view>\n              <view class=\"search-result\" hidden=\"{{!hasResult}}\">\n                <repeat for=\"{{searchResult}}\" key=\"key\" index=\"index\" item=\"item\">\n                  <view class=\"search-result-container\" style=\"border-bottom-left-radius:{{isTapIndexS[index]? '0rpx' : '20rpx'}};border-bottom-right-radius:{{isTapIndexS[index]? '0rpx' : '20rpx'}};border-bottom:{{isTapIndexS[index]? 'none' : '1rpx solid rgba(0,0,0,0.1)'}}\">\n                    <view class=\"search-info-all\">\n                      <view class=\"search-book-name\">{{item.bookname}}</view>\n                      <view class=\"search-info-item\">作者: {{item.author}}</view>\n                      <view class=\"search-info-item\">出版社: {{item.publishers}}</view>\n                      <view class=\"search-info-item\">索书号: {{item.callno}}</view>\n                      <view class=\"search-info-item\">可借本数: {{item.leftBookNum}}</view>\n                    </view>\n                    <image data-index=\"{{index}}\" data-name=\"{{item.marc_no}}\" class=\"search-button-updown\" src=\"https://static.airbob.org/under-graduate/image/score/button_down.png\" @tap=\"{{hideS[index]? 'showSearchedBookDetails' : 'hideSearchedBookDetails'}}\" animation=\"{{spinS[index]}}\">\n                  </view>\n                  <view class=\"search-detail-container\" animation=\"{{showOffS[index]}}\" style=\"border-bottom:{{isTapIndexS[index]? '1rpx solid rgba(0,0,0,0.1)' : 'none'}}\">\n                    <view class=\"search-detail-info-all\" id=\"searchbook{{index}}\">\n                      <repeat for=\"{{item.positionDetail}}\" key=\"key\" item=\"item\">\n                        <view class=\"search-info-item\">图书位置: {{item.position}}</view>\n                        <view class=\"search-info-item\">索书号: {{item.callno}}</view>\n                        <view class=\"search-info-item\">状态: {{item.status}}</view>\n                        <view style=\"height:20rpx; width: 590rpx\"></view>\n                      </repeat>\n                      <view class=\"search-info-divide\"></view>\n                      <view class=\"search-info-item\">所属分类: {{item.category}}</view>\n                      <view class=\"search-info-item\">ISBN: {{item.ISBN}}</view>\n                      <view class=\"search-info-item\">价格: {{item.price}}</view>\n                      <view class=\"search-info-item\">简介: {{item.summary}}</view>\n                    </view>\n                  </view>\n                </repeat>\n              </view>\n            </scroll-view>\n          </view>\n        </swiper-item>\n        <!-- 座位查询 -->\n        <swiper-item>\n          <view class=\"seats-container\">\n            <scroll-view scroll-y=\"true\" enable-back-to-top=\"true\" style=\"height:{{winHeight-38}}px\">\n              <view class=\"seats-head\"></view>\n              <view class=\"seats-divide\"></view>\n              <view class=\"seats-body\">\n                <repeat for=\"{{floors}}\" key=\"key\" index=\"index\" item=\"item\">\n                  <seats-card :lib.sync=\"item\"></seats-card>\n                </repeat>\n              </view>\n            </scroll-view>\n          </view>\n        </swiper-item>\n      </swiper>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport {\n  librarySearch,\n  alreadyBorrowBooksSum,\n  historicalBorrow,\n  bookArrears,\n  remainSeats,\n  hotBooks,\n  bookStore,\n  bookStoreAgain,\n  bookStoreContent\n} from \"@/api/library\";\nimport {\n  mockLibrarySearch,\n  mockAlreadyBorrowBooksSum,\n  mockHistoricalBorrow,\n  mockBookArrears,\n  mockRemainSeats,\n  mockHotBooks,\n  mockBookStore,\n  mockBookStoreAgain,\n  mockBookStoreContent\n} from \"@/mock/library\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport seatsCard from \"../../components/seats-card\";\nimport { changeSecretCode } from \"@/api/common\";\nimport JudgeStatus from \"@/mixins/module\";\n\nexport default class Library extends wepy.page {\n  config = {\n    navigationBarTitleText: \"图书馆\"\n  };\n  components = {\n    BaseContainer,\n    \"seats-card\": seatsCard\n  };\n  mixins = [JudgeStatus];\n  data = {\n    navTitle: \"图书馆\",\n    bindModalVisible: false,\n    bindInputPassword: \"\",\n    userInfo: {},\n    winWidth: 0,\n    winHeight: 0,\n    currentTab: 0,\n    arrears: 0,\n    totalBooksNumber: 0,\n    curBooksNum: 0,\n    searchedPage: 0,\n    showModal: false,\n    isTapIndex: [],\n    hide: [],\n    isTapIndexS: [],\n    hideS: [],\n    animationNav: {},\n    coverAnimation: {},\n    showOff: [],\n    spin: [],\n    showOffS: [],\n    spinS: [],\n    // 一件续借初始状态为可不可点击\n    renewAll: false,\n    hasInput: false,\n    hasResult: false,\n    emptyResult: false,\n    renewbtn: {\n      highlight:\n        \"https://static.airbob.org/under-graduate/btn_next_highlight.png\",\n      disabled: \"https://static.airbob.org/under-graduate/btn_next_disable.png\"\n    },\n    lendBooks: [],\n    recomends: [],\n    searchResult: [],\n    searchBookName: \"\",\n    floors: [\n      {\n        floor: \"二\",\n        rooms: []\n      },\n      {\n        floor: \"三\",\n        rooms: []\n      },\n      {\n        floor: \"四\",\n        rooms: []\n      },\n      {\n        floor: \"五\",\n        rooms: []\n      }\n    ],\n    visitorModeStatus: false,\n    passwordModelOptions: {\n      passwordModelProps: false,\n      placeholder: \"图书馆密码（默认学号）\",\n      refreshData: this.getHistoricalBorrowing,\n      bindInfo: {\n        username: wepy.getStorageSync(\"User\").studentId,\n        domainType: \"0\"\n      }\n    }\n  };\n  methods = {\n    switchNav(e) {\n      let chosen = e.target.dataset.current;\n      let cur = this.data.currentTab.toString();\n      if (chosen === cur) {\n        return false;\n      } else {\n        this.currentTab = chosen;\n      }\n      this.$apply();\n    },\n    changeTab(e) {\n      this.currentTab = e.detail.current;\n      if (this.currentTab === 1) {\n        this.getHotRecommandBooks();\n      }\n      if (this.currentTab === 0) {\n        this.onLoadRequests();\n      }\n      if (this.currentTab === 2) {\n        this.queryOverplusSeats();\n      }\n      this.$apply();\n    },\n    async showBooksTip() {\n      let that = this;\n      function go() {\n        return new Promise((resolve, reject) => {\n          resolve((that.showModal = true));\n        });\n      }\n      await go();\n      let coverAnimation = wepy.createAnimation({\n        duration: 500\n      });\n      coverAnimation.opacity(0.5).step();\n      that.coverAnimation = coverAnimation.export();\n      that.$apply();\n    },\n    understandTip(e) {\n      let coverAnimation = wepy.createAnimation({\n        duration: 0\n      });\n      coverAnimation.opacity(0).step();\n      this.coverAnimation = coverAnimation.export();\n      this.showModal = false;\n      this.$apply();\n    },\n    loadMoreBooks(e) {\n      if (!this.visitorModeStatus && this.searchResult.length !== 0) {\n        wepy.showLoading({\n          title: \"加载中\"\n        });\n        this.searchedPage++;\n        let ifMockBookStore = this.visitorModeStatus\n          ? mockBookStore(this.searchBookName, this.searchedPage)\n          : bookStore(this.searchBookName, this.searchedPage);\n        ifMockBookStore.then(res => {\n          let results = res.data.data;\n          if (res.data) {\n            // 判断是否有更多：请求的最后一个和当前搜索结果的最后一个相同\n            if (\n              results[results.length - 1].name ===\n              this.searchResult[this.searchResult.length - 1].bookname\n            ) {\n              wepy.hideLoading();\n              wepy.showToast({\n                title: \"没有更多了!\",\n                icon: \"none\",\n                duration: 1000\n              });\n            } else {\n              for (let i = 0; i < results.length; i++) {\n                let book = {};\n                book.bookname = results[i].name;\n                book.author = results[i].author;\n                book.publishers = results[i].press;\n                book.callno = results[i].callNumber;\n                book.leftBookNum = results[i].numbers;\n                book.marc_no = results[i].marc_no;\n                this.searchResult.push(book);\n                this.spinS.push({});\n                this.showOffS.push({});\n                this.isTapIndexS.push(false);\n                this.hideS.push(true);\n              }\n              this.$apply();\n              wepy.hideLoading();\n            }\n          }\n        });\n      }\n    },\n    async showBookDetails(e) {\n      let that = this;\n      let name = e.currentTarget.dataset.name;\n      let index = e.currentTarget.dataset.index;\n      wepy.showLoading({\n        title: \"加载中\"\n      });\n      async function addDetails(name, index) {\n        return new Promise((resolve, reject) => {\n          let ifMockBookStoreContent = that.visitorModeStatus\n            ? mockBookStoreContent(name)\n            : bookStoreContent(name);\n          ifMockBookStoreContent\n            .then(res => {\n              let detail = res.data.data;\n              that.lendBooks[index].category = detail.type;\n              that.lendBooks[index].ISBN = detail.isbn;\n              that.lendBooks[index].price = detail.price;\n              that.lendBooks[index].summary = detail.summary;\n              that.lendBooks[index].author = detail.author;\n              that.lendBooks[index].publishers = detail.press;\n              that.$apply();\n              return that.lendBooks[index];\n            })\n            .then(res => {\n              let query = wepy.createSelectorQuery();\n              let book = \"#lendbook\" + index;\n              query.select(book).boundingClientRect();\n              that.isTapIndex[index] = true;\n              that.hide[index] = false;\n              that.$apply();\n              query.exec(function(res) {\n                let hh = (750 / that.winWidth) * res[0].height + 30;\n                let showOff = wepy.createAnimation({\n                  duration: 300,\n                  timingFunction: \"ease\"\n                });\n                let spin = wepy.createAnimation({\n                  duration: 300,\n                  timingFunction: \"ease\"\n                });\n                showOff.height(hh + \"rpx\").step();\n                spin.rotate(-180).step();\n                that.showOff[index] = showOff;\n                that.spin[index] = spin;\n                that.$apply();\n              });\n              that.$apply();\n            });\n          that.$apply();\n          resolve(that.lendBooks[index]);\n        });\n      }\n      await addDetails(name, index);\n      wepy.hideLoading();\n    },\n    hideBookDetails(e) {\n      const { index } = e.currentTarget.dataset;\n      this.isTapIndex[index] = false;\n      this.hide[index] = true;\n      let query = wepy.createSelectorQuery();\n      let book = \"#lendbook\" + index;\n      query.select(book).boundingClientRect();\n      query.exec(res => {\n        let showOff = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        let spin = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        showOff.height(0).step();\n        spin.rotate(-360).step();\n        this.spin[index] = spin.export();\n        this.showOff[index] = showOff.export();\n        this.$apply();\n      });\n      this.$apply();\n    },\n    async showSearchedBookDetails(e) {\n      let that = this;\n      // 获取请求数据后再展开\n      let name = e.currentTarget.dataset.name;\n      let index = e.currentTarget.dataset.index;\n      wepy.showLoading({\n        title: \"加载中\"\n      });\n      function addDetails(name, index) {\n        return new Promise((resolve, reject) => {\n          // 发送请求, if执行成功，reslove()\n          let ifMockBookStoreContent = that.visitorModeStatus\n            ? mockBookStoreContent(name)\n            : bookStoreContent(name);\n          ifMockBookStoreContent\n            .then(res => {\n              let detail = res.data.data;\n              that.searchResult[index].category = detail.type;\n              that.searchResult[index].ISBN = detail.ISBN;\n              that.searchResult[index].price = detail.price;\n              that.searchResult[index].summary = detail.summary;\n              that.searchResult[index].author = detail.author;\n              that.searchResult[index].publishers = detail.press;\n              that.searchResult[index].ISBN = detail.isbn;\n              that.searchResult[index].positionDetail = [];\n              let positionDetail = detail.bookPositionModels;\n              for (let i = 0; i < positionDetail.length; i++) {\n                let pos = {};\n                pos.position = positionDetail[i].position;\n                pos.callno = positionDetail[i].callNumber;\n                pos.status = positionDetail[i].status;\n                that.searchResult[index].positionDetail.push(pos);\n              }\n              that.$apply();\n              return that.searchResult[index];\n            })\n            .then(res => {\n              let query = wepy.createSelectorQuery();\n              let book = \"#searchbook\" + index;\n              query.select(book).boundingClientRect();\n              that.isTapIndexS[index] = true;\n              that.hideS[index] = false;\n              that.$apply();\n              query.exec(function(res) {\n                that.$apply();\n                let hh = (750 / that.winWidth) * res[0].height + 30;\n                let showOff = wepy.createAnimation({\n                  duration: 300,\n                  timingFunction: \"ease\"\n                });\n                let spin = wepy.createAnimation({\n                  duration: 300,\n                  timingFunction: \"ease\"\n                });\n                showOff.height(hh + \"rpx\").step();\n                spin.rotate(-180).step();\n                that.spinS[index] = spin.export();\n                that.showOffS[index] = showOff.export();\n                that.$apply();\n              });\n              that.$apply();\n            });\n          that.$apply();\n          resolve(that.searchResult[index]);\n        });\n      }\n      await addDetails(name, index);\n      wepy.hideLoading();\n    },\n    hideSearchedBookDetails(e) {\n      let that = this;\n      let index = e.currentTarget.dataset.index;\n      that.isTapIndexS[index] = false;\n      that.hideS[index] = true;\n      let query = wepy.createSelectorQuery();\n      let book = \"#searchbook\" + index;\n      query.select(book).boundingClientRect();\n      query.exec(function(res) {\n        let showOff = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        let spin = wepy.createAnimation({\n          duration: 300,\n          timingFunction: \"ease\"\n        });\n        showOff.height(0).step();\n        spin.rotate(-360).step();\n        that.spinS[index] = spin.export();\n        that.showOffS[index] = showOff.export();\n        that.$apply();\n      });\n      that.$apply();\n    },\n    /**\n     * 续借 => 已借的书籍📚\n     */\n    async renewBooks(e) {\n      let that = this;\n      wepy.showLoading();\n      let ifMockBookStoreAgain = this.visitorModeStatus\n        ? mockBookStoreAgain()\n        : await bookStoreAgain();\n      ifMockBookStoreAgain\n        .then(res => {\n          let results = res.data.data;\n          if (res.data) {\n            for (let i = 0; i < results.length; i++) {\n              let bar = results[i].bar;\n              let status = results[i].result;\n              let tip = results[i].tip;\n              for (let j = 0; j < that.lendBooks.length; j++) {\n                // 匹配图书的条形码\n                if (bar === that.lendBooks[j].bar) {\n                  if (!status) {\n                    return tip;\n                  }\n                }\n              }\n            }\n          }\n          return \"200\";\n        })\n        .then(res => {\n          // 请求已借书目获取that.lendBooks[j].leftDDL 和 that.lendBooks[j].newDDL\n          if (res === \"200\") {\n            let ifMockAlreadyBorrowBooksSum = this.visitorModeStatus\n              ? mockAlreadyBorrowBooksSum()\n              : alreadyBorrowBooksSum();\n            ifMockAlreadyBorrowBooksSum.then(res => {\n              let results = res.data.data;\n              for (let i = 0; i < results.length; i++) {\n                let bar = results[i].bar;\n                // 此时获取的deadline为新的应还日期\n                let newDDL = results[i].deadline;\n                let leftDDL = results[i].leftTime;\n                let renew = results[i].renew_conut;\n                for (let j = 0; j < that.lendBooks.length; j++) {\n                  if (bar === that.lendBooks[j].bar) {\n                    that.lendBooks[j].DDL = newDDL;\n                    that.lendBooks[j].leftDDL = leftDDL;\n                    that.lendBooks[j].renew = renew;\n                  }\n                }\n              }\n              wepy.hideLoading();\n              wepy.showToast({\n                title: \"续借成功\",\n                icon: \"success\",\n                duration: 2000\n              });\n              that.$apply();\n              // resolve((that.renewAll = false));\n            });\n          } else {\n            wepy.showToast({\n              title: res,\n              icon: \"none\",\n              duration: 2000\n            });\n          }\n        });\n      that.$apply();\n    },\n    clearPlaceHolder(e) {\n      this.hasInput = true;\n      this.$apply();\n    },\n    getPlaceHolder(e) {\n      this.hasInput = false;\n      this.$apply();\n    },\n    search(e) {\n      // 仅仅改变palceholder\n      if (e.detail.value !== \"\") {\n        this.hasInput = true;\n      } else this.hasInput = false;\n      this.$apply();\n    },\n    confirmSearch(e) {\n      const { value } = e.detail;\n      this.searchResult = [];\n      this.find(value);\n      this.$apply();\n    },\n    goToRecomened(e) {\n      wepy.navigateTo({\n        url: \"library-recommened\"\n      });\n    },\n    quickSearch(e) {\n      const { name } = e.target.dataset;\n      this.searchResult = [];\n      this.find(name);\n      this.$apply();\n    },\n    bindCardPassword(e) {\n      this.bindInputPassword = e.detail.value;\n    }\n  };\n  /**\n   * 查询书籍接口\n   */\n  find(e) {\n    let name = e;\n    this.searchBookName = name;\n    // 搜索\"我要荐购\"则显示荐购，否则显示搜索结果\n    if (name === \"我要荐购\") {\n      this.hasResult = false;\n      this.emptyResult = true;\n    } else {\n      this.emptyResult = false;\n      this.hasResult = true;\n    }\n    // 请求数据\n    wepy.showLoading({\n      title: \"加载中\"\n    });\n    let ifMockHistoricalBorrow = this.visitorModeStatus\n      ? mockLibrarySearch(this.searchBookName, \"1\")\n      : librarySearch(this.searchBookName, \"1\");\n    ifMockHistoricalBorrow.then(res => {\n      this.searchedPage = 1;\n      const {\n        data: [...results],\n        success\n      } = res.data;\n      if (success) {\n        if (results.length === 0) {\n          this.hasResult = false;\n          this.emptyResult = true;\n          this.searchResult = [];\n          this.$apply();\n        } else {\n          for (let i = 0; i < results.length; i++) {\n            let book = {};\n            book.bookname = results[i].name;\n            book.author = results[i].author;\n            book.publishers = results[i].press;\n            book.callno = results[i].callNumber;\n            book.leftBookNum = results[i].numbers;\n            book.marc_no = results[i].marc_no;\n            this.searchResult.push(book);\n            this.spinS.push({});\n            this.showOffS.push({});\n            this.isTapIndexS.push(false);\n            this.hideS.push(true);\n          }\n          this.$apply();\n        }\n        wepy.hideLoading();\n      }\n    });\n    this.$apply();\n  }\n  watch = {\n    currentTab(newValue, oldValue) {\n      let lineAnimation = wepy.createAnimation({\n        duration: 500,\n        timingFunction: \"ease-in-out\"\n      });\n      let leftWidth = 40;\n      if (newValue === 0) {\n        leftWidth = 40;\n      } else if (newValue === 1) {\n        leftWidth = 312;\n      } else {\n        leftWidth = 590;\n      }\n      lineAnimation.left(leftWidth + \"rpx\").step();\n      this.animationNav = lineAnimation.export();\n      this.$apply();\n    },\n    bindingVisible(newValue, oldValue) {\n      if (!newValue) {\n        this.onLoadRequests();\n      }\n    }\n  };\n  computed = {\n    curBooksNum() {\n      return this.lendBooks.length;\n    }\n  };\n  /**\n   * 获取欠款金额（需模块绑定后使用）finish\n   */\n  getArrearMoney() {\n    let ifMockHistoricalBorrow = this.visitorModeStatus\n      ? mockBookArrears()\n      : bookArrears();\n    ifMockHistoricalBorrow.then(res => {\n      if (res.data) {\n        if (res.data.data.charAt(0) === \".\") this.arrears = \"0\" + res.data.data;\n        else this.arrears = res.data.data;\n      }\n      this.$apply();\n    });\n  }\n  /**\n   * 获取总借阅书本数（需模块绑定后使用）finish, 仅在此处判断密码更新。\n   */\n  getHistoricalBorrowing() {\n    let ifMockHistoricalBorrow = this.visitorModeStatus\n      ? mockHistoricalBorrow()\n      : historicalBorrow();\n    ifMockHistoricalBorrow.then(res => {\n      if (!res.data.success) {\n        this.passwordModelOptions.passwordModelProps = true;\n        this.$apply();\n      } else {\n        this.totalBooksNumber = res.data.data;\n      }\n      this.$apply();\n    });\n  }\n  /**\n   * 获取用户已借书目（需模块绑定后使用）\n   */\n  getAlreadyBorrowBooks() {\n    let ifMockAlreadyBorrowBooksSum = this.visitorModeStatus\n      ? mockAlreadyBorrowBooksSum()\n      : alreadyBorrowBooksSum();\n    ifMockAlreadyBorrowBooksSum.then(res => {\n      let results = res.data.data;\n      this.lendBooks = [];\n      if (res.data) {\n        for (let i = 0; i < results.length; i++) {\n          let lend = {};\n          lend.bookname = results[i].name;\n          lend.renew = results[i].renew_conut;\n          lend.DDL = results[i].deadline;\n          lend.leftDDL = results[i].leftTime;\n          lend.marc_no = results[i].marc_no;\n          lend.bar = results[i].bar;\n          this.lendBooks.push(lend);\n          this.spin.push({});\n          this.showOff.push({});\n          this.isTapIndex.push(false);\n          this.hide.push(true);\n        }\n        for (let i = 0; i < this.lendBooks.length; i++) {\n          if (this.lendBooks[i].leftDDL <= 0) {\n            this.renewAll = false;\n            break;\n          } else if (\n            parseInt(this.lendBooks[i].leftDDL) <= 10 &&\n            this.lendBooks[i].renew === \"0\" &&\n            parseInt(this.lendBooks[i].leftDDL) > 0\n          ) {\n            // 续借次数为0，且剩余天数小于10大于0存在可借图书。续借按钮高亮\n            this.renewAll = true;\n            break;\n          }\n        }\n      }\n      this.$apply();\n    });\n  }\n  /**\n   * 获取热门推荐\n   */\n  getHotRecommandBooks() {\n    wepy.showLoading({\n      title: \"加载中\"\n    });\n    let ifMockHotBooks = this.visitorModeStatus ? mockHotBooks() : hotBooks();\n    ifMockHotBooks.then(res => {\n      const { data } = res.data;\n      data.map((item, index) => {\n        this.recomends[index] = {\n          name: item,\n          id: index + 1\n        };\n      });\n      this.$apply();\n      wepy.hideLoading();\n    });\n  }\n  /**\n   * 获取剩余座位\n   */\n  queryOverplusSeats() {\n    wepy.showLoading({\n      title: \"加载中\"\n    });\n    let ifMockRemainSeats = this.visitorModeStatus\n      ? mockRemainSeats()\n      : remainSeats();\n    ifMockRemainSeats.then(res => {\n      let results = res.data.data;\n      for (let i = 0; i < 4; i++) {\n        this.floors[i].rooms = [];\n        this.$apply();\n      }\n      for (let i = 0; i < results.length; i++) {\n        let room = {};\n        room.name = results[i].place;\n        room.totalSeats = results[i].total;\n        room.curSeats = results[i].available;\n        if (results[i].location === \"二层\") {\n          this.floors[0].rooms.push(room);\n        } else if (results[i].location === \"三层\") {\n          this.floors[1].rooms.push(room);\n        } else if (results[i].location === \"四层\") {\n          this.floors[2].rooms.push(room);\n        } else if (results[i].location === \"五层\") {\n          this.floors[3].rooms.push(room);\n        }\n      }\n      this.$apply();\n      wepy.hideLoading();\n    });\n  }\n  /**\n   * 页面绑定模块后的一些请求\n   */\n  onLoadRequests() {\n    wepy.showLoading({\n      title: \"正在加载\"\n    });\n    this.getHistoricalBorrowing();\n    this.getAlreadyBorrowBooks();\n    this.getArrearMoney();\n    wepy.hideLoading();\n  }\n  async init() {\n    wepy.showLoading({\n      title: \"加载中\"\n    });\n    await this.onLoadRequests();\n    wepy.hideLoading();\n  }\n  onLoad(option) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(option.name).then(async () => {\n      wepy.getSystemInfo().then(res => {\n        this.winWidth = parseInt(res.windowWidth);\n        this.winHeight = parseInt(res.windowHeight);\n      });\n      if (option.page === \"search\") {\n        this.currentTab = 1;\n      } else if (option.page === \"seats\") {\n        this.currentTab = 2;\n      } else {\n        this.currentTab = 0;\n        this.init();\n      }\n      this.$apply();\n    });\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\n.cover\n  position fixed\n  width 100vw\n  height 100vh\n  background rgb(0, 0, 0)\n  opacity 0\n  z-index 1000\n.cover-modal\n  position absolute\n  margin 0 auto\n  width 500rpx\n  left 105rpx\n  padding 20rpx\n  top 40vh\n  background #fff\n  z-index 1000\n  border-radius 10rpx\n  font-size 28rpx\n  text-align center\n.swiper-tab\n  display flex\n  position relative\n  justify-content space-between\n  align-items center\n  text-align center\n  height 44rpx\n  padding 0 40rpx\n  padding-top 8.5rpx\n  padding-bottom 24rpx\n  border-bottom 2rpx solid #dddddd\n  .swiper-tab-list\n    font-size 30rpx\n    color #353535\n    transition color 0.5s\n  .active\n    color #39c9ff\n  .swiper-line\n    background-color #39c9ff\n    width 120rpx\n    height 5rpx\n    border-radius 8rpx\n    position absolute\n    bottom 16rpx\n    left 40rpx\n.swiper-box\n  .books-container\n    .books-head\n      width 750rpx\n      height 300rpx\n      text-align center\n      background-position center\n      background-image url('https://static.airbob.org/under-graduate/library_pic_banner.png')\n      background-repeat no-repeat\n      background-size contain\n      color #fff\n      display flex\n      justify-content center\n      align-items flex-end\n      .books-num\n        font-size 70rpx\n        margin-right 30rpx\n        margin-bottom 30rpx\n      .books-cnt\n        font-size 30rpx\n        margin-bottom 40rpx\n    .books-tip\n      color #E64340\n      font-size 24rpx\n      width 250rpx\n      margin-left 60rpx\n      margin-top 20rpx\n      margin-bottom 30rpx\n      .books-question\n        width 25rpx\n        height 25rpx\n        margin-left 10rpx\n    .books-none-container\n      width 750rpx\n      height 700rpx\n      padding-top 180rpx\n      text-align center\n      font-size 28rpx\n      color #999CA0\n      .books-none-img\n        width 400rpx\n        height 291rpx\n        margin-bottom 50rpx\n    .hist-container\n      width 665rpx\n      height 97rpx\n      display flex\n      flex-direction row\n      align-items center\n      justify-content space-between\n      border-radius 20rpx\n      margin 30rpx auto\n      padding 26rpx 30rpx\n      box-shadow 0rpx 0rpx 10rpx 0rpx rgba(0, 0, 0, 0.05)\n      box-sizing border-box\n      .hist-title\n        width 570rpx\n        span\n          font-size 30rpx\n          font-weight bold\n          color #353535\n      .button-right\n        width 31rpx\n        height 16rpx\n        transform rotate(-90deg)\n    .books-list\n      display flex\n      flex-direction column\n      align-items center\n      width 750rpx\n      .book-container\n        width 665rpx\n        min-height 180rpx\n        box-shadow 0rpx 0rpx 10rpx 0rpx rgba(0, 0, 0, 0.05)\n        border-radius 20rpx\n        margin-bottom 30rpx\n        display flex\n        flex-direction row\n        justify-content space-between\n        align-items center\n        padding 26rpx 30rpx\n        box-sizing border-box\n        .book-info-all\n          display flex\n          flex-direction column\n          align-items flex-start\n          font-size 24rpx\n          color #353535\n          line-height 45rpx\n          width 570rpx\n          .book-name\n            font-size 30rpx\n            font-weight bold\n        .button-updown\n          width 31rpx\n          height 16rpx\n      .book-detail-container\n        width 665rpx\n        height 0\n        overflow hidden\n        border-radius 0 0 20rpx 20rpx\n        font-size 24rpx\n        color #353535\n        margin-top -30rpx\n        margin-bottom 30rpx\n        z-index 1000\n        box-shadow 0rpx 0rpx 10rpx 0rpx rgba(0, 0, 0, 0.05)\n        .book-detail-info-all\n          border-top 1rpx solid #E3E3E3\n          display flex\n          flex-direction column\n          align-items flex-start\n          line-height 45rpx\n          margin 0rpx 30rpx 30rpx 30rpx\n          padding-top 30rpx\n    .button-renew\n      background-repeat no-repeat\n      background-position top center\n      background-size 605rpx 80rpx\n      width 605rpx\n      height 80rpx\n      font-size 30rpx\n      text-align center\n      line-height 80rpx\n      color #fff\n      margin 50rpx auto 15% auto\n  .search-container\n    .search-bar-container\n      width 750rpx\n      height 300rpx\n      .search-bar\n        height 60rpx\n        font-size 30rpx\n        position relative\n        top 50%\n        transform translateY(-50%)\n        .search-placeholder-all\n          color #999CA0\n          text-align center\n          height 60rpx\n          width 630rpx\n          position absolute\n          top 12rpx\n          left 50rpx\n          z-index 2\n          .search-icon\n            width 25rpx\n            height 25rpx\n            display inline-block\n          .search-placeholder\n            height 60rpx\n            padding 0 20rpx\n            display inline-block\n        .search-input\n          height 60rpx\n          width 630rpx\n          margin 0 auto\n          background #F5F5F5\n          color #353535\n          border-radius 60rpx\n          padding 0 30rpx\n    .search-recommend\n      width 750rpx\n      .search-recommend-title\n        text-align center\n        font-size 30rpx\n        font-weight bolder\n      .search-recommend-content\n        .search-recommend-book\n          width 630rpx\n          text-align center\n          margin 30rpx auto\n          color #39c9ff\n          font-size 24rpx\n          line-height 1.5em\n    .search-no-result\n      font-size 30rpx\n      display flex\n      flex-direction column\n      justify-content center\n      .search-no-result-pic\n        width 400rpx\n        height 300rpx\n        margin 100rpx auto\n      .search-no-result-tips\n        color #999CA0\n        width 630rpx\n        height 60rpx\n        margin 10rpx auto\n      .search-no-result-recom\n        background-color #39c9ff\n        width 260rpx\n        height 60rpx\n        margin 30rpx auto\n        border-radius 8rpx\n        text-align center\n        line-height 60rpx\n        color #fff\n    .search-result\n      width 750rpx\n      margin-bottom 120rpx\n      .search-result-container\n        width 675rpx\n        min-height 180rpx\n        border-radius 20rpx\n        margin 29rpx auto\n        border-top 1rpx solid rgba(0, 0, 0, 0.1)\n        border-right 1rpx solid rgba(0, 0, 0, 0.1)\n        border-left 1rpx solid rgba(0, 0, 0, 0.1)\n        font-size 24rpx\n        color #353535\n        display flex\n        align-items center\n        .search-info-all\n          width 590rpx\n          display flex\n          flex-direction column\n          align-items flex-start\n          font-size 24rpx\n          color #353535\n          line-height 45rpx\n          margin 30rpx 0rpx 30rpx 30rpx\n          .search-book-name\n            font-size 30rpx\n            font-weight bold\n        .search-button-updown\n          width 34rpx\n          height 20rpx\n      .search-detail-container\n        width 675rpx\n        height 0rpx\n        overflow hidden\n        border-right 1rpx solid rgba(0, 0, 0, 0.1)\n        border-left 1rpx solid rgba(0, 0, 0, 0.1)\n        border-radius 0 0 20rpx 20rpx\n        font-size 24rpx\n        color #353535\n        margin -29rpx auto 29rpx auto\n        .search-detail-info-all\n          width 590rpx\n          border-top 2rpx solid #dddddd\n          display flex\n          flex-direction column\n          align-items flex-start\n          line-height 45rpx\n          margin 0rpx 30rpx 30rpx 30rpx\n          padding-top 30rpx\n          .search-info-divide\n            width 590rpx\n            border 1rpx dashed #dddddd\n            margin-top 10rpx\n            margin-bottom 30rpx\n  .seats-container\n    .seats-head\n      width 750rpx\n      height 300rpx\n      background-position center\n      background-image url('https://static.airbob.org/under-graduate/library_seat_banner.png')\n      background-repeat no-repeat\n      background-size contain\n    .seats-divide\n      width 750rpx\n      height 20rpx\n      background-color rgb(245, 245, 245)\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 485rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n"
  },
  {
    "path": "src/others-page/pages/login.wpy",
    "content": "<template>\n  <view>\n    <view class=\"content\">\n      <view hidden=\"{{initFinish}}\" class=\"toggle-body {{centerBody}}\">\n        <view class=\"content-body\">\n          <view class=\"welcome-container\">\n            <view>\n              <view>欢迎使用</view>\n              <view>南邮小程序</view>\n            </view>\n            <view class=\"welcome-image\"></view>\n          </view>\n        </view>\n        <view class=\"content-body\">\n          <view class=\"input-container\">\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              src=\"https://static.airbob.org/under-graduate/image/png/login/phone.png\"\n            >\n            <input\n              type=\"number\"\n              @input=\"getNumber\"\n              class=\"input\"\n              placeholder=\"请输入手机号\"\n              maxlength=\"11\"\n            >\n          </view>\n          <view class=\"input-container\">\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              src=\"https://static.airbob.org/under-graduate/image/png/login/password.png\"\n            >\n            <input\n              type=\"{{isShowPassword ? 'text' : 'password'}}\"\n              @input=\"getPassword\"\n              class=\"input\"\n              placeholder=\"请输入小程序密码\"\n            >\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              @tap=\"togglePassword\"\n              src=\"{{isShowPassword ? 'https://static.airbob.org/under-graduate/image/png/login/showpassword.png' : 'https://static.airbob.org/under-graduate/image/png/login/hidepassword.png'}}\"\n            >\n          </view>\n          <view class=\"forget-password\" @tap=\"forgetPassword\">忘记密码</view>\n          <view class=\"login-btn {{isLogining ? 'btn-disabled' : ''}}\" @tap=\"goLogin\">登录</view>\n          <view class=\"login-choice\">\n            <view class=\"login-toggle\" @tap=\"toggleStep\">还没注册？点这里</view>\n            <view class=\"login-toggle\" @tap=\"toggleVisitor\">游客模式</view>\n          </view>\n        </view>\n        <view class=\"content-body\">\n          <view class=\"input-container\">\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              src=\"https://static.airbob.org/under-graduate/image/png/login/phone.png\"\n            >\n            <input\n              type=\"number\"\n              @input=\"getNumber\"\n              class=\"input\"\n              placeholder=\"请输入手机号\"\n              maxlength=\"11\"\n            >\n          </view>\n          <view class=\"input-container\">\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              src=\"https://static.airbob.org/under-graduate/image/png/login/verification.png\"\n            >\n            <input\n              type=\"number\"\n              @input=\"getVertication\"\n              class=\"input\"\n              placeholder=\"请输入验证码\"\n              maxlength=\"6\"\n            >\n            <button\n              open-type=\"{{flag ? 'getUserInfo' : ''}}\"\n              @getuserinfo=\"onGotUserInfo\"\n              class=\"input-after {{flag ? '' : 'btn-disabled'}}\"\n              @tap=\"fetchVertication\"\n            >{{verticationMsg}}</button>\n          </view>\n          <view class=\"login-btn {{isInputing ? 'btn-disabled' : ''}}\" @tap=\"checkPhoneNumber\">下一步</view>\n          <view class=\"login-agreement\">\n            <image\n              class=\"obey\"\n              @tap=\"obeyPro\"\n              src=\"{{!obeyed ? 'https://static.airbob.org/under-graduate/image/png/login/unchoose.png' : 'https://static.airbob.org/under-graduate/image/png/login/chosen.png'}}\"\n              mode=\"aspectFill\"\n            >我已阅读并遵守\n            <view class=\"agreement-url\">\n              <navigator url=\"./personalPages/protocol\" hover-class=\"navigator-hover\">南邮小程序用户协议</navigator>\n            </view>\n          </view>\n          <view class=\"login-toggle\" @tap=\"toggleStep\">已经注册？直接登录</view>\n        </view>\n        <view class=\"content-body\">\n          <view class=\"input-container\">\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              src=\"https://static.airbob.org/under-graduate/%E6%AD%A3%E6%96%B9%E8%B4%A6%E5%8F%B7.png\"\n            >\n            <input type=\"text\" @input=\"getZfAccount\" class=\"input\" placeholder=\"请输入学号\">\n          </view>\n          <view class=\"input-container\">\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              src=\"https://static.airbob.org/under-graduate/%E5%AF%86%E7%A0%81.png\"\n            >\n            <input\n              type=\"{{isShowPassword ? 'text' : 'password'}}\"\n              @input=\"getPassword\"\n              class=\"input\"\n              placeholder=\"请输入正方密码\"\n            >\n            <image\n              mode=\"widthFix\"\n              class=\"input-image\"\n              @tap=\"togglePassword\"\n              src=\"{{isShowPassword ? 'https://static.airbob.org/under-graduate/image/png/login/showpassword.png' : 'https://static.airbob.org/under-graduate/image/png/login/hidepassword.png'}}\"\n            >\n          </view>\n          <view class=\"login-btn {{isBinding ? 'btn-disabled' : ''}}\" @tap=\"goBind\">绑定</view>\n        </view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport Input from \"@/components/qy-input\";\nimport {\n  login,\n  sendSms,\n  checkCaptcha,\n  register,\n  getToken,\n  getUserInfo\n} from \"@/api/common\";\n\nexport default class Login extends wepy.page {\n  config = {\n    navigationBarTitleText: \"\",\n    navigationBarBackgroundColor: \"#95EDFF\"\n  };\n  components = {\n    \"qy-input\": Input\n  };\n\n  data = {\n    userInfo: {},\n    userId: \"\",\n    token: \"\",\n    isRegister: true,\n    obeyed: true,\n    verticationMsg: \"获取验证码\",\n    phoneNumber: \"\",\n    vertication: \"\",\n    password: \"\",\n    zfAccount: \"\",\n    flag: true,\n    isShowPassword: false,\n    step: 0,\n    initFinish: true,\n    stepTimeout: null\n  };\n\n  methods = {\n    onGotUserInfo(e) {\n      this.userInfo = e.detail.userInfo;\n      wepy.setStorageSync(\"userInfo\", e.detail.userInfo);\n    },\n    getNumber(e) {\n      this.phoneNumber = e.detail.value;\n    },\n    getPassword(e) {\n      this.password = e.detail.value;\n    },\n    getZfAccount(e) {\n      this.zfAccount = e.detail.value;\n    },\n    getVertication(e) {\n      this.vertication = e.detail.value;\n    },\n    togglePassword() {\n      this.isShowPassword = !this.isShowPassword;\n    },\n    obeyPro() {\n      this.obeyed = !this.obeyed;\n    },\n    async fetchVertication() {\n      if (this.phoneNumber.trim().length === 0) {\n        this.$parent.showTip(\"手机号不能为空\");\n      } else {\n        // 60s\n        if (this.flag) {\n          await this.getTokenAndUserInfo();\n          this.flag = false;\n          let count = 60;\n          let t = setInterval(() => {\n            this.verticationMsg = `${count--}s`;\n            if (count === 0) {\n              clearInterval(t);\n              this.verticationMsg = \"获取验证码\";\n              this.flag = true;\n            }\n            this.$apply();\n          }, 1000);\n          sendSms(this.phoneNumber).then(res => {\n            if (!res.data) {\n              this.$parent.showTip(res.data.errMsg);\n            }\n          });\n        }\n      }\n    },\n    checkPhoneNumber() {\n      if (!this.isInputing) {\n        checkCaptcha(this.vertication).then(res => {\n          if (res.data) {\n            // 验证码正确\n            if (this.obeyed) {\n              // 如果遵守协议, 跳转到绑定正方账号密码\n              this.step = 3;\n              this.password = \"\";\n              this.$apply();\n            } else {\n              this.$parent.showTip(\"您还没有同意用户协议呢\");\n            }\n          } else {\n            this.$parent.showTip(\"验证码错误\");\n          }\n        });\n      }\n    },\n    async goLogin() {\n      wepy.showLoading({\n        title: \"加载中\"\n      });\n      if (!this.isLogining) {\n        try {\n          await this.getTokenAndUserInfo();\n          const res = await login(\n            this.phoneNumber,\n            this.password,\n            wepy.$appConfig.fromQQ\n          );\n          await wepy.setStorageSync(\n            \"indexIcon\",\n            this.$parent.globalData.modules.slice(0, 8)\n          );\n          wepy.hideLoading();\n          if (res.data) {\n            wepy.reLaunch({\n              url: \"../../pages/index\"\n            });\n          }\n        } catch (e) {\n          console.log(e);\n        }\n      }\n    },\n    async goBind() {\n      if (!this.isBinding) {\n        wepy.showLoading({\n          title: \"加载中\"\n        });\n        register(\n          this.phoneNumber,\n          this.zfAccount,\n          this.password,\n          this.userInfo.avatarUrl,\n          this.userInfo.gender,\n          this.userInfo.nickName\n        ).then(res => {\n          wepy.hideLoading();\n          if (res.data) {\n            login(this.phoneNumber, this.password, wepy.$appConfig.fromQQ).then(\n              response => {\n                if (response.data) {\n                  wepy.setStorageSync(\n                    \"indexIcon\",\n                    this.$parent.globalData.modules.slice(0, 8)\n                  );\n                  wepy.reLaunch({\n                    url: \"../../pages/index\"\n                  });\n                } else {\n                  this.$parent.showTip(\"登录失败\");\n                }\n              }\n            );\n          } else {\n            this.$parent.showTip(\"学号或正方教务系统密码错误，请核对重试\");\n            this.$apply();\n          }\n        });\n      }\n    },\n    toggleStep() {\n      if (this.step === 1) {\n        this.step = 2;\n      } else if (this.step === 2) {\n        this.step = 1;\n      }\n      this.$apply();\n    },\n    toggleVisitor() {\n      wepy.reLaunch({ url: \"../../pages/index\" });\n      wepy.$store.dispatch({ type: `ENTER_VISITOR_MODE` });\n    },\n    forgetPassword() {\n      wepy.navigateTo({ url: \"./personalPages/change-password\" });\n    }\n  };\n\n  events = {\n    TapFunc: (e, tap) => {}\n  };\n\n  computed = {\n    isLogining() {\n      return (\n        this.phoneNumber.trim().length !== 11 ||\n        this.password.trim().length === 0\n      );\n    },\n    isInputing() {\n      return (\n        this.phoneNumber.trim().length !== 11 ||\n        this.vertication.trim().length !== 6\n      );\n    },\n    isBinding() {\n      return (\n        this.zfAccount.trim().length === 0 || this.password.trim().length === 0\n      );\n    },\n    centerBody() {\n      switch (this.step) {\n        case 0:\n          return \"welcome-step\";\n        case 1:\n          return \"login-step\";\n        case 2:\n          return \"sms-step\";\n        case 3:\n          return \"bind-step\";\n        default:\n          return \"login-step\";\n      }\n    }\n  };\n\n  onLoad({ step }) {\n    if (step) {\n      this.step = Number(step);\n    } else {\n      this.stepTimeout = setTimeout(() => {\n        this.step = 1;\n        this.$apply();\n      }, 2800);\n    }\n  }\n  onUnload() {\n    clearTimeout(this.stepTimeout);\n  }\n  getTokenAndUserInfo = async () => {\n    const { code } = await wepy.login();\n    const getTokenResponse = await getToken(code, wepy.$appConfig.fromQQ);\n    if (getTokenResponse !== null) {\n      this.token = getTokenResponse.data.data;\n      wepy.setStorageSync(\"token\", this.token);\n    } else {\n      this.$parent.showTip();\n    }\n  };\n}\n</script>\n<style lang=\"stylus\" scoped>\nvendors = official\nanimation-time = 2.5s\n@import '../../css/global-style'\n.content\n  position absolute\n  top 0\n  left 0\n  width 100vw\n  height 100vh\n  z-index 0\n  background url('https://static.airbob.org/under-graduate/image/png/login/background.png') no-repeat\n  background-size cover\n  overflow hidden\n.toggle-body\n  display flex\n  position absolute\n  top 43%\n  height 57%\n  width 400vw\n  transition all 0.5s\n.welcome-step\n  transform translateX(0vw)\n.login-step\n  transform translateX(-100vw)\n.sms-step\n  transform translateX(-200vw)\n.bind-step\n  transform translateX(-300vw)\n.content-body\n  width 100vw\n.welcome-container\n  height 100%\n  display flex\n  font-family PingFangSC-Light\n  font-size 90rpx\n  line-height 108rpx\n  color #9b9b9b\n  flex-direction column\n  justify-content space-between\n  align-items center\n  .welcome-image\n    background-image url('https://static.airbob.org/under-graduate/welcome-borad.png')\n    background-repeat no-repeat\n    background-position bottom\n    background-size contain\n    width 450rpx\n    height 388rpx\n.input-container\n  display flex\n  width 586rpx\n  margin 30rpx auto 0\n  padding-bottom 6rpx\n  border-bottom 1rpx solid #F2F2F2\n  align-items center\n  .input-image\n    width 26rpx\n    height 40rpx\n    margin-right 20rpx\n  .input\n    font-size 28rpx\n    flex 1\n  .input-after\n    width 160rpx\n    height 45rpx\n    margin-left 20rpx\n    padding 0\n    background linear-gradient(-225deg, #ABDCFF 0%, #6AE4FF 100%)\n    color #fff\n    font-size 24rpx\n    line-height 45rpx\n    text-align center\n    border-radius 30rpx\n    &:after\n      border 0\n.input-placeholder\n  color #888\n.login-btn\n  height 74rpx\n  width 586rpx\n  margin 30rpx auto 40rpx\n  line-height 74rpx\n  color #fff\n  font-size 32rpx\n  text-align center\n  border-radius 30rpx\n  background linear-gradient(-225deg, #ABDCFF 0%, #6AE4FF 100%)\n.login-agreement\n  display flex\n  justify-content center\n  font-size 20rpx\n  .obey\n    width 30rpx\n    height 30rpx\n    margin-right 20rpx\n    color #353535\n.agreement-url\n  text-decoration underline\n  color #47CFF5\n.login-choice\n  width 320rpx\n  margin 0 auto\n  display flex\n  justify-content space-between\n.login-toggle\n  margin-top 40rpx\n  font-size 20rpx\n  color #47CFF5\n  text-align center\n.forget-password\n  padding-top 30rpx\n  font-size 20rpx\n  color #47CFF5\n  text-align right\n  width 586rpx\n  margin 0 auto\n.btn-disabled\n  background #D0F5FF !important\n</style>\n"
  },
  {
    "path": "src/others-page/pages/more.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <qy-tip :on.sync=\"tipsOn\" :content.sync=\"tipsContent\"/>\n    <view style=\"position:relative;\">\n      <view class=\"index-application\">\n        <view class=\"application\">首页应用</view>\n        <view hidden=\"{{showEdit}}\">\n          <repeat for=\"{{indexIcon}}\" key=\"key\" index=\"index\" item=\"item\">\n            <view\n              class=\"application-image\"\n              style=\"background-image:url('{{item.src}}');width:{{IconWidth}}rpx;height:90rpx;\"\n            ></view>\n          </repeat>\n        </view>\n        <view hidden=\"{{!showEdit}}\" class=\"edit-index\">（首页需放置7个功能入口）</view>\n        <view class=\"edit\" @tap=\"toEdit\">{{!showEdit ? '编辑' : '完成'}}</view>\n      </view>\n      <view class=\"classification\" id=\"show-index\" animation=\"{{showDetailAnimation}}\">\n        <view class=\"classification-detail\">\n          <repeat for=\"{{indexIcon}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"detail-info\">\n              <view\n                class=\"detail-info-container\"\n                style=\"background:#F5F5F5;\"\n                animation=\"{{deleteAnimation[index]}}\"\n              >\n                <view class=\"detail-image\" style=\"position:relative;\">\n                  <image src=\"{{item.src}}\" mode=\"aspectFit\" class=\"detail-image\">\n                  <view\n                    class=\"add-or-delete\"\n                    style=\"background-image:url('https://static.airbob.org/under-graduate/more/delete.png')\"\n                    @tap.stop=\"deleteIcon\"\n                    data-index=\"{{index}}\"\n                    data-item=\"{{item}}\"\n                  ></view>\n                </view>\n                <view class=\"detail-name\">{{item.name}}</view>\n              </view>\n            </view>\n          </repeat>\n        </view>\n      </view>\n      <view style=\"width:750rpx;height:20rpx;background:#F5F5F5;\"></view>\n      <view class=\"classification\">\n        <view class=\"classification-title\">图书馆</view>\n        <view class=\"classification-detail\">\n          <repeat for=\"{{details.library}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"detail-info\">\n              <view animation=\"{{deleteIconAnimation[item.id]}}\">\n                <view\n                  class=\"detail-info-container\"\n                  animation=\"{{animationData}}\"\n                  @tap.stop=\"nav\"\n                  data-item=\"{{item}}\"\n                >\n                  <view class=\"detail-image\" style=\"position:relative;\">\n                    <image src=\"{{item.src}}\" mode=\"aspectFit\" class=\"detail-image\">\n                    <view class=\"image-red-dot\" hidden=\"{{ !item.isNew||showEdit }}\"></view>\n                    <view\n                      hidden=\"{{!showEdit}}\"\n                      @tap=\"changeStatus\"\n                      data-item=\"{{item}}\"\n                      class=\"add-or-delete\"\n                      style=\"background-image:url('{{item.isIndex ? 'https://static.airbob.org/under-graduate/more/delete.png' : 'https://static.airbob.org/under-graduate/more/add.png'}}')\"\n                    ></view>\n                  </view>\n                  <view class=\"detail-name\">{{item.name}}</view>\n                </view>\n              </view>\n            </view>\n          </repeat>\n        </view>\n      </view>\n      <view class=\"classification\">\n        <view class=\"classification-title\">一卡通</view>\n        <view class=\"classification-detail\">\n          <repeat for=\"{{details.card}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"detail-info\">\n              <view animation=\"{{deleteIconAnimation[item.id]}}\">\n                <view\n                  class=\"detail-info-container\"\n                  animation=\"{{animationData}}\"\n                  @tap.stop=\"nav\"\n                  data-item=\"{{item}}\"\n                >\n                  <view class=\"detail-image\" style=\"position:relative;\">\n                    <image src=\"{{item.src}}\" mode=\"aspectFit\" class=\"detail-image\">\n                    <view class=\"image-red-dot\" hidden=\"{{ !item.isNew||showEdit }}\"></view>\n                    <view\n                      hidden=\"{{!showEdit}}\"\n                      @tap=\"changeStatus\"\n                      data-item=\"{{item}}\"\n                      class=\"add-or-delete\"\n                      style=\"background-image:url('{{item.isIndex ? 'https://static.airbob.org/under-graduate/more/delete.png' : 'https://static.airbob.org/under-graduate/more/add.png'}}')\"\n                    ></view>\n                  </view>\n                  <view class=\"detail-name\">{{item.name}}</view>\n                </view>\n              </view>\n            </view>\n          </repeat>\n        </view>\n      </view>\n      <view class=\"classification\">\n        <view class=\"classification-title\">学业相关</view>\n        <view class=\"classification-detail\">\n          <repeat for=\"{{details.course}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"detail-info\">\n              <view animation=\"{{deleteIconAnimation[item.id]}}\">\n                <view\n                  class=\"detail-info-container\"\n                  animation=\"{{animationData}}\"\n                  @tap.stop=\"nav\"\n                  data-item=\"{{item}}\"\n                >\n                  <view class=\"detail-image\" style=\"position:relative;\">\n                    <image src=\"{{item.src}}\" mode=\"aspectFit\" class=\"detail-image\">\n                    <view class=\"image-red-dot\" hidden=\"{{ !item.isNew||showEdit }}\"></view>\n                    <view\n                      hidden=\"{{!showEdit}}\"\n                      @tap=\"changeStatus\"\n                      data-item=\"{{item}}\"\n                      class=\"add-or-delete\"\n                      style=\"background-image:url('{{item.isIndex ? 'https://static.airbob.org/under-graduate/more/delete.png' : 'https://static.airbob.org/under-graduate/more/add.png'}}')\"\n                    ></view>\n                  </view>\n                  <view class=\"detail-name\">{{item.name}}</view>\n                </view>\n              </view>\n            </view>\n          </repeat>\n        </view>\n      </view>\n      <view class=\"classification\">\n        <view class=\"classification-title\">校园生活</view>\n        <view class=\"classification-detail\">\n          <repeat for=\"{{details.campus}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"detail-info\">\n              <view animation=\"{{deleteIconAnimation[item.id]}}\">\n                <view\n                  class=\"detail-info-container\"\n                  animation=\"{{animationData}}\"\n                  @tap.stop=\"nav\"\n                  data-item=\"{{item}}\"\n                >\n                  <view class=\"detail-image\" style=\"position:relative;\">\n                    <image src=\"{{item.src}}\" mode=\"aspectFit\" class=\"detail-image\">\n                    <view class=\"image-red-dot\" hidden=\"{{ !item.isNew||showEdit }}\"></view>\n                    <view\n                      hidden=\"{{!showEdit}}\"\n                      @tap=\"changeStatus\"\n                      data-item=\"{{item}}\"\n                      class=\"add-or-delete\"\n                      style=\"background-image:url('{{item.isIndex ? 'https://static.airbob.org/under-graduate/more/delete.png' : 'https://static.airbob.org/under-graduate/more/add.png'}}')\"\n                    ></view>\n                  </view>\n                  <view class=\"detail-name\">{{item.name}}</view>\n                </view>\n              </view>\n            </view>\n          </repeat>\n        </view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport { getModuleStatus } from \"@/api/common\";\nimport tip from \"@/components/qy-tip\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"更多\"\n  };\n  components = {\n    \"qy-tip\": tip,\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"更多\",\n    IconWidth: 0,\n    showEdit: false,\n    tipsOn: false,\n    tipsContent: \"\",\n    showDetailAnimation: {},\n    deleteIconAnimation: [],\n    deleteAnimation: [],\n    details: {\n      library: [\n        {\n          name: \"图书馆\",\n          src: \"https://static.airbob.org/under-graduate/more/library.png\",\n          isIndex: true,\n          id: 0,\n          path: \"../others-page/pages/libraryPages/library\",\n          module: \"图书馆\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"已借书目\",\n          src: \"https://static.airbob.org/under-graduate/more/borrow.png\",\n          isIndex: false,\n          id: 1,\n          path: \"../others-page/pages/libraryPages/library\",\n          module: \"图书馆\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"检索书目\",\n          src: \"https://static.airbob.org/under-graduate/more/retrieval.png\",\n          isIndex: false,\n          id: 2,\n          path: \"../others-page/pages/libraryPages/library\",\n          module: \"图书馆\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"座位查询\",\n          src: \"https://static.airbob.org/under-graduate/more/seat inquiry.png\",\n          isIndex: false,\n          id: 3,\n          path: \"../others-page/pages/libraryPages/library\",\n          module: \"图书馆\",\n          isOpen: true,\n          isNew: false\n        }\n      ],\n      card: [\n        {\n          name: \"一卡通\",\n          src: \"https://static.airbob.org/under-graduate/more/card.png\",\n          isIndex: true,\n          id: 4,\n          path: \"../campus-card-page/pages/campus-card-index\",\n          module: \"一卡通\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"校园卡充值\",\n          src: \"https://static.airbob.org/under-graduate/more/recharge.png\",\n          isIndex: false,\n          id: 5,\n          path: \"../campus-card-page/pages/campus-card-charge\",\n          module: \"一卡通\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"电费充值\",\n          src: \"https://static.airbob.org/under-graduate/more/electricity.png\",\n          isIndex: false,\n          id: 6,\n          path: \"../campus-card-page/pages/electric-charge\",\n          module: \"一卡通\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"校园网充值\",\n          src:\n            \"https://static.airbob.org/under-graduate/more/ campus network.png\",\n          isIndex: false,\n          id: 7,\n          path: \"../campus-card-page/pages/net-charge\",\n          module: \"一卡通\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"校园卡挂失\",\n          src:\n            \"https://static.airbob.org/under-graduate/more/report the loss.png\",\n          isIndex: false,\n          id: 8,\n          path: \"../campus-card-page/pages/campus-card-loss\",\n          module: \"一卡通\",\n          isOpen: true,\n          isNew: false\n        }\n      ],\n      course: [\n        {\n          name: \"成绩查询\",\n          src:\n            \"https://static.airbob.org/under-graduate/more/results query.png\",\n          isIndex: true,\n          id: 9,\n          path: \"../edu-admin-page/pages/score-inquire\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"体育部\",\n          src: \"https://static.airbob.org/under-graduate/more/sport.png\",\n          isIndex: true,\n          id: 10,\n          path: \"../others-edu-page/pages/pe-score\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"考试倒计时\",\n          src: \"https://static.airbob.org/under-graduate/more/exam.png\",\n          isIndex: false,\n          id: 11,\n          path: \"../edu-admin-page/pages/cut-down\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"等级考试\",\n          src:\n            \"https://static.airbob.org/under-graduate/more/rank examination.png\",\n          isIndex: false,\n          id: 12,\n          path: \"../edu-admin-page/pages/check-grade\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"补考查询\",\n          src: \"https://static.airbob.org/under-graduate/more/resit.png\",\n          isIndex: false,\n          id: 13,\n          path: \"../edu-admin-page/pages/supplement-and-tutorials\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"辅导课查询\",\n          src:\n            \"https://static.airbob.org/under-graduate/more/prenatal class.png\",\n          isIndex: false,\n          id: 14,\n          path: \"../edu-admin-page/pages/supplement-and-tutorials\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"GPA计算器\",\n          src: \"https://static.airbob.org/under-graduate/more/gpa.png\",\n          isIndex: true,\n          id: 15,\n          path: \"../others-edu-page/pages/GpaCalculator\",\n          module: \"一卡通\",\n          isOpen: true,\n          isNew: false\n        }\n      ],\n      campus: [\n        {\n          name: \"课表\",\n          src: \"https://static.airbob.org/under-graduate/more/timetable.png\",\n          isIndex: true,\n          id: 16,\n          path: \"../edu-admin-page/pages/course\",\n          module: \"一卡通\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"校历\",\n          src: \"https://static.airbob.org/under-graduate/more/calendar.png\",\n          isIndex: false,\n          id: 17,\n          path: \"../others-edu-page/pages/calendar\",\n          module: \"校历\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"自主学分\",\n          src: \"https://static.airbob.org/under-graduate/more/credit.png\",\n          isIndex: false,\n          id: 18,\n          path: \"../edu-admin-page/pages/credit\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"晨跑\",\n          src: \"https://static.airbob.org/under-graduate/more/run.png\",\n          isIndex: true,\n          id: 19,\n          path: \"../others-page/pages/run\",\n          module: \"晨跑\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"学费查询\",\n          src: \"https://static.airbob.org/under-graduate/more/tuition.png\",\n          isIndex: false,\n          id: 20,\n          path: \"../others-page/pages/tuition\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"社团招新\",\n          src: \"https://static.airbob.org/under-graduate/more/club.png\",\n          isIndex: false,\n          id: 21,\n          path: \"../others-page/pages/associationPages/association\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"问卷\",\n          src:\n            \"https://static.airbob.org/under-graduate/more/questionnaire.png\",\n          isIndex: false,\n          id: 22,\n          path:\n            \"../others-page/pages/questionnairePages/questionnaire-homepage\",\n          module: \"正方\",\n          isOpen: true,\n          isNew: false\n        },\n        {\n          name: \"校车\",\n          src:\n            \"https://static.airbob.org//under-graduate/bus/QjE2MDEyMzI3LWJ1cy5wbmc=\",\n          isIndex: false,\n          id: 23,\n          path: \"../others-page/pages/school-bus\",\n          module: \"校车\",\n          isOpen: true,\n          isNew: false\n        }\n        // {\n        //   name: \"认证\",\n        //   src: \"https://static.airbob.org/under-graduate/more/club.png\",\n        //   isIndex: false,\n        //   id: 23,\n        //   path: \"../others-page/pages/auth\",\n        //   module: \"正方\",\n        //   isOpen: true,\n        //   isNew: false\n        // }\n      ]\n    },\n    animationData: {},\n    indexIcon: [],\n    moreFunc: {},\n    fromIconListDeleteIndexIcon: {}\n  };\n  computed = {\n    functionalList() {\n      let length = wepy.getStorageSync(\"indexIcon\").length;\n      return wepy.getStorageSync(\"indexIcon\").slice(0, parseInt(length - 1));\n    }\n  };\n  methods = {\n    nav(e) {\n      if (!this.showEdit) {\n        let item = e.currentTarget.dataset.item;\n        let newModule = wepy.getStorageSync(\"newModule\");\n        if (item.isNew) {\n          for (let i in this.details) {\n            for (let j of this.details[i]) {\n              if (j.name === item.name) {\n                j.isNew = false;\n              }\n            }\n          }\n          for (let i in newModule) {\n            if (newModule[i].moduleName === item.name) {\n              newModule.splice(i, 1);\n              wepy.setStorageSync(\"newModule\", newModule);\n              break;\n            }\n          }\n          this.$apply();\n        }\n        if (item.name === \"检索书目\") {\n          this.$navigate({\n            url: `../${item.path}?page=search&name=图书馆`\n          });\n        } else if (item.name === \"座位查询\") {\n          this.$navigate({\n            url: `../${item.path}?page=seats&name=图书馆`\n          });\n        } else if (item.name === \"已借书目\") {\n          this.$navigate({\n            url: `../${item.path}?name=图书馆`\n          });\n        } else {\n          this.$navigate({\n            url: `../${item.path}?name=${item.name}`\n          });\n        }\n      }\n    },\n    toEdit() {\n      if (this.indexIcon.length < 7) {\n        this.tipsOn = true;\n        this.tipsContent = \"首页应用必须为7个！\";\n        return 0;\n      } else {\n        this.showEdit = !this.showEdit;\n        let animation = wepy.createAnimation({\n          duration: 300,\n          delay: 300\n        });\n        animation\n          .backgroundColor(!this.showEdit ? \"#FFFFFF\" : \"#F5F5F5\")\n          .step();\n        this.animationData = animation.export();\n        let showDetailAnimation = wepy.createAnimation({\n          duration: 300\n        });\n        let ceil = Math.ceil(parseFloat(this.indexIcon.length / 4));\n        let moveHeight = 187 * ceil;\n        showDetailAnimation\n          .height(this.showEdit ? moveHeight + \"rpx\" : \"0rpx\")\n          .step();\n        this.showDetailAnimation = showDetailAnimation.export();\n        this.$apply();\n        let indexIcon = this.indexIcon;\n        wepy.setStorageSync(\"indexIcon\", indexIcon);\n        if (!this.showEdit) {\n          let nowIndexIcon = wepy.getStorageSync(\"indexIcon\");\n          nowIndexIcon.push(this.moreFunc);\n          wepy.setStorageSync(\"indexIcon\", nowIndexIcon);\n        }\n        return 0;\n      }\n    },\n    deleteIcon(e) {\n      let item = e.currentTarget.dataset.item;\n      for (let i in this.details) {\n        let detailItem = this.details[i].find(e => e.id === item.id);\n        if (detailItem !== undefined) {\n          detailItem.isIndex = !detailItem.isIndex;\n          break;\n        }\n      }\n      let indexIcon = this.indexIcon;\n      let index = e.currentTarget.dataset.index;\n      let deleteAnimation = wepy.createAnimation({\n        duration: 300\n      });\n      deleteAnimation.opacity(0).step();\n      this.deleteAnimation[index] = deleteAnimation.export();\n      this.$apply();\n      setTimeout(() => {\n        indexIcon.splice(index, 1);\n        this.indexIcon = indexIcon;\n        let deleteAnimation = wepy.createAnimation({\n          duration: 0\n        });\n        deleteAnimation.opacity(1).step();\n        this.deleteAnimation[index] = deleteAnimation.export();\n        this.$apply();\n      }, 300);\n    },\n    changeStatus(e) {\n      let item = e.currentTarget.dataset.item;\n      if (this.indexIcon.length < 7) {\n        for (let i in this.details) {\n          let detailItem = this.details[i].find(event => event.id === item.id);\n          if (detailItem !== undefined) {\n            for (let things of this.indexIcon) {\n              if (things.id === detailItem.id) {\n                if (detailItem.isIndex) {\n                  this.deleteIconFromListAnimation(item);\n                }\n                this.$apply();\n                return 0;\n              }\n            }\n            detailItem.isIndex = !detailItem.isIndex;\n            let indexIcon = this.indexIcon;\n            indexIcon.splice(parseInt(indexIcon.length), 0, item);\n            this.indexIcon = indexIcon;\n            break;\n          }\n        }\n      } else {\n        this.deleteIconFromListAnimation(item);\n      }\n    }\n  };\n  deleteIconFromListAnimation(item) {\n    if (item.isIndex) {\n      this.fromIconListDeleteIndexIcon = this.indexIcon.find(\n        indexItem => indexItem.name === item.name\n      );\n      this.deleteIconFromList();\n    } else {\n      this.tipsOn = true;\n      this.tipsContent = \"首页已有此应用\";\n    }\n  }\n  deleteIconFromList() {\n    let item = this.fromIconListDeleteIndexIcon;\n    for (let i in this.details) {\n      let detailItem = this.details[i].find(e => e.id === item.id);\n      if (detailItem !== undefined) {\n        detailItem.isIndex = !detailItem.isIndex;\n        break;\n      }\n    }\n    let indexIcon = this.indexIcon;\n    let index;\n    this.indexIcon.forEach((item2, index2) => {\n      if (item2.name === item.name) {\n        index = index2;\n      }\n    });\n    let deleteAnimation = wepy.createAnimation({\n      duration: 300\n    });\n    deleteAnimation.opacity(0).step();\n    this.deleteAnimation[index] = deleteAnimation.export();\n    this.$apply();\n    setTimeout(() => {\n      indexIcon.splice(index, 1);\n      this.indexIcon = indexIcon;\n      let deleteAnimation = wepy.createAnimation({\n        duration: 0\n      });\n      deleteAnimation.opacity(1).step();\n      this.deleteAnimation[index] = deleteAnimation.export();\n      this.$apply();\n    }, 300);\n  }\n  async onShow() {\n    let that = this;\n    const module = await getModuleStatus();\n    const newModule = wepy.getStorageSync(\"newModule\");\n    let cantUse = [];\n    if (module.data) {\n      const currentModuleData = module.data.data;\n      for (let i of currentModuleData) {\n        if (!i.open) {\n          cantUse.push(i);\n        }\n      }\n      if (newModule) {\n        for (let i of newModule) {\n          for (let j in this.details) {\n            for (let k of this.details[j]) {\n              if (k.name === i.moduleName) {\n                k.isNew = true;\n              }\n            }\n          }\n        }\n        this.$apply();\n      }\n    }\n    if (cantUse.length !== 0) {\n      for (let i in that.details) {\n        for (let j of that.details[i]) {\n          for (let m of cantUse) {\n            if (j.name === m.moduleName) {\n              j.isOpen = false;\n            }\n          }\n        }\n      }\n    }\n\n    if (wepy.getStorageSync(\"indexIcon\").length !== 8) {\n      wepy.setStorageSync(\n        \"indexIcon\",\n        this.$parent.globalData.modules.slice(0, 8)\n      );\n    }\n    this.indexIcon = wepy\n      .getStorageSync(\"indexIcon\")\n      .splice(0, wepy.getStorageSync(\"indexIcon\").length - 1);\n    this.moreFunc = wepy.getStorageSync(\"indexIcon\")[7];\n    this.IconWidth = parseInt(71 - 20);\n    let indexIcon = this.indexIcon;\n    for (let i in this.details) {\n      this.details[i].forEach((item, index) => {\n        indexIcon.forEach(indexIcon => {\n          if (indexIcon.name === item.name) {\n            item.isIndex = true;\n          }\n        });\n      });\n    }\n    that.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.index-application\n  width 750rpx\n  height 90rpx\n  border-top 1rpx solid #E3E3E3\n  display flex\n  .application\n    display inline-block\n    font-size 28rpx\n    width 150rpx\n    line-height 90rpx\n    top 0\n    font-weight bold\n    text-align center\n  .edit-index\n    width 500rpx\n    color #888888\n    font-size 28rpx\n    height 90rpx\n    line-height 90rpx\n  .edit\n    display inline-block\n    width 100rpx\n    font-size 28rpx\n    color #47CFF5\n    border 1rpx solid #47CFF5\n    border-radius 30rpx\n    text-align center\n    height 50rpx\n    line-height 50rpx\n    margin-top 20rpx\n  .application-image\n    display inline-block\n    margin 0 10rpx\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n.now-index-course\n  width 750rpx\n  height 300rpx\n.classification\n  width 750rpx\n  border-bottom 1rpx solid #E3E3E3\n  padding 30rpx 0\n  .classification-title\n    width 500rpx\n    padding-left 10rpx\n    margin-left 20rpx\n    height 40rpx\n    line-height 40rpx\n    font-size 32rpx\n    color #353535\n    border-left 10rpx solid #47CFF5\n  .classification-detail\n    display flex\n    flex-wrap wrap\n    width 750rpx\n    position relative\n    .detail-info\n      display flex\n      justify-content center\n      flex-direction column\n      text-align center\n      width 187rpx\n      height 187rpx\n      .detail-info-container\n        position relative\n        width 150rpx\n        margin 0 auto\n        padding 10rpx\n        .add-or-delete\n          position absolute\n          width 30rpx\n          height 30rpx\n          top -10rpx\n          right -35rpx\n          background-repeat no-repeat\n          background-position center\n          background-size contain\n        .detail-image\n          position relative\n          margin 0 auto\n          height 65rpx\n          width 65rpx\n          .image-red-dot\n            position absolute\n            top -10rpx\n            right -30rpx\n            height 25rpx\n            width 25rpx\n            border-radius 50%\n            background #fd2200\n        .detail-name\n          font-size 28rpx\n          color #353535\n#show-index\n  overflow hidden\n  height 0rpx\n  padding 0rpx\n</style>\n"
  },
  {
    "path": "src/others-page/pages/news.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"container\">\n      <view style=\"margin-bottom:128rpx;\">\n        <view class=\"news-title\">{{title}}</view>\n        <view class=\"news-date\">\n          发布时间：{{date}}\n          <view class=\"ads-tip\" wx-if=\"{{isAds}}\">推广资讯</view>\n        </view>\n        <view class=\"news-content\">\n          <rich-text nodes=\"{{content}}\"></rich-text>\n        </view>\n      </view>\n      <view class=\"news-file-list\" hidden=\"{{fileList.length === 0}}\">\n        <repeat for=\"{{fileList}}\" key=\"index\" index=\"index\" item=\"item\">\n          <view class=\"news-file-item\">\n            <image mode=\"aspectFit\" src=\"{{filterWxs.filter(item.name)}}\" class=\"file-type-img\">\n            <view class=\"file-name\">{{item.name}}</view>\n            <image\n              mode=\"aspectFit\"\n              @tap=\"downLoad\"\n              data-url=\"{{item.url}}\"\n              src=\"https://static.airbob.org/admin/news_icon_download.png\"\n              class=\"file-download-img\"\n            >\n          </view>\n          <view class=\"divide\"></view>\n        </repeat>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport filterWxs from \"../wxs/filter.wxs\";\nimport { getNewsInformationContent } from \"@/api/common\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"资讯详情\",\n    title: \"\",\n    content: \"\",\n    date: \"\",\n    isAds: false,\n    fileList: []\n  };\n  wxs = {\n    filterWxs\n  };\n  methods = {\n    downLoad(event) {\n      const {\n        currentTarget: {\n          dataset: { url }\n        }\n      } = event;\n      wepy\n        .showModal({\n          title: \"提示\",\n          content: \"预览或下载附件需要消耗流量，是否继续？\",\n          confirmText: \"继续\"\n        })\n        .then(res => {\n          if (res.confirm) {\n            wepy.showLoading({\n              title: \"下载中，请稍候\",\n              mask: true\n            });\n            wepy\n              .downloadFile({\n                url: url\n              })\n              .then(res => {\n                const filePath = res.tempFilePath;\n                wepy.hideLoading();\n                wepy\n                  .openDocument({\n                    filePath: filePath\n                  })\n                  .then(() => {})\n                  .catch(() => {\n                    wepy.showToast({\n                      title: \"文件打开失败！\",\n                      icon: \"none\",\n                      mask: true\n                    });\n                  });\n              })\n              .catch(() => {\n                wepy.hideLoading();\n                wepy.showToast({\n                  title: \"下载失败！\",\n                  icon: \"none\",\n                  mask: true\n                });\n              });\n          }\n        });\n    }\n  };\n  onLoad(data) {\n    this.title = data.title;\n    if (data.time) {\n      this.date = data.time;\n      this.isAds = true;\n    } else {\n      this.isAds = false;\n      getNewsInformationContent(data.newsId).then(res => {\n        if (res.data) {\n          if (this.date) {\n            this.content = res.data.data.content;\n          } else {\n            this.content = res.data.data.detail;\n            this.fileList = res.data.data.links;\n            this.date = res.data.data.createTime;\n          }\n          this.$apply();\n        }\n      });\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  font-family 'SimHei'\n  overflow hidden\n  display flex\n  flex-direction column\n  justify-content space-between\n  min-height 100vh\n  .news-title\n    font-size 36rpx\n    color #353535\n    padding 0 55rpx\n    text-align center\n    font-weight bold\n  .news-date\n    margin 40rpx 0\n    font-size 24rpx\n    color #888\n    text-align center\n    .ads-tip\n      display inline-block\n      color #00b8ec\n      border 1rpx solid #00b8ec\n      border-radius 10px\n      padding 4rpx 8rpx\n      font-size 22rpx\n      margin-left 20rpx\n  .news-content\n    font-size 30rpx\n    color #353535\n    line-height 50rpx\n    padding 0 46rpx\n  .news-file-list\n    .divide\n      height 35rpx\n    .news-file-item\n      padding 10rpx 26rpx\n      width 650rpx\n      margin 0 auto\n      border-radius 16rpx\n      display flex\n      align-items center\n      box-shadow 0px 0px 6px 0px rgba(0, 0, 0, 0.1)\n    .file-type-img\n      width 100rpx\n      height 100rpx\n    .file-name\n      font-size 28rpx\n      margin 0 30rpx\n      overflow hidden\n      text-overflow ellipsis\n      display -webkit-box\n      -webkit-line-clamp 2\n      -webkit-box-orient vertical\n      flex 1\n    .file-download-img\n      width 65rpx\n      height 65rpx\n</style>\n"
  },
  {
    "path": "src/others-page/pages/nicpPages/nicp-check-in.wpy",
    "content": "<template>\n  <view class=\"nicp-check-in\">\n    <!-- <qy-navigation :title=\"navTitle\" :background=\"background\"></qy-navigation> -->\n    <view id=\"login-cloak\">\n      <view class=\"left-pane {{ isOthersOpen ? 'open' : '' }}\">\n        <view class=\"keyhole\" @tap=\"scanCode\">\n          <view class=\"outer-circle\">\n            <view class=\"inner-circle\">\n              <view class=\"rect {{ isHoleOpen ? 'open' : '' }}\"></view>\n            </view>\n          </view>\n        </view>\n      </view>\n      <view class=\"middle-pane {{ isOthersOpen ? 'open' : '' }}\"></view>\n      <view class=\"right-pane {{ isOthersOpen ? 'open' : '' }}\"></view>\n    </view>\n\n    <view class=\"content\">\n      <view class=\"user-info\">{{ userInfo.name }} {{ userInfo.studentId }}</view>\n      <view class=\"qy-logo\">\n        <image class=\"pomelo\" src=\"https://static.airbob.org/report-2018-06/logo-min.png\"/>\n      </view>\n\n      <view class=\"copy-right\">\n        <image class=\"copy-right-image\" src=\"https://static.airbob.org/nicp/copyright.png\" mode=\"widthFix\"/>\n      </view>\n    </view>\n  </view>\n</template>\n\n\n<script>\nimport wepy from \"wepy\";\nimport qs from \"qs\";\nimport { addEntry } from \"@/api/common\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class NicpVote extends wepy.page {\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"柚子秒签\",\n    background: \"transparent\",\n    open: false,\n    isHoleOpen: false,\n    isOthersOpen: false,\n    userInfo: null,\n    now: \"\"\n  };\n\n  ejectParamsFromPath(path) {\n    return path\n      .split(\"?\")[1]\n      .split(\"&\")\n      .map(item => ({\n        key: item.split(\"=\")[0],\n        value: item.split(\"=\")[1]\n      }));\n  }\n\n  handleCodeRes(path) {\n    const params = this.ejectParamsFromPath(path);\n    this.handleScene(params.find(({ key }) => key === \"scene\").value);\n  }\n\n  checkLogin() {\n    if (wepy.getStorageSync(\"token\") === \"\") {\n      wepy.redirectTo({\n        url: \"/others-page/pages/login\"\n      });\n    }\n  }\n\n  async handleScene(sceneValue) {\n    if (sceneValue === \"undefined\") {\n      return;\n    }\n    sceneValue = decodeURIComponent(sceneValue);\n    const type = sceneValue.split(\"@\")[1];\n    const sessionId = wepy.getStorageSync(\"token\");\n    const timestamp = Math.floor(Date.now() / 1000);\n    const params = {\n      type,\n      scene: sceneValue,\n      timestamp\n    };\n\n    try {\n      const {\n        data: { success, ...err }\n      } = await addEntry(qs.stringify(params));\n\n      if (success) {\n        console.log(\"签到成功\");\n        this.handleOpen();\n      } else {\n        if (err.errCode === 8) {\n          wepy.redirectTo({\n            url: \"../../pages/login\"\n          });\n        }\n        console.error(err);\n        wepy.showToast({\n          title: err.errMsg,\n          icon: \"none\",\n          duration: 5000\n        });\n      }\n    } catch (e) {\n      console.error(e);\n    }\n  }\n\n  methods = {\n    scanCode() {\n      wepy\n        .scanCode()\n        .then(res => {\n          this.handleCodeRes(res.path);\n        })\n        .catch(err => console.error(err));\n    }\n  };\n\n  handleOpen() {\n    this.open = true;\n    this.isHoleOpen = true;\n    setTimeout(() => {\n      this.isOthersOpen = true;\n      this.$apply();\n    }, 1000);\n  }\n\n  onLoad(options) {\n    this.checkLogin();\n    const scene = decodeURIComponent(options.scene);\n    this.handleScene(scene);\n    this.userInfo = wepy.getStorageSync(\"userInfo\");\n    const date = new Date();\n    this.now = date.toLocaleString(\"zh-CN\");\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\nvendors = official\n\n.content\n  position relative\n  width 100vw\n  height 100vh\n  background url('https://static.airbob.org/nicp/bg_1.png')\n  background-size cover\n  background-position bottom\n  .user-info\n    position absolute\n    top 52%\n    left 19vw\n    width 62%\n    padding 12rpx 0\n    font-size 34rpx\n    color #e55425\n    text-align center\n    border-radius 60rpx\n    background rgba(255, 255, 255, 0.8)\n  .pomelo\n    position absolute\n    right 2vw\n    bottom 10rpx\n    width 50rpx\n    height 50rpx\n    animation rotating 5s linear infinite\n    @keyframes rotating\n      from\n        transform rotate(0deg)\n      to\n        transform rotate(360deg)\n  .copy-right\n    position fixed\n    bottom 0\n    width 100vw\n    text-align center\n    .copy-right-image\n      width 30%\n\nflexbox()\n  display flex\n\nflex($values)\n  flex $values\n\nflexdiretion($direction = 'column')\n  flex-direction $direction\n\norder($val)\n  order $val\n\n#login-cloak\n  position absolute\n  top 0\n  bottom 0\n  left 0\n  right 0\n  z-index 100\n  flexbox()\n  .left-pane\n    position relative\n    background rgb(246, 246, 246)\n    border-right 15px solid rgb(250, 250, 250)\n    width 50%\n    // min-width 300px\n    flex(1 auto)\n    order(0)\n    transition-duration 700ms\n    &.open\n      width 0\n      transition-duration 700ms\n      min-width 0\n      margin-left -200px\n    &:after\n      position absolute\n      content ' '\n      top 0\n      bottom 0\n      right 0\n      width 1px\n      background rgb(178, 178, 178)\n    .keyhole\n      width 150px\n      height 150px\n      border 1px solid rgb(178, 178, 178)\n      border-radius 50%\n      background #fff\n      position absolute\n      top 40%\n      right -90px\n      z-index 100\n      flexbox()\n      justify-content center\n      .outer-circle\n        flex(1 auto)\n        order(0)\n        max-width 125px\n        height 125px\n        margin auto\n        border 1px solid rgb(178, 178, 178)\n        border-radius 50%\n        flexbox()\n        justify-content center\n        background rgb(40, 215, 255)\n        background linear-gradient(to bottom, rgba(40, 215, 255, 1) 19%, rgba(43, 163, 215, 1) 52%, rgb(60, 139, 194) 90%)\n        .inner-circle\n          flex(1 100%)\n          order(0)\n          max-width 100px\n          height 100px\n          background rgb(246, 246, 246)\n          margin auto\n          border 1px solid rgb(178, 178, 178)\n          border-radius 50%\n          flexbox()\n          justify-content center\n          .rect\n            position relative\n            flex(1 auto)\n            order(0)\n            max-width 20px\n            height 70px\n            background rgb(102, 102, 102)\n            margin auto\n            box-shadow inset 0 0 10px rgba(0, 0, 0, 0.8)\n            &:after\n              content ' '\n              position absolute\n              top 20px\n              left 0\n              width 0\n              height 0\n              border 5px solid rgba(0, 0, 0, 0)\n              border-left-color #F6F6F6\n            &:before\n              content ' '\n              position absolute\n              bottom 25px\n              right 0\n              width 0\n              height 0\n              border 5px solid rgba(0, 0, 0, 0)\n              border-right-color #F6F6F6\n            transition-duration 1s\n            &.open\n              transform rotate(180deg)\n              transition-duration 1s\n  .middle-pane\n    width 0\n    max-width 0\n    background rgba(0, 0, 0, 0)\n    border-left 1px solid rgb(178, 178, 178)\n    border-right 1px solid rgb(178, 178, 178)\n    flex(1 auto)\n    order(1)\n    transition-duration 700ms\n    &.open\n      width 150%\n      max-width 150%\n      transition-duration 700ms\n  .right-pane\n    background rgb(246, 246, 246)\n    border-left 15px solid rgb(250, 250, 250)\n    position relative\n    width 50%\n    flex(1 auto)\n    order(2)\n    transition-duration 700ms\n    &.open\n      transition-duration 700ms\n      width 0\n      margin-right -200px\n    &:before\n      position absolute\n      top 0\n      bottom 0\n      left 0\n      width 1px\n      content ' '\n      background rgb(178, 178, 178)\n</style>\n"
  },
  {
    "path": "src/others-page/pages/nicpPages/nicp-more.wpy",
    "content": "<template>\n<view class=\"nicp-more\">\n  <qy-navigation :title=\"navTitle\" :background=\"background\"></qy-navigation>\n  <web-view class=\"webview\" src=\"https://miniprogram.banoflife.cn/v/2tok4Z35/\"></web-view>\n</view>\n</template>\n\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class NicpMore extends wepy.page {\n  config = {\n    navigationBarTitleText: \"创新杯\",\n    navigationBarBackgroundColor: \"#45D3FB\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"创新杯\",\n    background: \"#45D3FB\"\n  };\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\n.webview\n  width 100vw\n  height 100vh\n</style>\n"
  },
  {
    "path": "src/others-page/pages/nicpPages/nicp-vote.wpy",
    "content": "<template>\n  <view class=\"nicp-vote\">\n    <qy-navigation :title=\"navTitle\" :background=\"background\"></qy-navigation>\n    <view class=\"content\">\n      <view class=\"logo\">\n        <image class=\"logo-image\" src=\"https://static.airbob.org/nicp/cxb_logo.png\"/>\n      </view>\n      <view class=\"header\">投票成功</view>\n      <view class=\"check\">✔</view>\n      <view>\n        <image class=\"pomelo\" src=\"https://static.airbob.org/report-2018-06/logo-min.png\"/>\n      </view>\n    </view>\n  </view>\n</template>\n\n\n<script>\nimport wepy from \"wepy\";\nimport qs from \"qs\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class NicpVote extends wepy.page {\n  config = {\n    navigationBarTitleText: \"创新杯投票\",\n    navigationBarBackgroundColor: \"#ecd6e8\"\n  };\n\n  components = {\n    \"qy-navigation\": navigation\n  };\n\n  data = {\n    navTitle: \"创新杯投票\",\n    background: \"#ecd6e8\"\n  };\n\n  ejectParamsFromPath(path) {\n    return path\n      .split(\"?\")[1]\n      .split(\"&\")\n      .map(item => ({\n        key: item.split(\"=\")[0],\n        value: item.split(\"=\")[1]\n      }));\n  }\n\n  handleCodeRes(path) {\n    const params = this.ejectParamsFromPath(path);\n    this.handleScene(params.find(({ key }) => key === \"scene\").value);\n  }\n\n  checkLogin() {\n    if (wepy.getStorageSync(\"token\") === \"\") {\n      wepy.redirectTo({\n        url: \"/others-page/pages/login\"\n      });\n    }\n  }\n\n  async handleScene(sceneValue) {\n    if (sceneValue === \"undefined\") {\n      return;\n    }\n    const type = sceneValue.split(\"@\")[1];\n    const sessionId = wepy.getStorageSync(\"token\");\n    const timestamp = Math.floor(Date.now() / 1000);\n    const params = {\n      type,\n      scene: sceneValue,\n      timestamp\n    };\n\n    try {\n      const {\n        data: { success, ...err }\n      } = await this.$parent.axios.post(\n        \"https://wechat.njupt.edu.cn/nicp/addEntry\",\n        qs.stringify(params),\n        {\n          headers: {\n            \"Content-Type\": \"application/x-www-form-urlencoded\"\n          }\n        }\n      );\n\n      if (success) {\n        console.log(\"投票成功\");\n        this.handleOpen();\n      } else {\n        if (err.errCode === 8) {\n          wepy.redirectTo({\n            url: \"../../pages/login\"\n          });\n        }\n        console.error(err);\n        wepy.showToast({\n          title: err.errMsg,\n          icon: \"none\",\n          duration: 2000\n        });\n      }\n    } catch (e) {\n      console.error(e);\n    }\n  }\n\n  methods = {\n    scanCode() {\n      wepy\n        .scanCode()\n        .then(res => {\n          console.log(res);\n          this.handleCodeRes(res.path);\n        })\n        .catch(err => console.error(err));\n    }\n  };\n\n  onLoad(options) {\n    this.checkLogin();\n    const scene = decodeURIComponent(options.scene);\n    this.handleScene(scene);\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\nvendors = official\n\n.nicp-vote\n  .content\n    position relative\n    width 100vw\n    height 100vh\n    background url('https://static.airbob.org/nicp/bg.png')\n    background-size cover\n    background-position bottom\n    .logo,\n    .header,\n    .check\n      text-align center\n    .logo\n      padding-top 10vh\n      width 100%\n      .logo-image\n        width 24vw\n        height 24vw\n    .header\n      padding-top 4vh\n      font-size 60rpx\n    .check\n      font-size 100rpx\n      color #2ba246\n    .pomelo\n      position absolute\n      right 2vw\n      bottom 2vw\n      width 50rpx\n      height 50rpx\n      animation rotating 5s linear infinite\n      @keyframes rotating\n        from\n          transform rotate(0deg)\n        to\n          transform rotate(360deg)\n</style>\n"
  },
  {
    "path": "src/others-page/pages/personalPages/aboutus.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"header\">\n      <image mode=\"aspectFit\" src=\"https://static.airbob.org/admin/about_pic_logo.png\" class=\"header-logo\"/>\n    </view>\n    <view class=\"body\">\n      <view class=\"body-head\">- 南邮小程序 -</view>\n      <view class=\"body-content\">\n        南京邮电大学小程序是由南京邮电大学青柚工作室开发，一款方便快捷，无需下载安装即可在{{isFromQQ ? 'QQ客户端' : '微信客户端'}}即开即用的APP，有别于一般需要下载安装的APP，也不同于微信公众号，具有方便快捷的特点。\n      </view>\n      <view class=\"body-content\">\n        南京邮电大学小程序具有许多方便柚子们的功能，服务于广大的南京邮电大学学生们。小程序可以用来查询课表、跑操次数，图书馆、一卡通、校内外资讯、校历等等，集多种功能于一身。还在担心期末图书馆没有座位？那还不赶紧使用我们的小程序。\n      </view>\n      <view class=\"body-content\">\n        南京邮电大学小程序也将不断的进行完善，除了基础的功能以外，日后还会推出各种更加强大实用的功能，各位柚子们敬请期待吧！\n      </view>\n      <view class=\"body-content\">\n        欢迎广大柚子们一起见证小程序的不断完善，交流反馈群：330843906。\n      </view>\n    </view>\n    <view class=\"body\" style=\"margin-top: 50rpx\">\n      <view class=\"body-head\">- 青柚工作室 -</view>\n        <view class=\"body-content\">\n          青柚工作室成立于2017年10月，现已有超过30位成员分别负责技术、设计、运营推广等工作。截止到现在，青柚工作室已经开发“南京邮电大学”、“校谈”等微信小程序。其中，“南邮小程序”现已有超过3.9万用户，日均活跃量超过8千人次。\n        </view>\n        <view class=\"body-content\">\n          出于对技术的热爱和对设计的追求，青柚工作室成员本着为南邮学生服务的出发点，创造解决生活学习中存在的痛点的可能，开发产品，服务同学，提升技术能力。青柚，我们在创造可能。\n        </view>\n      </view>\n    <view class=\"footer\">\n      <view class=\"footer-dialog-btn\" @tap=\"goProtocol\">用户协议 | 隐私政策</view>\n        <view class=\"footer-version\">Version 3.0</view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"关于我们\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"关于我们\",\n    isFromQQ: wepy.$appConfig.fromQQ\n  };\n  methods = {\n    goProtocol() {\n      this.$navigate({\n        url: \"./protocol\"\n      });\n    }\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.header\n  text-align center\n  height 340rpx\n  background url('https://static.airbob.org/admin/about_pic_bg.png')\n  background-size contain\n  .header-logo\n    width 390rpx\n    margin-top -70rpx\n\n.body-head\n  margin-bottom 30rpx\n  text-align center\n  font-size 34rpx\n\n.body-content\n  color #888\n  line-height 200%\n  font-size 32rpx\n  padding 0 60rpx\n  text-indent 64rpx\n  text-align justify\n\n.footer\n  margin-top 100rpx\n  margin-bottom 20rpx\n  text-align center\n  font-size 24rpx\n  .footer-dialog-btn\n    margin 15rpx 0\n    color #4ad1f4\n  .footer-version\n    color #7d7d7d\n</style>\n"
  },
  {
    "path": "src/others-page/pages/personalPages/change-password.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\" class=\"container\">\n      <view class=\"content\">\n        <view class=\"toggle-body {{centerBody}}\">\n          <view hidden=\"{{!isFromLogin}}\" class=\"content-body\">\n            <view class=\"container-main\">\n              <view class=\"input-container\">\n                <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/image/png/login/phone.png\"/>\n                <input type=\"number\" class=\"input\" @input=\"bindPhone\" placeholder=\"请输入手机号\" maxlength=\"11\"/>\n              </view>\n              <view class=\"input-container\">\n                <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/image/png/login/verification.png\"/>\n                <input type=\"number\" class=\"input\" @input=\"bindVerificationCode\" placeholder=\"请输入验证码\" maxlength=\"6\"/>\n                <button class=\"input-after {{flag ? 'btn-disabled':''}}\" @tap=\"getVerificationCode\">{{verticationMsg}}</button>\n              </view>\n              <view class=\"login-btn\" @tap=\"handleVerificationCode\">下一步</view>\n            </view>\n          </view>\n          <view hidden=\"{{!isFromLogin}}\" class=\"content-body\">\n            <view class=\"container-main\">\n              <view class=\"input-container\">\n                <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/%E5%AF%86%E7%A0%81.png\"/>\n                <input type=\"password\" @input=\"bindPassword\" class=\"input\" placeholder=\"请输入新的小程序密码\" />\n              </view>\n              <view class=\"input-container\">\n                <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/%E5%AF%86%E7%A0%81.png\"/>\n                <input type=\"password\" @input=\"bindPassword2\" class=\"input\" placeholder=\"请再次输入新的小程序密码\" />\n              </view>\n              <view class=\"login-btn {{disableChange?'disabled-btn':''}}\" @tap=\"handlePasswordChange\">确认更新密码</view>\n            </view>\n          </view>\n          <view hidden=\"{{isFromLogin}}\" class=\"content-body\">\n            <view class=\"container-main\">\n              <view class=\"input-container\">\n                <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/%E5%AF%86%E7%A0%81.png\"/>\n                <input type=\"password\" @input=\"bindPasswordOld\" class=\"input\" placeholder=\"请输入旧的小程序密码\" />\n              </view>\n              <view class=\"input-container\">\n                <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/%E5%AF%86%E7%A0%81.png\"/>\n                <input type=\"password\" @input=\"bindPassword\" class=\"input\" placeholder=\"请输入新的小程序密码\" />\n              </view>\n              <view class=\"login-btn {{disableUpdate?'disabled-btn':''}}\" @tap=\"handlePasswordUpdate\">确认更新密码</view>\n            </view>\n          </view>\n          <view class=\"content-body\">\n            <view class=\"container-main\">\n              <view class=\"success-container\">\n                <view class=\"image-container\"></view>\n                <view class=\"change-success\">修改成功^-^</view>\n              </view>\n            </view>\n          </view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n<script>\nimport wepy from \"wepy\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport {\n  sendSmsAtForgetPassword,\n  checkCaptchaAtForgetPassword,\n  modifyPasswordAtForgetPassword,\n  modifyPasswordByOldPassword\n} from \"@/api/password\";\n\nexport default class ChangePhone extends wepy.page {\n  components = {\n    BaseContainer\n  };\n  data = {\n    step: 0,\n    verticationMsg: \"获取验证码\",\n    passwordOld: \"\",\n    zfPassword: \"\",\n    zfPassword2: \"\",\n    phoneNumber: \"\",\n    flag: false,\n    vertication: \"\",\n    isFromLogin: false\n  };\n  methods = {\n    async getVerificationCode() {\n      if (this.phoneNumber && this.phoneNumber.trim().length) {\n        if (!this.flag) {\n          this.flag = true;\n          let count = 60;\n          this.verticationMsg = \"请求中\";\n          this.$apply();\n          wepy.showLoading({\n            title: \"请求中\",\n            mask: true\n          });\n          const { data } = await sendSmsAtForgetPassword(this.phoneNumber);\n          wepy.hideLoading();\n          if (data && data.data) {\n            this.verticationMsg = `60s`;\n            this.$apply();\n            let t = setInterval(() => {\n              this.verticationMsg = `${--count}s`;\n              if (count === 0) {\n                clearInterval(t);\n                this.verticationMsg = \"获取验证码\";\n                this.flag = false;\n              }\n              this.$apply();\n            }, 1000);\n          } else {\n            this.flag = false;\n            this.verticationMsg = \"获取验证码\";\n            this.$apply();\n            if (data.errCode !== 1601) {\n              this.$parent.showTip(\"不知道为什么失败了呢～\");\n            }\n          }\n        }\n      } else {\n        this.$parent.showTip(\"手机号不能为空\");\n      }\n    },\n    async handleVerificationCode() {\n      if (\n        this.phoneNumber &&\n        this.phoneNumber.trim().length &&\n        this.vertication &&\n        this.vertication.length\n      ) {\n        wepy.showLoading({\n          title: \"验证手机验证码中~\",\n          mask: true\n        });\n        const { data } = await checkCaptchaAtForgetPassword(\n          this.vertication,\n          this.phoneNumber\n        );\n        wepy.hideLoading();\n        if (data && data.data) {\n          this.step++;\n          this.$apply();\n        } else {\n          this.$parent.showTip(\"验证码错误\");\n        }\n      } else {\n        this.$parent.showTip(\"手机号和验证码不能为空\");\n      }\n    },\n    async handlePasswordChange() {\n      if (!this.disableChange && this.zfPassword && this.zfPassword.length) {\n        wepy.showLoading({\n          title: \"修改密码中~\",\n          mask: true\n        });\n        const { data } = await modifyPasswordAtForgetPassword(\n          this.zfPassword,\n          this.phoneNumber\n        );\n        wepy.hideLoading();\n        if (data && data.data) {\n          this.step++;\n          this.$apply();\n        } else {\n          this.$parent.showTip(\"不知道为什么失败了呢～\");\n        }\n      }\n    },\n    async handlePasswordUpdate() {\n      if (!this.disableUpdate) {\n        wepy.showLoading({\n          title: \"修改密码中...\",\n          mask: true\n        });\n        const { data } = await modifyPasswordByOldPassword(\n          this.passwordOld,\n          this.zfPassword\n        );\n        wepy.hideLoading();\n        if (data && data.data) {\n          this.step++;\n          this.$apply();\n          this.$parent.showTip(\"即将跳转至登录页\");\n          setTimeout(() => {\n            wepy.reLaunch({ url: \"../login\" });\n          }, 800);\n        } else {\n          this.$parent.showTip(\"不知道为什么失败了呢～\");\n        }\n      }\n    },\n    bindPhone(e) {\n      this.phoneNumber = e.detail.value;\n    },\n    bindVerificationCode(e) {\n      this.vertication = e.detail.value;\n    },\n    bindPassword(e) {\n      this.zfPassword = e.detail.value;\n    },\n    bindPassword2(e) {\n      this.zfPassword2 = e.detail.value;\n    },\n    bindPasswordOld(e) {\n      this.passwordOld = e.detail.value;\n    }\n  };\n  computed = {\n    centerBody() {\n      switch (this.step) {\n        case 0:\n          return \"zf-step\";\n        case 1:\n          return \"sms-step\";\n        case 2:\n          return \"success-step\";\n        default:\n          return \"zf-step\";\n      }\n    },\n    disableChange() {\n      if (\n        this.zfPassword &&\n        this.zfPassword2 &&\n        this.zfPassword.length &&\n        this.zfPassword2.length\n      ) {\n        return this.zfPassword !== this.zfPassword2;\n      } else {\n        return true;\n      }\n    },\n    disableUpdate() {\n      if (\n        this.zfPassword &&\n        this.passwordOld &&\n        this.zfPassword.length &&\n        this.passwordOld.length\n      ) {\n        return this.zfPassword === this.passwordOld;\n      } else {\n        return true;\n      }\n    },\n    navTitle() {\n      return this.isFromLogin ? \"修改小程序密码\" : \"找回小程序密码\";\n    }\n  };\n  onLoad() {\n    // 如果是来自登录页则是忘记密码，否则是修改密码\n    const LOGIN_ROUTE = \"others-page/pages/login\";\n    this.isFromLogin = getCurrentPages().some(x => x.route === LOGIN_ROUTE);\n  }\n}\n</script>\n<style lang=\"stylus\" scoped>\n.content\n  display flex\n  flex-direction column\n  width 100vw\n  height 100%\n  z-index 0\n  overflow hidden\n.toggle-body\n  display flex\n  width 300vw\n  transition all 0.5s\n.zf-step\n  transform translateX(0vw)\n.sms-step\n  transform translateX(-100vw)\n.success-step\n  transform translateX(-200vw)\n.container\n  display flex\n  align-items center\n  min-height 90vh\n  .content-body\n    width 100vw\n    .container-main\n      height 100%\n      display flex\n      flex-direction column\n      justify-content center\n    .success-container\n      display flex\n      justify-content center\n      align-items center\n      flex-wrap wrap\n      .image-container\n        width 750rpx\n        height 148rpx\n        background-image url('https://static.airbob.org/under-graduate/%E6%88%90%E5%8A%9F.png')\n        background-size contain\n        background-position center\n        background-repeat no-repeat\n      .change-success\n        width 750rpx\n        text-align center\n        font-family PingFangSC-Regular\n        font-size 36rpx\n        margin-top 32rpx\n        color #888888\n    .login-btn\n      height 74rpx\n      width 586rpx\n      margin 90rpx auto 40rpx\n      line-height 74rpx\n      color #fff\n      font-size 32rpx\n      text-align center\n      border-radius 50rpx\n      background linear-gradient(45deg, #abdcff 0%, #6ae4ff 100%)\n    .disabled-btn\n      background #cacaca !important\n    .input-container\n      display flex\n      width 586rpx\n      margin 10rpx auto 30rpx\n      padding-bottom 6rpx\n      border-bottom 1rpx solid #F2F2F2\n      align-items center\n      .input-image\n        width 26rpx\n        height 40rpx\n        margin-right 20rpx\n      .input\n        font-size 28rpx\n        flex 1\n      .input-after\n        width 160rpx\n        height 45rpx\n        margin-left 20rpx\n        padding 0\n        background linear-gradient(-225deg, #ABDCFF 0%, #6AE4FF 100%)\n        color #fff\n        font-size 24rpx\n        line-height 45rpx\n        text-align center\n        border-radius 30rpx\n        &:after\n          border 0\n.btn-disabled\n  background #D0F5FF !important\n</style>\n\n"
  },
  {
    "path": "src/others-page/pages/personalPages/change-phone.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"content\">\n      <view class=\"toggle-body {{centerBody}}\">\n        <view class=\"content-body\">\n          <view class=\"container-main\">\n            <view class=\"input-container\">\n              <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/%E5%AF%86%E7%A0%81.png\"/>\n              <input type=\"password\" @input=\"getPassword\" class=\"input\" placeholder=\"请输入小程序密码\" />\n            </view>\n            <view class=\"login-btn\" @tap=\"getCheck\">验证密码</view>\n          </view>\n        </view>\n        <view class=\"content-body\">\n          <view class=\"container-main\">\n            <view class=\"input-container\">\n              <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/image/png/login/phone.png\"/>\n              <input type=\"number\" @input=\"getNumber\" class=\"input\" placeholder=\"请输入手机号\" maxlength=\"11\"/>\n            </view>\n            <view class=\"input-container\">\n              <image mode=\"widthFix\" class=\"input-image\" src=\"https://static.airbob.org/under-graduate/image/png/login/verification.png\"/>\n              <input type=\"number\" @input=\"getVertication\" class=\"input\" placeholder=\"请输入验证码\" maxlength=\"6\"/>\n              <button class=\"input-after {{flag ? '' : 'btn-disabled'}}\" @tap=\"fetchVertication\">{{verticationMsg}}</button>\n            </view>\n            <view class=\"login-btn\" @tap=\"goLogin\">下一步</view>\n          </view>\n        </view>\n        <view class=\"content-body\">\n          <view class=\"container-main\">\n            <view class=\"success-container\">\n              <view class=\"image-container\"></view>\n              <view class=\"change-success\">修改成功^-^</view>\n            </view>\n          </view>\n        </view>\n      </view>\n    </view>\n  </view>\n</template>\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\nimport {\n  changePhone,\n  checkPhone,\n  getUserInfo,\n  changePhoneVerification\n} from \"@/api/common\";\n\nexport default class ChangePhone extends wepy.page {\n  config = {\n    navigationBarTitleText: \"更改绑定手机\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  mixins = [];\n\n  data = {\n    navTitle: \"更改绑定手机\",\n    step: 0,\n    verticationMsg: \"请输入验证码\",\n    zfPassword: \"\",\n    phoneNumber: \"\",\n    flag: true,\n    vertication: \"\"\n  };\n\n  methods = {\n    getVertication(e) {\n      this.vertication = e.detail.value;\n    },\n    getCheck() {\n      let that = this;\n      wepy.showLoading(\"请求中\");\n      changePhone(this.zfPassword).then(res => {\n        wepy.hideLoading();\n        if (!res.data || !res.data.data) {\n          that.$parent.showTip(\"不知道为什么失败了呢～\");\n        } else {\n          that.step = 1;\n          that.$apply();\n        }\n      });\n    },\n    async goLogin() {\n      wepy.showLoading(\"请求中\");\n      const res = await checkPhone(this.vertication);\n      if (res.data.data) {\n        const response = await getUserInfo();\n        wepy.hideLoading();\n        wepy.setStorageSync(\"User\", response.data.data);\n        this.step = 2;\n        this.$apply();\n      }\n    },\n    getPassword(e) {\n      this.zfPassword = e.detail.value;\n    },\n    getNumber(e) {\n      this.phoneNumber = e.detail.value;\n    },\n    fetchVertication() {\n      if (this.phoneNumber.trim().length === 0) {\n        this.$parent.showTip(\"手机号不能为空\");\n      } else {\n        // 60s\n        if (this.flag) {\n          this.flag = false;\n          let count = 60;\n          let t = setInterval(() => {\n            this.verticationMsg = `${--count}s`;\n            if (count === 0) {\n              clearInterval(t);\n              this.verticationMsg = \"获取验证码\";\n              this.flag = true;\n            }\n            this.$apply();\n          }, 1000);\n          changePhoneVerification(this.phoneNumber).then(res => {\n            if (!res.data.data) {\n              this.$parent.showTip(res.data.errMsg);\n            }\n          });\n        }\n      }\n    }\n  };\n  computed = {\n    centerBody() {\n      switch (this.step) {\n        case 0:\n          return \"zf-step\";\n        case 1:\n          return \"sms-step\";\n        case 2:\n          return \"success-step\";\n        default:\n          return \"zf-step\";\n      }\n    }\n  };\n\n  onLoad() {}\n}\n</script>\n<style lang=\"stylus\" scoped>\n.content\n  position absolute\n  display flex\n  flex-direction column\n  width 100vw\n  height 100vh\n  z-index 0\n  overflow hidden\n.toggle-body\n  display flex\n  width 300vw\n  transition all 0.5s\n.zf-step\n  transform translateX(0vw)\n.sms-step\n  transform translateX(-100vw)\n.success-step\n  transform translateX(-200vw)\n.container\n  display flex\n  align-items center\n  min-height 90vh\n  .content-body\n    width 100vw\n    .container-main\n      height 100vh\n      display flex\n      flex-direction column\n      justify-content center\n    .success-container\n      display flex\n      justify-content center\n      align-items center\n      flex-wrap wrap\n      .image-container\n        width 750rpx\n        height 148rpx\n        background-image url('https://static.airbob.org/under-graduate/%E6%88%90%E5%8A%9F.png')\n        background-size contain\n        background-position center\n        background-repeat no-repeat\n      .change-success\n        width 750rpx\n        text-align center\n        font-family PingFangSC-Regular\n        font-size 36rpx\n        margin-top 32rpx\n        color #888888\n    .login-btn\n      height 74rpx\n      width 586rpx\n      margin 90rpx auto 40rpx\n      line-height 74rpx\n      color #fff\n      font-size 32rpx\n      text-align center\n      border-radius 50rpx\n      background linear-gradient(45deg, #abdcff 0%, #6ae4ff 100%)\n    .input-container\n      display flex\n      width 586rpx\n      margin 30rpx auto 0\n      padding-bottom 6rpx\n      border-bottom 1rpx solid #F2F2F2\n      align-items center\n      .input-image\n        width 26rpx\n        height 40rpx\n        margin-right 20rpx\n      .input\n        font-size 28rpx\n        flex 1\n      .input-after\n        width 160rpx\n        height 45rpx\n        margin-left 20rpx\n        padding 0\n        background linear-gradient(-225deg, #ABDCFF 0%, #6AE4FF 100%)\n        color #fff\n        font-size 24rpx\n        line-height 45rpx\n        text-align center\n        border-radius 30rpx\n        &:after\n          border 0\n.btn-disabled\n  background #D0F5FF !important\n</style>\n\n"
  },
  {
    "path": "src/others-page/pages/personalPages/changelog.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view style=\"box-sizing: border-box;width: 100vw\">\n      <view style=\"margin-left: 70rpx\" id=\"scroll-view\">\n        <repeat for=\"{{logList}}\" key=\"index\">\n          <change-log-item :log=\"item\"/>\n        </repeat>\n      </view>\n      <view class=\"toTop\" @tap=\"toTop\">Top</view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\nimport changeLogItem from \"../../components/changeLogItem\";\nimport { getUpdateLog } from \"@/mock/common\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"更新日志\"\n  };\n  components = {\n    \"change-log-item\": changeLogItem,\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"更新日志\",\n    logList: [\n      {\n        title: \"小程序持续更新中\",\n        content: \"\"\n      }\n    ]\n  };\n  methods = {\n    toTop() {\n      wepy.pageScrollTo({\n        scrollTop: 0,\n        duration: 300\n      });\n    }\n  };\n  async onLoad() {\n    try {\n      wepy.showLoading({\n        title: \"加载更新日志中...\", //提示的内容,\n        mask: true //显示透明蒙层，防止触摸穿透,\n      });\n      const {\n        data: { data }\n      } = await getUpdateLog();\n      this.logList = data;\n      this.$apply();\n    } finally {\n      wepy.hideLoading();\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.toTop\n  display inline-block\n  width 80rpx\n  height 80rpx\n  margin 0 0 50rpx 50rpx\n  border-radius 50%\n  color #ffffff\n  font-size 36rpx\n  line-height 80rpx\n  text-align center\n  background #f65758\n</style>\n"
  },
  {
    "path": "src/others-page/pages/personalPages/protocol.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"protocol-container\">\n      <view class=\"head\">“南京邮电大学”微信小程序用户协议</view>\n      <view>青柚工作室（以下简称“青柚”）在此特别提醒您（用户）在注册成为用户之前，请认真阅读本《用户协议》（以下简称“协议”），确保您充分理解本协议中各条款，包括免除青柚责任的条款及限制用户权利的条款。请您审慎阅读并选择接受或不接受本协议。除非您接受本协议所有条款，否则您无权注册、登录或使用本协议所涉服务。您的注册、登录、使用等行为将视为对本协议的接受，并同意接受本协议各项条款的约束。</view>\n      <view>本协议约定青柚与用户之间关于“南京邮电大学”微信小程序（以下简称“南邮小程序”）服务（以下简称“服务”）的权利义务。“用户”是指注册、登录、使用本服务的个人。本协议可由青柚随时更新，更新后的协议条款在代替原来的协议条款之前会另行通知用户，用户可在南邮小程序中查阅最新版协议条款。在青柚修改协议条款后，如果用户不接受修改后的条款，请立即停止使用青柚提供的服务，用户继续使用青柚提供的服务将被视为接受修改后的协议。</view>\n      <view>一、账号注册</view>\n      <view>1、账号须知：</view>\n      <view>用户在使用本服务前需要注册一个“南邮小程序”账号。“南邮小程序”账号应当使用手机号码绑定注册，请用户使用尚未与“南邮小程序”账号绑定的手机号码注册“南邮小程序”账号。青柚可以根据用户需求或产品需要对账号注册和绑定的方式进行变更，而无须事先通知用户。</view>\n      <view>2、用户信息：</view>\n      <view>南邮小程序用户系统与南邮正方教务系统接入，个人用户基本信息（如：昵称、头像等）使用微信小程序的用户信息，遵守微信小程序平台的相关用户规范。</view>\n      <view>二、服务内容</view>\n      <view>1、南邮小程序网络服务的具体内容由南邮小程序根据实际情况提供，例如实用功能、社交消息和信息推送等。</view>\n      <view>2、南邮小程序仅提供相关的网络服务，除此之外与相关网络服务有关的设备(如个人电脑、手机、及其他与接入互联网或移动网有关的装置)及所需的费用(如为接入互联网而支付的电话费及上网费、为使用移动网而支付的手机费)均应由用户自行负担。</view>\n      <view>3、南邮小程序与南邮正方教务系统接入，提供课程查询、成绩查询、跑操查询等实用服务，在您注册使用之前，会提示需要提供正方教务系统和其他系统学号、密码等信息。您输入学号、密码后即同意授权并委托我们以您的名义接入正方和其他系统。在等级查询相关功能中，我们会提示您输入准考证号，在您输入后即视为同意授权并委托我们以您的名义查询信息，我们将通过相关等级考试官方查询渠道的方式为您获取成绩等信息。对于在上述过程中所获悉的用户个人的学号、密码、准考证号、姓名、课程、成绩等信息我们将会严格保密，不会以任何形式向其他第三方组织或个人泄露。</view>\n      <view>三、隐私保护</view>\n      <view>1、用户在注册账号或使用本服务的过程中，可能需要填写或提交一些必要的信息，如法律法规、规章规范性文件（以下称“法律法规”）规定的需要填写的身份信息。如用户提交的信息不完整或不符合法律法规的规定，则用户可能无法使用本服务或在使用本服务的过程中受到限制。</view>\n      <view>2、个人隐私信息是指涉及用户个人身份或个人隐私的信息，比如，用户真实姓名、身份证号、手机号码、手机设备识别码、IP地址。非个人隐私信息是指用户对本服务的操作状态以及使用习惯等明确且客观反映在青柚服务器端的基本记录信息、个人隐私信息范围外的其它普通信息，以及用户同意公开的上述隐私信息。</view>\n      <view>3、尊重用户个人隐私信息的私有性是青柚的一贯制度，青柚将采取技术措施和其他必要措施，确保用户个人隐私信息安全，防止在本服务中收集的用户个人隐私信息泄露、毁损或丢失。在发生前述情形或者青柚发现存在发生前述情形的可能时，将及时采取补救措施。</view>\n      <view>4、青柚未经用户同意不向任何第三方公开、 透露用户个人隐私信息。但以下特定情形除外：</view>\n      <view>青柚根据法律法规规定或有权机关的指示提供用户的个人隐私信息；</view>\n      <view>由于用户将其用户密码告知他人或与他人共享注册帐户与密码，由此导致的任何个人信息的泄漏，或其他非因青柚原因导致的个人隐私信息的泄露；</view>\n      <view>用户自行向第三方公开其个人隐私信息；</view>\n      <view>用户与青柚及合作单位之间就用户个人隐私信息的使用公开达成约定，青柚因此向合作单位公开用户个人隐私信息；</view>\n      <view>任何由于黑客攻击、电脑病毒侵入及其他不可抗力事件导致用户个人隐私信息的泄露。</view>\n      <view>5、用户同意青柚可在以下事项中使用用户的个人隐私信息：</view>\n      <view>青柚向用户及时发送重要通知，如软件更新、本协议条款的变更；</view>\n      <view>青柚内部进行审计、数据分析和研究等，以进行相关总结活动，改进青柚的产品、服务和与用户之间的沟通；</view>\n      <view>依本协议约定，青柚管理、审查用户信息及进行处理措施；</view>\n      <view>适用法律法规规定的其他事项。</view>\n      <view>除上述事项外，如未取得用户事先同意，青柚不会将用户个人隐私信息使用于任何其他用途。</view>\n      <view>6、为了改善青柚的技术和服务，向用户提供更好的服务体验，青柚或可会自行收集使用或向第三方提供用户的非个人隐私信息。</view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport navigation from \"@/components/qy-navigation\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"用户协议\"\n  };\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"用户协议\"\n  };\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nview\n  text-indent 50rpx\n  padding 0 10rpx\n.protocol-container\n  font-size 25rpx\n  line-height 1.5\n  .head\n    font-size 28rpx\n    text-align center\n</style>\n"
  },
  {
    "path": "src/others-page/pages/questionnairePages/questionnaire-homepage.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <view class=\"container-header\">\n          <view class=\"my-portrait\">\n            <open-data type=\"userAvatarUrl\"></open-data>\n          </view>\n          <!-- <image class=\"header-avatar\" mode=\"aspectFit\" src=\"{{avatar}}\"/> -->\n          <view class=\"header-username\">{{ username }}</view>\n        </view>\n        <view class=\"container-body\">\n          <repeat for=\"{{ questionnaires }}\" index=\"index\" key=\"key\" item=\"item\">\n            <view\n              class=\"questionnaire-card {{ item.status==2?'questionnaire-card-finished':'' }}\"\n              style=\"display:{{ item.status>=0?'flex':'none' }};\"\n              @tap=\"toQuestionnaire\"\n              data-id=\"{{item.questionId}}\"\n              data-status=\"{{item.status}}\"\n              data-deadline=\"{{item.deadline}}\"\n              data-assign-name=\"{{item.assignName}}\"\n            >\n              <view class=\"card-title\">{{ item.title }}(匿名)</view>\n              <view class=\"card-detail\">\n                <view\n                  class=\"detail-status {{ item.status==1?'detail-status-finished':'detail-status-unfinished' }}\"\n                >{{ item.status==1?'已填写':'未填写' }}</view>\n                <view class=\"detail-deadline\">{{ item.deadline }}</view>\n              </view>\n            </view>\n          </repeat>\n        </view>\n        <view class=\"container-footer\">没有更多了</view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport {\n  getAllQuestionnaires,\n  questionnaireWithAuth\n} from \"@/api/questionnaire\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"问卷测评\"\n  };\n  components = {\n    BaseContainer\n  };\n  mixins = [JudgeStatus];\n  data = {\n    navTitle: \"问卷测评\",\n    // avatar: \"\",\n    username: \"\",\n    questionnaires: [],\n    relativeDeadline: \"\",\n    visitorModeStatus: false\n  };\n  methods = {\n    toQuestionnaire(e) {\n      let id = e.currentTarget.dataset.id;\n      let deadline = e.currentTarget.dataset.deadline;\n      let status = Number(e.currentTarget.dataset.status);\n      let assignName = e.currentTarget.dataset.assignname;\n      if (status === 0) {\n        wepy.navigateTo({\n          url: `./questionnaire?questionnaireId=${id}&&deadline=${deadline}&&assignName=${assignName}`\n        });\n      } else if (status === 1) {\n        wepy.showToast({\n          title: \"问卷已填写\",\n          icon: \"none\",\n          duration: 1500\n        });\n      } else if (status === 2) {\n        wepy.showToast({\n          title: \"问卷已结束\",\n          icon: \"none\",\n          duration: 1500\n        });\n      }\n    }\n  };\n  async getQuestionnaires() {\n    let that = this;\n    let questionnaires = await getAllQuestionnaires();\n    if (questionnaires.data !== null) {\n      that.questionnaires = this.sortQuestionnaires(questionnaires.data.data);\n    } else {\n      await wepy.showToast({\n        title: \"获取问卷信息失败,请重试\",\n        icon: \"none\",\n        duration: 1500\n      });\n    }\n    this.questionnaires.map(item => {\n      item.deadline = this.getRelativeDeadline(item.deadline);\n    });\n    this.$apply();\n  }\n  sortQuestionnaires(qArray) {\n    let arr0 = [];\n    let arr1 = [];\n    let arr2 = [];\n    qArray.map(item => {\n      if (item.status === 0) {\n        arr0.push(item);\n      } else if (item.status === 1) {\n        arr1.push(item);\n      } else if (item.status === 2) {\n        arr2.push(item);\n      }\n    });\n    arr0.sort(this.sortTimeStamp(\"timestamp\"));\n    arr1.sort(this.sortTimeStamp(\"timestamp\"));\n    arr2.sort(this.sortTimeStamp(\"timestamp\")).reverse();\n    return arr0.concat(arr1, arr2);\n  }\n  sortTimeStamp(t) {\n    return (a, b) => a[t] - b[t];\n  }\n  getRelativeDeadline(timestamp) {\n    let currentTimestamp = Date.parse(new Date());\n    let due = !(timestamp - currentTimestamp >= 0);\n    let days = parseInt((timestamp - currentTimestamp) / (1000 * 60 * 60 * 24));\n    if (!due) {\n      if (days === 0) {\n        return \"今天截止\";\n      } else {\n        return timestamp === 3489458895000 || timestamp === 1356019200000\n          ? \"长期有效\"\n          : days + \"天后截止\";\n      }\n    } else {\n      let absDays = Math.abs(days);\n      if (absDays < 7) {\n        return absDays + \"天前\";\n      } else if (absDays >= 7 && absDays < 30) {\n        return parseInt(absDays / 7) + \"周前\";\n      } else if (absDays >= 30 && absDays < 365) {\n        return parseInt(absDays / 30) + \"月前\";\n      } else if (absDays >= 365) {\n        return parseInt(absDays / 365) + \"年前\";\n      }\n    }\n  }\n  async init() {\n    // let that = this;\n    // let login = await this.$parent.axios({\n    //   url:\n    //     this.$parent.globalData.config.questionnaireWithAuth +\n    //     wepy.getStorageSync(\"token\"),\n    //   method: \"GET\"\n    // });\n    wepy.showLoading({\n      title: \"加载中\"\n    });\n    let login = await questionnaireWithAuth(wepy.getStorageSync(\"token\"));\n    if (login.data) {\n      wepy.setStorageSync(\"questionnaire_token\", login.data.data);\n    }\n    await this.getQuestionnaires();\n    wepy.hideLoading();\n  }\n  onLoad(op) {\n    // this.avatar = wepy.getStorageSync(\"User\").nativeInformation.avatar;\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    if (!this.visitorModeStatus) {\n      this.judgeStatus(op.name).then(() => {\n        this.username = wepy.getStorageSync(\"User\").name;\n        this.init();\n        this.$apply();\n      });\n    } else {\n      this.$redirect({\n        url: \"../../../others-page/pages/close\"\n      });\n    }\n  }\n  onShow() {\n    const getPage = this.getCurrentPages();\n    const nowPage = getPage[getPage.length - 1];\n    this.questionnaires = nowPage.data.questionnaires;\n  }\n}\n</script>\n\n\n<style lang=\"stylus\" scoped>\n.container\n  font-size 24rpx\n  .container-header\n    padding 0 60rpx\n    display flex\n    flex-direction row\n    align-items center\n    height 160rpx\n    .header-avatar\n      height 66rpx\n      width 66rpx\n      border-radius 50%\n      margin-right 28rpx\n      overflow hidden\n      box-shadow 0 0 10rpx 0 rgba(56, 138, 255, 0.15)\n    .header-username\n      font-family PingFangSC-Semibold\n      color #353535\n      font-size 36rpx\n  .container-body\n    padding 0 44rpx\n    .questionnaire-card\n      padding 30rpx\n      min-height 90rpx\n      box-shadow 0rpx 2rpx 12rpx 0rpx rgba(219, 219, 219, 0.5)\n      border-radius 16rpx\n      margin-bottom 20rpx\n      display flex\n      flex-direction column\n      justify-content center\n      background #fff\n      .card-title\n        font-family PingFangSC-Medium\n        font-size 32rpx\n        color #353535\n        margin-bottom 4rpx\n      .card-detail\n        display flex\n        flex-direction row\n        .detail-status\n          margin-right 40rpx\n        .detail-status-unfinished\n          color #d0021b\n        .detail-status-finished\n          color #7ed321\n        .detail-deadline\n          color #9b9b9b\n    .questionnaire-card:last-child\n      margin-bottom 40rpx\n    .questionnaire-card-finished\n      background #f2f2f2\n      box-shadow none\n  .container-footer\n    text-align center\n    font-size 20rpx\n    color #9a9a9a\n</style>\n"
  },
  {
    "path": "src/others-page/pages/questionnairePages/questionnaire.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"questionnaire-header\">\n      <view class=\"header-title\">{{ title }}(匿名)</view>\n      <view class=\"header-detail\">\n        <view>来源：{{ source }}</view>\n        <view>时间：{{ deadline }}{{ relativeDate }}</view>\n      </view>\n      <view class=\"header-circle\">\n        <view class=\"header-circle-1\"></view>\n        <view class=\"header-circle-2\"></view>\n        <view class=\"header-circle-3\"></view>\n        <view class=\"header-circle-4\"></view>\n      </view>\n    </view>\n    <view class=\"questionnaire-line\"></view>\n    <view class=\"questionnaire-content\">\n      <repeat for=\"{{ questions }}\" index=\"qIndex\" key=\"qItem\" item=\"qItem\">\n        <view class=\"question-title\">{{ qItem.id }}. {{ qItem.content }}<span>{{ qItem.required?\"*\":\"\" }}</span></view>\n        <view class=\"question-card {{qItem.type=='single'?'radio-box-container':''}}\">\n          <repeat for=\"{{ qItem.answer }}\" index=\"aIndex\" key=\"aItem\" item=\"aItem\">\n            <view class=\"answerItem radioItem shadow-box\" @tap=\"checkbox\" data-qIndex=\"{{ qIndex }}\" data-aIndex=\"{{ aIndex }}\" data-type=\"radio\">\n              <view class=\"answer-radiobox {{ aItem.checked?'answer-radiobox-ontap':'' }}\">\n                <view class=\"radiobox-circle {{ aItem.checked?'radiobox-circle-ontap':'' }}\"></view>\n              </view>\n              <div class=\"answer-content {{ aItem.checked?'answer-content-ontap':'' }}\">{{aItem.value}}</div>\n            </view>\n          </repeat>\n        </view>\n        <view class=\"question-card shadow-box {{qItem.type=='multiple'?'check-box-container':''}}\">\n          <repeat for=\"{{ qItem.answer }}\" index=\"aIndex\" key=\"aItem\" item=\"aItem\">\n            <view class=\"answerItem checkItem\" @tap=\"checkbox\" data-qIndex=\"{{ qIndex }}\" data-aIndex=\"{{ aIndex }}\" data-type=\"check\">\n              <view class=\"answer-checkbox {{ aItem.checked?'answer-checkbox-ontap':'' }}\">\n                <image class=\"checkbox-tick {{ aItem.checked?'checkbox-tick-ontap':'' }}\" mode=\"aspectFit\" src=\"https://static.airbob.org/under-graduate/tick.svg\" />\n              </view>\n              <div class=\"answer-content {{ aItem.checked?'answer-content-ontap':'' }}\">{{aItem.value}}</div>\n            </view>\n          </repeat>\n        </view>\n        <view class=\"question-card {{qItem.type=='textA'?'input-container':''}}\">\n          <input class=\"answerItem inputItem boxshadow {{ inputOnTap?'boxshadow-onfocus':'' }}\" placeholder-class=\"placeholderClass\" placeholder=\"{{qItem.answer}}\" @focus=\"showboxshadow\" @blur=\"hideboxshadow\" @input=\"textInput\" data-qIndex=\"{{ qIndex }}\" data-type=\"input\"\n          />\n        </view>\n        <view class=\"question-card {{qItem.type=='textB'?'textarea-container':''}}\">\n          <textarea class=\"answerItem textareaItem boxshadow {{ textareaOnTap?'boxshadow-onfocus':'' }}\" placeholder-class=\"placeholderClass\" placeholder=\"{{qItem.answer}}\" @focus=\"showboxshadow\" @blur=\"hideboxshadow\" @input=\"textInput\" data-qIndex=\"{{ qIndex }}\"\n            data-type=\"textarea\" />\n        </view>\n      </repeat>\n      <button class=\"save-submit-btn\" @tap=\"submitQuestionnaire\">保存并提交</button>\n    </view>\n  </view>\n</template>\n\n<script>\n  import wepy from \"wepy\";\n  import navigation from \"@/components/qy-navigation\";\n  import { getQuestionnaireInfo, submitQuestionnaire } from \"@/api/questionnaire\";\n  export default class extends wepy.page {\n    config = {\n      navigationBarTitleText: \"\"\n    };\n    components = {\n      \"qy-navigation\": navigation\n    };\n    data = {\n      navTitle: \"问卷测评\",\n      inputOnTap: false,\n      textareaOnTap: false,\n      title: \"\",\n      questionnaireId: \"\",\n      source: \"\",\n      deadline: \"\",\n      relativeDate: \"\",\n      questions: [],\n      completed: true\n    };\n    methods = {\n      showboxshadow(e) {\n        let type = e.currentTarget.dataset.type;\n        if (type === \"textarea\") {\n          this.textareaOnTap = true;\n        } else if (type === \"input\") {\n          this.inputOnTap = true;\n        }\n        this.$apply();\n      },\n      hideboxshadow(e) {\n        let type = e.currentTarget.dataset.type;\n        if (type === \"textarea\") {\n          this.textareaOnTap = false;\n        } else if (type === \"input\") {\n          this.inputOnTap = false;\n        }\n        this.$apply();\n      },\n      checkbox(e) {\n        let qIndex = Number(e.currentTarget.dataset.qindex);\n        let aIndex = Number(e.currentTarget.dataset.aindex);\n        let type = e.currentTarget.dataset.type;\n        let answer = this.questions[qIndex].answer;\n        if (type === \"radio\") {\n          for (let i in answer) {\n            if (Number(i) === aIndex) {\n              this.questions[qIndex].answer[i].checked = !answer[i].checked;\n            } else {\n              this.questions[qIndex].answer[i].checked = false;\n            }\n          }\n        } else if (type === \"check\") {\n          this.questions[qIndex].answer[aIndex].checked = !answer[aIndex].checked;\n        }\n        this.$apply();\n      },\n      textInput(e) {\n        let qIndex = Number(e.currentTarget.dataset.qindex);\n        this.questions[qIndex].answer = e.detail.value;\n      }\n    };\n    async getQuestionnaire() {\n      let that = this;\n      let questionnaire = await getQuestionnaireInfo(that.questionnaireId);\n      if (questionnaire.data.success) {\n        that.questions = questionnaire.data.data.questions;\n        that.title = questionnaire.data.data.name;\n        let timestamp = questionnaire.data.data.deadline;\n        if (timestamp !== 1356019200000 && timestamp !== 3489458895000) {\n          that.deadline =\n            new Date(questionnaire.data.data.deadline)\n              .toLocaleDateString()\n              .replace(/\\//g, \".\") + \" \";\n        } else {\n          that.deadline = \"\";\n        }\n      } else {\n        await wepy.showToast({\n          title: \"获取问卷信息失败,请重试\",\n          icon: \"none\",\n          duration: 1500\n        });\n      }\n    }\n    async submitQuestionnaire() {\n      let answerArray = [];\n      let that = this;\n      this.completed = true;\n      this.questions.map(item => {\n        let answer = this.getQuestionAnswer(item);\n        if (answer || answer === \"\") {\n          answerArray.push({\n            answer: answer,\n            id: item.id,\n            type: item.type\n          });\n        } else {\n          this.completed = false;\n        }\n      });\n      this.$apply();\n      if (this.completed) {\n        let postQuestionnaire = await submitQuestionnaire(\n          that.questionnaireId,\n          answerArray\n        );\n        wepy.showLoading({\n          title: \"提交中\"\n        });\n        setTimeout(() => {\n          wepy.hideLoading();\n          if (postQuestionnaire.data.success) {\n            wepy.showToast({\n              title: \"提交成功\",\n              icon: \"none\",\n              duration: 1500\n            });\n            const page = this.getCurrentPages();\n            page[page.length - 2].data.questionnaires.map(item => {\n              if (this.questionnaireId === item.questionId) {\n                item.status = 1;\n              }\n            });\n            wepy.navigateBack({\n              delta: 1\n            });\n          } else if (postQuestionnaire.data.errCode === 425) {\n            wepy.showToast({\n              title: \"已经提交过一次了哦\",\n              icon: \"none\",\n              duration: 1500\n            });\n          } else {\n            wepy.showToast({\n              title: \"提交失败,请重试\",\n              icon: \"none\",\n              duration: 1500\n            });\n          }\n        }, 1000);\n      } else {\n        wepy.showToast({\n          title: \"问卷尚未填写完整\",\n          icon: \"none\",\n          duration: 1500\n        });\n      }\n    }\n    getQuestionAnswer(item) {\n      let indexArray = [];\n      if (item.type === \"single\" || item.type === \"multiple\") {\n        for (let i in item.answer) {\n          if (item.answer[i].checked) {\n            indexArray.push(i);\n          }\n        }\n        if ((item.required && indexArray.length !== 0) || !item.required) {\n          return indexArray;\n        } else {\n          return false;\n        }\n      } else {\n        if ((item.required && !/^\\s*$/.test(item.answer)) || !item.required) {\n          return item.answer;\n        } else {\n          return false;\n        }\n      }\n    }\n    async init() {\n      if (wepy.getStorageSync(\"token\") && wepy.getStorageSync(\"User\").enabled) {\n        await this.getQuestionnaire();\n        this.questions.map(item => {\n          let answer = item.answer;\n          if (item.type === \"single\" || item.type === \"multiple\") {\n            for (let i in answer) {\n              item.answer[i] = {\n                value: answer[i],\n                checked: false\n              };\n            }\n          } else {\n            item.answer = answer[0];\n          }\n        });\n        this.$apply();\n      } else {\n        wepy.reLaunch({\n          url: \"../../pages/login\"\n        });\n      }\n    }\n    onLoad(options) {\n      this.questionnaireId = options.questionnaireId;\n      this.relativeDate = options.deadline;\n      this.source = options.assignName;\n      this.$apply();\n      this.init();\n    }\n  }\n</script>\n\n<style lang=\"stylus\" scoped>\n.container\n  display flex\n  flex-direction column\n  .questionnaire-header\n    padding 60rpx 60rpx 40rpx 60rpx\n    position relative\n    overflow hidden\n    .header-title\n      font-size 40rpx\n      font-family PingFangSC-Semibold\n      color #195498\n      margin-bottom 16rpx\n    .header-detail\n      font-size 24rpx\n      color #9a9a9a\n    .header-circle\n      .header-circle-1\n        height 16rpx\n        width 16rpx\n        border-radius 50%\n        border solid 8rpx rgba(230, 241, 255, 1)\n        position absolute\n        right 310rpx\n        bottom 130rpx\n        z-index -2\n      .header-circle-2\n        height 30rpx\n        width 30rpx\n        border-radius 50%\n        border solid 12rpx rgba(230, 242, 255, 1)\n        position absolute\n        right 260rpx\n        bottom 80rpx\n        z-index -2\n      .header-circle-3\n        width 90rpx\n        height 90rpx\n        border-radius 50%\n        border solid 24rpx rgba(230, 242, 255, 1)\n        position absolute\n        right 120rpx\n        bottom -20rpx\n        z-index -2\n      .header-circle-4\n        width 150rpx\n        height 150rpx\n        border-radius 50%\n        border solid 36rpx rgba(221, 237, 255, 1)\n        position absolute\n        bottom -14rpx\n        right -14rpx\n        z-index -1\n  .questionnaire-line\n    background #f5f5f5\n    height 14rpx\n    width 100%\n  .questionnaire-content\n    padding 40rpx 50rpx\n    .question-title\n      font-size 32rpx\n      color #353535\n      margin 0 10rpx\n      span\n        color #d0021b\n    .question-card\n      display none\n      .placeholderClass\n        color #9a9a9a\n    .radio-box-container, .check-box-container, .input-container, .textarea-container\n      display block\n      overflow hidden\n    .radio-box-container, .input-container, .textarea-container\n      padding 20rpx 10rpx 40rpx 10rpx\n    .check-box-container\n      margin 20rpx 10rpx 40rpx 10rpx\n    .answerItem\n      min-height 50rpx\n      display flex\n      flex-direction row\n      align-items center\n      padding 22rpx\n      width auto\n      .answer-radiobox, .answer-checkbox\n        margin-right 20rpx\n        height 34rpx\n        min-width 34rpx\n        border solid 2rpx #9a9a9a\n        display flex\n        align-items center\n        justify-content center\n      .answer-radiobox\n        border-radius 50%\n        .radiobox-circle\n          height 18rpx\n          width 18rpx\n          background #4a90e2\n          display none\n          border-radius 50%\n        .radiobox-circle-ontap\n          display block\n      .answer-checkbox\n        border-radius 4rpx\n        .checkbox-tick\n          display none\n          height 30rpx\n          width 30rpx\n        .checkbox-tick-ontap\n          display block\n      .answer-radiobox-ontap, .answer-checkbox-ontap\n        border solid 2rpx #4a90e2\n      .answer-content\n        color #9a9a9a\n      .answer-content-ontap\n        color #4a90e2\n    .radioItem\n      margin-bottom 20rpx\n    .radioItem:last-child\n      margin-bottom 0\n    .checkItem\n      border-bottom solid 2rpx rgba(219, 219, 219, 0.5)\n    .checkItem:last-child\n      border none\n    .textareaItem\n      height 160rpx\n      padding 20rpx 26rpx\n    .save-submit-btn\n      border solid 2rpx rgba(219, 219, 219, 0.5)\n      border-radius 14rpx\n      background #4a90e2\n      font-size 32rpx\n      margin 20rpx 10rpx\n      color #fff\n.shadow-box\n  background-color rgba(255, 255, 255, 0.34)\n  box-shadow 0rpx 0rpx 10rpx 0rpx rgba(219, 219, 219, 0.5)\n  border-radius 14rpx\n  border solid 2rpx rgba(219, 219, 219, 0.5)\n.shadow-box:hover\n  box-shadow 0rpx 0rpx 10rpx 0rpx #4a90e2\n  border solid 2rpx #4a90e2\n.boxshadow\n  background-color rgba(255, 255, 255, 0.34)\n  box-shadow 0rpx 0rpx 10rpx 0rpx rgba(219, 219, 219, 0.5)\n  border-radius 14rpx\n  border solid 2rpx rgba(219, 219, 219, 0.5)\n.boxshadow-onfocus\n  box-shadow 0rpx 0rpx 10rpx 0rpx #4a90e2\n  border solid 2rpx #4a90e2\n</style>\n"
  },
  {
    "path": "src/others-page/pages/run.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\" :passwordModelOptions.sync=\"passwordModelOptions\">\n    <view slot=\"qy-content\" class=\"run-container\">\n      <view class=\"circle\">\n        <view class=\"scale-text-container\">\n          <view class=\"scale-text-top\">60</view>\n          <view class=\"scale-text-right\">15</view>\n          <view class=\"scale-text-bottom\">30</view>\n          <view class=\"scale-text-left\">45</view>\n        </view>\n        <view class=\"circle-times\">{{runTimes}}</view>\n        <view class=\"clock-container\">\n          <repeat for=\"{{Arrs}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"scale\" style=\"height:{{item.height}}rpx;transform:rotate({{index*6}}deg);left:{{item.left}}rpx;top:{{item.top}}rpx;background:{{item.color}}\"></view>\n          </repeat>\n        </view>\n      </view>\n      <view class=\"run-history-btn\" @tap.stop=\"handleRunHistoryItem\">\n        <view class=\"run-history-btn-text\">历史跑操记录>></view>\n      </view>\n      <view class=\"run-history-card-container\" hidden=\"{{runHistoryHidden}}\" @tap=\"handleRunHistoryItemHidden\">\n        <view class=\"run-history-card\">\n          <text class=\"run-history-card-title\">历史跑操记录</text>\n          <repeat for=\"{{runHistoryData}}\" key=\"index\" index=\"index\" item=\"item\">\n              <view class=\"run-history-card-item\">\n                <view style=\"font-size:18px;transform:translateY(3px)\"><text style=\"font-size:36px\">{{item.count}}</text>次</view>\n                <view class=\"run-history-card-item-term\">\n                  <view>{{item.year}}</view>\n                  <view>{{item.semester}}</view>\n                </view>\n              </view>\n          </repeat>\n          <!-- <view hidden=\"{{runHistoryData.length}}\">\n            <text class=\"run-history-nohistory\">暂时没有您的跑操记录~</text>\n          </view> -->\n        </view>\n      </view>\n      <view class=\"divide\" style=\"margin-top:15rpx\"></view>\n      <view class=\"runtime-column\">\n        <view class=\"runtime-item\"><view>奖惩记录</view><view class=\"runtime-item-score\">{{rewordRecord}}</view></view>\n        <view class=\"runtime-item\"><view>年级最多</view><view class=\"runtime-item-score\">{{maxCount}}</view></view>\n        <view class=\"runtime-item\" style=\"border:none\"><view>年级排行</view><view class=\"runtime-item-score\">{{Rank}}</view></view>\n      </view>\n    <view class=\"divide\" wx:if=\"{{runPosterBtn.isShow}}\"></view>\n      <view class='run-poster' wx:if=\"{{runPosterBtn.isShow}}\">\n          <view class='run-poster-title'>你已经完成跑操<span>{{runTimes}}</span>次啦！</view>\n          <view class='run-poster-btn'>\n            <view class=\"run-poster-btn-text\" @tap.stop=\"handleRunPosterModal\">生成海报>></view>\n          </view>\n      </view>\n      <view class='run-poster-modal-container' hidden=\"{{runPosterHidden}}\" @tap=\"handleRunPosterModalHidden\" catchtouchmove=\"ture\">\n        <view class='run-poster-modal'>\n          <canvas class='run-poster-modal-img' canvas-id=\"run-poster-modal-img\" id=\"run-poster-modal-img\"></canvas>\n          <view class=\"run-poster-modal-btn\" @tap='saveRunPoster'>\n            <p>保存到本地</p>\n          </view>\n        </view>\n      </view>\n      <view class=\"divide\"></view>\n      <view>\n        <repeat for=\"{{runDetails}}\" index=\"index\" key=\"key\" item=\"item\">\n          <view class=\"card-item\" style=\"color:{{item.finish ? '#fff' : '#000'}};background-image:url({{item.finish ? 'https://static.airbob.org/under-graduate/run_pic_card_success.png' : 'https://static.airbob.org/under-graduate/run_pic_card_fail.png'}})\">\n          <view>{{item.date}}</view>\n          <view>{{item.time}}</view>\n          </view>\n        </repeat>\n      </view>\n      <view wx:if=\"{{!runDetails[0]}}\">\n        <view class=\"no-result\"></view>\n        <view class=\"no-result-content\">赶快起床跑步啦！</view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport {\n  getExercise,\n  getRunHistory,\n  changeSecretCode,\n  commonInformation\n} from \"@/api/common\";\nimport { mockGetExercise, mockGetRunHistory } from \"@/mock/common\";\nimport JudgeStatus from \"@/mixins/module\";\nimport navigation from \"@/components/qy-navigation\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"晨跑\"\n  };\n  components = {\n    \"qy-navigation\": navigation,\n    BaseContainer\n  };\n  data = {\n    navTitle: \"晨跑\",\n    Arrs: [],\n    runTimes: 0,\n    rewordRecord: \"无\",\n    Rank: \"\",\n    maxCount: \"\",\n    runDetails: [],\n    runHistoryHidden: true,\n    runPosterBtn: {\n      isShow: false,\n      isFreshmen: false\n    },\n    runPosterHidden: true,\n    runHistoryData: [],\n    passwordModelOptions: {\n      passwordModelProps: false,\n      placeholder: \"请输入体育部密码\",\n      refreshData: this.loadHistory,\n      bindInfo: {\n        username: wepy.getStorageSync(\"User\").studentId,\n        domainType: \"2\"\n      }\n    },\n    visitorModeStatus: false\n  };\n  mixins = [JudgeStatus];\n  methods = {\n    handleRunHistoryItem() {\n      this.loadHistory();\n    },\n    handleRunHistoryItemHidden() {\n      this.runHistoryHidden = true;\n    },\n    handleRunPosterModal() {\n      this.drawRunPoster();\n      this.runPosterHidden = false;\n    },\n    handleRunPosterModalHidden() {\n      this.runPosterHidden = true;\n    }\n  };\n  async saveRunPoster() {\n    wx.canvasToTempFilePath({\n      destWidth: 605,\n      destHeight: 1075,\n      canvasId: \"run-poster-modal-img\",\n      success(res) {\n        wx.saveImageToPhotosAlbum({\n          filePath: res.tempFilePath,\n          success(res) {\n            wepy.showToast({\n              title: \"成功保存~\"\n            });\n          },\n          fail() {\n            wepy.showToast({\n              title: \"保存失败\",\n              icon: \"none\"\n            });\n          }\n        });\n      }\n    });\n  }\n  async drawRunPoster() {\n    let index = 0;\n    let extra = this.rewordRecord;\n    let tempRunDetails = JSON.parse(JSON.stringify(this.runDetails));\n    let posterDate = tempRunDetails[0][\"date\"];\n    if (extra === \"无\") extra = 0;\n    tempRunDetails.reverse().forEach(item => {\n      if (item.finish) {\n        index++;\n        if (\n          (index + extra == 25 && this.runPosterBtn.isFreshmen) ||\n          (index + extra == 35 && !this.runPosterBtn.isFreshmen)\n        ) {\n          posterDate =\n            tempRunDetails.length === 0 ? \"xxxx-xx-xx\" : item[\"date\"];\n        }\n      }\n    });\n    wepy.showLoading({\n      title: \"海报生成中...\"\n    });\n    wx.downloadFile({\n      url: this.runPosterBtn.isFreshmen\n        ? \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LTI1dGltZXMuanBn\"\n        : \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LVJ1blBvc3Rlci5KUEc=\",\n      success: res => {\n        wx.getImageInfo({\n          src: res.tempFilePath,\n          success: res => {\n            const ctx = wx.createCanvasContext(\"run-poster-modal-img\");\n            let canvasWidth = wx.getSystemInfoSync().windowWidth;\n            let WIDTH = (605 / 750) * canvasWidth;\n            let HEIGHT = (1075 / 750) * canvasWidth;\n            ctx.drawImage(res.path, 0, 0, WIDTH, HEIGHT);\n            ctx.setTextAlign(\"center\");\n            ctx.setFillStyle(\"#a50a0a\");\n            ctx.font = \"22rpx STXingkai\";\n            ctx.fillText(posterDate.slice(5, 7), 0.17 * WIDTH, 0.39 * HEIGHT);\n            ctx.fillText(posterDate.slice(8, 10), 0.31 * WIDTH, 0.39 * HEIGHT);\n            ctx.draw();\n          }\n        });\n      },\n      complete: () => {\n        wepy.hideLoading();\n      }\n    });\n  }\n  async loadHistory() {\n    const { data: historyData } = this.visitorModeStatus\n      ? await mockGetRunHistory()\n      : await getRunHistory();\n    if (historyData && historyData.success) {\n      if (historyData.data.runningCountInfos === null) {\n        this.runHistoryHidden = true;\n        wepy.showModal({\n          content: \"暂时没有您的历史记录\",\n          confirmText: \"知道了\",\n          showCancel: false,\n          confirmColor: \"#353535\"\n        });\n      } else {\n        const temp = historyData.data.runningCountInfos.map((item, index) => {\n          const year = item.term.slice(0, 4);\n          const term = item.term.slice(item.term.length - 2);\n          item.year = `${year}-${Number(year) + 1}学年`;\n          item.semester = `第${parseInt(term) === 1 ? \"一\" : \"二\"}学期`;\n          return item;\n        });\n        this.runHistoryData = temp.filter(item => item.count !== \"0\");\n        this.passwordModelOptions.passwordModelProps = false;\n        if (this.runHistoryData.length === 0) {\n          this.runHistoryHidden = true;\n          wepy.showModal({\n            content: \"暂时没有您的历史记录\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          });\n        } else {\n          this.runHistoryHidden = false;\n        }\n      }\n    } else {\n      this.runHistoryHidden = true;\n      this.passwordModelOptions.passwordModelProps = true;\n    }\n    this.$apply();\n  }\n  async onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    this.judgeStatus(op.name);\n    let reg = /[\\u4e00-\\u9fa5]/;\n    let runtime = this.visitorModeStatus\n      ? await mockGetExercise()\n      : await getExercise();\n    this.runTimes = runtime.data.data.totalCount;\n    this.maxCount = runtime.data.data.maxCount;\n    this.Rank = parseInt(runtime.data.data.rankingPercent * 100) + \"%\";\n    this.rewordRecord =\n      runtime.data.data.extraCount === 0 || runtime.data.data.extraCount === \"0\"\n        ? \"无\"\n        : runtime.data.data.extraCount;\n    let details = runtime.data.data.recordTimeList;\n    let spareGender = wepy.getStorageSync(\"userInfo\").gender === \"女\" ? 2 : 1;\n    let gender =\n      wepy.getStorageSync(\"User\").nativeInformation.gender === 0\n        ? spareGender\n        : wepy.getStorageSync(\"User\").nativeInformation.gender;\n    details.forEach((item, index) => {\n      let start = item.start.split(reg);\n      let end = item.end.split(reg);\n      let time;\n      if (\n        end[3] === undefined ||\n        end[4] === undefined ||\n        end[3] === \"undefined\" ||\n        end[4] === \"undefined\"\n      ) {\n        time = start[3] + \":\" + start[4];\n      } else {\n        time = start[3] + \":\" + start[4] + \"~\" + end[3] + \":\" + end[4];\n      }\n      let isFinish = this.visitorModeStatus\n        ? true\n        : Math.abs(\n            parseInt((start[3] - end[3]) * 60) +\n              parseInt(start[4]) -\n              parseInt(end[4])\n          ) <= (gender === 2 ? 13 : 11);\n      this.runDetails.push({\n        date: start[0] + \"-\" + start[1] + \"-\" + start[2],\n        time: time,\n        finish: isFinish\n      });\n    });\n    this.$apply();\n    for (let i = 0; i < 60; i++) {\n      let left = 240 * Math.sin(((6 * i) / 180) * Math.PI);\n      let top = 240 - 240 * Math.cos(((6 * i) / 180) * Math.PI);\n      let color = \"#D0F5FF\";\n      let height = 24;\n      if (i % 15 === 0) {\n        height = 48;\n        top -= 12;\n        switch (i) {\n          case 0:\n            top += 12;\n            break;\n          case 15:\n            left -= 12;\n            break;\n          case 30:\n            top -= 12;\n            break;\n          case 45:\n            left += 12;\n            break;\n        }\n      }\n      this.Arrs.push({\n        left: left,\n        top: top,\n        color: color,\n        height: height,\n        id: i\n      });\n    }\n    for (let i = 0; i <= this.runTimes; i++) {\n      var timeOut = setTimeout(() => {\n        if (i === 0 && this.runTimes >= 60) {\n          this.Arrs[i].color = \"#FFCE43\";\n        } else if (i === 0 && this.runTimes < 60) {\n          this.Arrs[i + 1].color = \"#FFCE43\";\n          this.Arrs[i].color = \"#D0F5FF\";\n        } else if (i !== 0) {\n          this.Arrs[i + 1].color = \"#FFCE43\";\n          this.$apply();\n        }\n        clearTimeout(timeOut);\n      }, i * 100);\n    }\n    this.$apply();\n    const { data: commonInfo } = await commonInformation();\n    if (\n      commonInfo.data.semester.slice(5, 6) == 1 &&\n      commonInfo.data.year.slice(2, 4) ==\n        wepy.getStorageSync(\"User\").nativeInformation.studentId.slice(1, 3)\n    )\n      this.runPosterBtn[\"isFreshmen\"] = true;\n    if (this.runPosterBtn[\"isFreshmen\"]) {\n      if (this.runTimes >= 25) this.runPosterBtn[\"isShow\"] = true;\n    } else {\n      if (this.runTimes >= 35) this.runPosterBtn[\"isShow\"] = true;\n    }\n    if (op.showPoster) {\n      this.runPosterHidden = false;\n    }\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.run-container\n  max-width 750rpx\n  width 750rpx\n  overflow hidden\n  .circle\n    position relative\n    margin 0 auto\n    width 500rpx\n    height 500rpx\n    border 10rpx solid #89E1FB\n    border-radius 50%\n    padding 10rpx\n    overflow hidden\n    .circle-times\n      display fixed\n      position relative\n      line-height 500rpx\n      height 500rpx\n      font-size 180rpx\n      color #3CE2BB\n      text-align center\n      overflow hidden\n    .clock-container\n      position absolute\n      width 480rpx\n      height 480rpx\n      top 10rpx\n      left 260rpx\n      .scale\n        position absolute\n        width 5rpx\n        height 25rpx\n        background #D0F5FF\n    .scale-text-container\n      position absolute\n      margin 0 auto\n      width 500rpx\n      height 500rpx\n      font-size 18rpx\n      color #888888\n      .scale-text-top\n        position absolute\n        top 60rpx\n        left 240rpx\n      .scale-text-bottom\n        position absolute\n        bottom 60rpx\n        left 240rpx\n      .scale-text-left\n        position absolute\n        top 240rpx\n        left 60rpx\n      .scale-text-right\n        position absolute\n        top 240rpx\n        right 60rpx\n  .divide\n    height 25rpx\n    width 750rpx\n    background #F5F5F5\n  .runtime-column\n    padding 24rpx 60rpx\n    display flex\n    justify-content space-around\n    align-items center\n    font-size 30rpx\n    color #888888\n    text-align center\n    .runtime-item\n      width 33%\n      border-right 1rpx solid #F3F3F3\n      .runtime-item-score\n        color #353535\n        font-size 36rpx\n  .run-poster\n    display flex\n    align-items center\n    font-size 30rpx\n    height 100rpx\n    padding 10rpx\n    .run-poster-title\n      color #353535\n      width 58%\n      text-align center\n      span\n        color #ed2f6a\n    .run-poster-btn\n      width 30%\n      background-color #6AE4FF\n      border 10rpx solid #89E1FB\n      border-radius 20rpx\n      color white\n      padding 10rpx 20rpx\n      text-align center\n      .run-poster-btn-text\n        font-size 30rpx\n  .run-poster-modal-container\n    position fixed\n    width 100%\n    height 100%\n    background rgba(0, 0, 0, 0.5)\n    z-index 200\n    top 0px\n    left 0px\n    .run-poster-modal\n      position fixed\n      z-index 201\n      top 55%\n      left 50%\n      transform translate(-50%,-50%)\n      .run-poster-modal-img\n        width 605rpx\n        height 1075rpx\n        background-color #fff\n        z-index 202\n      .run-poster-modal-btn\n        background-color #6AE4FF\n        border 10rpx solid #89E1FB\n        color #fff\n        width 500rpx\n        height 60rpx\n        border-radius 50rpx\n        z-index 202\n        margin 20rpx auto\n        text-align center\n        line-height 60rpx\n  .card-item\n    position relative\n    display flex\n    align-items center\n    width 666rpx\n    margin 0 auto\n    height 130rpx\n    background #fff\n    color #000\n    font-size 32rpx\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n    justify-content space-around\n  .run-history-btn\n    border 2px solid bule\n    margin-top 15px\n    margin-bottom 15px\n    display flex\n    justify-content center\n    align-items center\n    .run-history-btn-text\n      height 25px\n      text-align center\n      color white\n      background-image url('https://static.airbob.org/run-radius1/QjE2MDEyMzI3LXJhZGl1czEucG5n');\n      background-color #18e0f7\n      background-position: center center;\n      background-size: cover;\n      background-repeat: no-repeat;\n      border 2px solid #89e1fb\n      border-radius 13px\n      padding 0\n      width 60vw\n      font-size 17px\n  .run-history-card-container\n    position fixed\n    width 100%\n    height 100%\n    background rgba(0, 0, 0, 0.5)\n    z-index 200\n    top 0px\n    left 0px\n    .run-history-card\n      position absolute\n      top 20vh\n      left 10vw\n      width 80vw\n      height 60vh\n      background-image url('https://static.airbob.org/run-radius2/QjE2MDEyMzI3LXJhZGl1czIucG5n')\n      background-position: center center;\n      background-size: cover;\n      background-repeat: no-repeat;\n      // background-color #52e2df\n      display flex\n      flex-direction column\n      align-items center\n      border-radius 10px\n      .run-history-nohistory\n        color #708090\n      .run-history-card-title\n        color white\n        margin-top 25px\n        font-size 23px\n        margin-bottom 35px\n        font-weight 100\n      .run-history-card-item\n        height 56px\n        border-radius 28px\n        width 67vw\n        margin-top 10px\n        margin-bottom 10px\n        display flex\n        justify-content space-around\n        background-color #a4f1ed\n        .run-history-card-item-term\n          font-size 15px\n          transform:translateY(5px)\n.no-result\n  position relative\n  top 66rpx\n  width 500rpx\n  height 400rpx\n  background-image url('https://static.airbob.org/under-graduate/%E7%BC%BA%E7%9C%81%E9%A1%B5_%E7%A9%BA.png')\n  background-position center\n  background-repeat no-repeat\n  background-size contain\n  margin 0 auto\n.no-result-content\n  position relative\n  padding-top 56rpx\n  margin 0 auto\n  text-align center\n  color #999CA0\n  font-size 28rpx\n.bind-container\n  display flex\n  flex-direction column\n  align-items center\n  background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n  background-repeat no-repeat\n  height 485rpx\n  border-radius 30rpx\n  background-size cover\n  .bind-input\n    font-size 26rpx\n    margin 221rpx 0 56rpx\n    width 438rpx\n    border-bottom 2rpx solid #999CA0\n  .bind-button\n    margin-top 26rpx\n    background-color #6AE4FF\n    text-align center\n    width 410rpx\n    height 80rpx\n    line-height 80rpx\n    color #ffffff\n    border-radius 50px\n</style>\n"
  },
  {
    "path": "src/others-page/pages/school-bus.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <view class=\"cover-container {{isModalOpen ? 'active' : ''}}\" hidden=\"{{!isModalOpen}}\" @tap.stop=\"changeModalStatus\" catchtouchmove=\"stopTouchMove\">\n        <view class=\"cover-modal\" hidden=\"{{!isModalOpen}}\" @tap.stop=\"prevent\">\n          <view class=\"text margin\">1、所有人员均凭智慧校园卡刷卡乘车，每次2元。</view>\n          <view class=\"text\">2、仙林校区内停靠站点。①由市区进入仙林校区的站点依次为：1号楼、行政楼、2号楼、5号楼、西门配电房、2食堂、大学生活动中心转盘、学科楼转盘、青教公寓；</view>\n          <view class=\"text margin\">②仙林校区返回市区的交通车均由学科楼转盘始发，仙林校区内站点依次为：大活转盘、2食堂、西门配电房、5号楼、2号楼、行政楼、1号楼、市区。</view>\n          <view class=\"text margin\">3、后勤管理处根据交通车运行情况做以上调整。车队杨调度电话：13913976262；监督电话：85866708。</view>\n          <view class=\"known\" @tap.stop=\"changeModalStatus\">知道了</view>\n        </view>\n      </view>\n      <view class=\"tab-wrapper\">\n        <view class=\"tabs-container\">\n          <repeat for=\"{{busTabs}}\" key=\"index\" item=\"item\" index=\"index\">\n            <view class=\"tab {{index === currentRoute ? 'active' : ''}}\" style=\"background-color: {{item.backgroundColor}}\" @tap=\"changeRoute\" data-route=\"{{index}}\">{{item.text}}</view>\n          </repeat>\n        </view>\n        <view class=\"tab-card\">\n          <swiper class=\"tab-card-wrapper\" current=\"{{currentRoute}}\" duration=\"400\" easing-function=\"easeOutCubic\">\n            <repeat for=\"{{tabsDetail}}\" key=\"index\" index=\"index\" item=\"item\">\n              <swiper-item class=\"card-inner\" style=\"background-image: url({{item.backgroundImage}})\" catchtouchmove=\"stopTouchMove\">\n                <view class=\"question-mark\" wx:if=\"{{index <= 1}}\" @tap.stop=\"changeModalStatus\"/>\n                <view class=\"bus-route\">\n                  <view class=\"destination start\">{{item.startAddress}}</view>\n                  <image class=\"arrow\" src=\"{{item.arrow}}\" mode=\"aspectFit\" />\n                  <view class=\"destination end\">{{item.endAddress}}</view>\n                </view>\n                <view class=\"tips\">\n                  更新于：{{updateTime}}\n                </view>\n              </swiper-item>\n            </repeat>\n          </swiper>\n        </view>\n      </view>\n      <view class=\"divider\" />\n      <view class=\"wrapper-container\" style=\"height : {{currentHeight ? currentHeight + 'rpx' : 'auto'}}\">\n        <view class=\"stop-site-wrapper\" animation=\"{{animationData}}\">\n          <repeat for=\"{{busInfo}}\" key=\"index\" index=\"index\" item=\"item\">\n            <view class=\"stop-site-contanier\" id=\"site-container{{index}}\">\n              <repeat for=\"{{item.buses}}\" key=\"innerIndex\" index=\"innerIndex\" item=\"bus\">\n                <BusCard\n                  :stopSites.sync=\"bus.stops\"\n                  :departureTime.sync=\"bus.departureTime\"\n                  :start.sync=\"bus.start\"\n                  :destination.sync=\"bus.destination\"\n                  :during.sync=\"bus.days\"\n                  :index.sync=\"innerIndex\"\n                  :cardAnimation.sync=\"cardAnimationData[index][innerIndex]\"\n                  :color.sync=\"bus.color\"\n                  :showStop.sync=\"bus.showStop\"\n                >\n                <view class=\"divider\" />\n              </repeat>\n            </view>\n          </repeat>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport { getSchoolBus } from \"@/mock/common\";\nimport BusCard from \"../components/bus-card\";\nexport default class SchoolBus extends wepy.page {\n  components = {\n    BaseContainer,\n    BusCard\n  };\n  data = {\n    navTitle: \"车次表\",\n    busTabs: [\n      {\n        text: \"往仙林\",\n        backgroundColor: \"#82FBB3\"\n      },\n      {\n        text: \"往市区\",\n        backgroundColor: \"#64E0FD\"\n      },\n      {\n        text: \"往扬州\",\n        backgroundColor: \"#FF9D6C\"\n      },\n      {\n        text: \"往南京\",\n        backgroundColor: \"#FF8991\"\n      }\n    ],\n    tabsDetail: [\n      {\n        startAddress: \"三牌楼\",\n        endAddress: \"仙林\",\n        arrow:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LeeureWktDEucG5n\",\n        backgroundImage:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3Lei9puasoeihqOS7meaely5wbmc=\"\n      },\n      {\n        startAddress: \"仙林\",\n        endAddress: \"三牌楼\",\n        arrow:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LeeureWktDIucG5n\",\n        backgroundImage:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LXNjaG9vbC1idXMyLnBuZw==\"\n      },\n      {\n        startAddress: \"南京\",\n        endAddress: \"通达\",\n        arrow:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LeeureWktDMucG5n\",\n        backgroundImage:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LXNjaG9vbC1idXMzLnBuZw==\"\n      },\n      {\n        startAddress: \"通达\",\n        endAddress: \"南京\",\n        arrow:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LeeureWktDQucG5n\",\n        backgroundImage:\n          \"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LXNjaG9vbC1idXM0LnBuZw==\"\n      }\n    ],\n    isModalOpen: false,\n    busInfo: [],\n    updateTime: \"\",\n    currentRoute: 0,\n    currentHeight: 0,\n    animationData: {},\n    cardAnimationData: [],\n    screenWidth: 0\n  };\n  methods = {\n    changeRoute(e) {\n      const { route } = e.currentTarget.dataset;\n      if (this.currentRoute != route) {\n        const animation = wepy.createAnimation({\n          duration: 400,\n          timingFunction: \"ease-out\"\n        });\n        this.animationData = animation\n          .right(`${100 * route}%`)\n          .step()\n          .export();\n        this.dealHeight(route);\n        this.currentRoute = route;\n      }\n    },\n    changeModalStatus() {\n      this.isModalOpen = !this.isModalOpen;\n    },\n    stopTouchMove() {\n      return false;\n    },\n    prevent() {}\n  };\n  events = {\n    showStopSites(index) {\n      const animation = wepy.createAnimation({\n        duration: 400,\n        timingFunction: \"ease-out\",\n        transformOrigin: \"50% 0 0\"\n      });\n      const tapBus = this.busInfo[this.currentRoute].buses[index];\n      const { length } = tapBus.stops;\n      this.cardAnimationData[this.currentRoute][index] = tapBus.showStop\n        ? animation\n            .height(`0rpx`)\n            .step()\n            .export()\n        : animation\n            .height(`${110 * length}rpx`)\n            .step()\n            .export();\n      this.dealHeight(this.currentRoute);\n      tapBus.showStop = !tapBus.showStop;\n      this.$apply();\n    }\n  };\n  dealHeight(index, delay) {\n    const query = wepy.createSelectorQuery();\n    const selector = `#site-container${index}`;\n    setTimeout(() => {\n      query\n        .select(selector)\n        .boundingClientRect(rect => {\n          this.currentHeight = rect.height / this.screenWidth;\n          this.$apply();\n        })\n        .exec();\n    }, 450);\n  }\n  prefixInteger(obj) {\n    Object.keys(obj).forEach(\n      key => (obj[key] = obj[key].toString().padStart(2, \"0\"))\n    );\n  }\n  randomInteger(min, max, pre) {\n    let randomInt = Math.floor(Math.random() * (max - min + 1) + min);\n    while (randomInt === pre) {\n      randomInt = Math.floor(Math.random() * (max - min + 1) + min);\n    }\n    return randomInt;\n  }\n  async onLoad() {\n    this.screenWidth = parseFloat(wepy.getSystemInfoSync().screenWidth / 750);\n    const res = await getSchoolBus();\n    if (res.data.data) {\n      this.updateTime = res.data.data.updateTime;\n      this.busInfo = res.data.data.busInfo;\n      const colorArray = [\"#FF8181\", \"#FFC24E\", \"#4ABEFF\"];\n      const animation = wepy.createAnimation({\n        duration: 400,\n        timingFunction: \"ease-out\"\n      });\n      this.animationData = animation\n        .right(`0%`)\n        .step()\n        .export();\n      this.busInfo.forEach((route, routeIndex) => {\n        this.cardAnimationData[routeIndex] = new Array(route.buses.length);\n        route.buses.forEach((bus, busIndex) => {\n          const randomIndex = this.randomInteger(\n            0,\n            2,\n            busIndex !== 0\n              ? colorArray.indexOf(route.buses[busIndex - 1].color)\n              : -1\n          );\n          bus.color = colorArray[randomIndex];\n          bus.showStop = false;\n          this.prefixInteger(bus.departureTime);\n          this.cardAnimationData[routeIndex][busIndex] = animation\n            .height(`0rpx`)\n            .step()\n            .export();\n          bus.stops.forEach(site => {\n            if (site.time) {\n              this.prefixInteger(site.time);\n            }\n          });\n        });\n      });\n      this.dealHeight(0);\n    }\n    this.$apply();\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n.cover-container\n  width 100vw\n  height 0\n  position fixed\n  background-color rgba(0, 0, 0, 0.4)\n  z-index 10000\n  display flex\n  justify-content center\n  align-items center\n  &.active\n    height calc(100vh - 128rpx)\n  .cover-modal\n    width 75%\n    border-radius 20rpx\n    background-color #fff\n    padding-top 40rpx\n    .text\n      padding 0 50rpx\n      letter-spacing 2rpx\n      margin-bottom 10rpx\n      &.margin\n        margin-bottom 25rpx\n    .known\n      height 80rpx\n      line-height 80rpx\n      border-top 1px solid #e5e5e5\n      text-align center\n      color #48C8FD\n.divider\n  width 100vw\n  height 30rpx\n  background-color #F5F5F5\n.tab-wrapper\n  display flex\n  flex-direction column\n  justify-content flex-end\n  align-items center\n  width 100vw\n  height 400rpx\n  .tabs-container\n    width 80%\n    display flex\n    flex-direction row\n    transform translateY(35rpx)\n    .tab\n      width 25%\n      height 85rpx\n      display flex\n      justify-content center\n      align-items center\n      border-radius 20rpx 20rpx 0 0\n      font-size 30rpx\n      transition transform 0.3s ease-out\n      transform translateY(0rpx)\n      &.active\n        transition transform 0.3s ease-out\n        transform translateY(-15rpx)\n  .tab-card\n    width 90%\n    height 80%\n    border-radius 35rpx\n    overflow hidden\n    .tab-card-wrapper\n      width 100%\n      height 100%\n      overflow hidden\n      display flex\n      position relative\n      .card-inner\n        width 100%\n        height 100%\n        display flex\n        flex-direction column\n        justify-content space-around\n        align-items center\n        background-size 100% 100%\n        position relative\n        .question-mark\n          width 40rpx\n          height 40rpx\n          position absolute\n          top 30rpx\n          right 40rpx\n          background-image url(\"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LemXruWPt+Wkh+S7vS5wbmc=\")\n          background-size 100% 100%\n        .bus-route\n          width 90%\n          height 60%\n          display flex\n          justify-content space-around\n          align-items center\n          .arrow\n            width 200rpx\n            height 50rpx\n          .destination\n            font-size 1.6rem\n            letter-spacing .2rem\n        .tips\n          width 100%\n          height 56rpx\n          line-height 45rpx\n          font-size 24rpx\n          text-align center\n.wrapper-container\n  width 100vw\n  position absolute\n  overflow hidden\n  .stop-site-wrapper\n    position relative\n    width 400vw\n    display flex\n    align-items flex-start\n</style>\n"
  },
  {
    "path": "src/others-page/pages/search.wpy",
    "content": "<template>\n  <view>\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <view class=\"search-bar\">\n      <image src=\"https://static.airbob.org/under-graduate/%E6%90%9C%E7%B4%A2.png\" class=\"search-icon\"/>\n      <input type=\"text\" class=\"search-input\" @input=\"search\" value=\"{{keyWord}}\" placeholder=\"搜索个关键词看看？\" focus=\"true\"/>\n      <text class=\"search-cancel\" @tap=\"goBack\">取消</text>\n    </view>\n    <view hidden=\"{{noSearch}}\">\n      <!-- <view class=\"hot-search\" style=\"border-bottom:1rpx solid #F5F5F5\">\n        <view class=\"search-title\">热门搜索</view>\n        <view class=\"hot-search-item\">\n          <repeat for=\"{{hotSearch}}\" index=\"index\" item=\"item\" key=\"key\">\n            <navigator open-type=\"navigate\" hover-class=\"none\" path=\"/other-pages/topic?id={{item.tagId}}\" target=\"miniProgram\" app-id=\"wxa16acae9f9d131fb\" class=\"search-item\" data-name=\"{{item}}\" style=\"padding-left:{{item.hotIcon ? '10rpx' : '34rpx'}}\">\n              <image wx:if=\"{{item.hotIcon}}\" src=\"https://static.airbob.org/under-graduate/search-icon-hot@3x.png\" mode=\"aspectFit\" class=\"hot-search-image\"/>\n              <span>{{item.tag}}</span>\n            </navigator>\n          </repeat>\n        </view>\n      </view> -->\n      <view class=\"hot-search\">\n        <view class=\"search-title\">\n          <view class=\"get-rid\" @tap=\"clearHistory\"></view>\n            搜索历史\n        </view>\n        <view class=\"hot-search-item\">\n          <repeat for=\"{{searchHistory}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"search-item\" @tap=\"quickSearch\" data-name=\"{{item}}\">{{item}}</view>\n          </repeat>\n        </view>\n      </view>\n    </view>\n    <view hidden=\"{{!noSearch}}\" class=\"result-page\">\n      <view class=\"result-title\">搜索结果</view>\n      <view hidden=\"{{!result[0]}}\">\n        <repeat for=\"{{result}}\" index=\"index\" key=\"key\" item=\"item\">\n          <view class=\"result-item\" @tap=\"navTo\" data-path=\"{{item.path}}\">\n            <view class=\"result-image\" style=\"background-image:url('{{item.icon}}')\"></view>\n            <view class=\"result-content\">\n              {{item.before}}<span class=\"result-color\">{{keyWord}}</span>{{item.leftWord}}\n            </view>\n          </view>\n        </repeat>\n      </view>\n      <view hidden=\"{{result[0]}}\">\n        <view class=\"no-result\"></view>\n        <view class=\"no-result-content\">啥也没搜到~</view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport allSearch from \"../mixins/all-search-thing\";\nimport { findIcons } from \"@/api/common\";\nimport navigation from \"@/components/qy-navigation\";\nexport default class extends wepy.page {\n  components = {\n    \"qy-navigation\": navigation\n  };\n  data = {\n    navTitle: \"搜索\",\n    isFocus: false,\n    keyWord: \"\",\n    hotSearch: [],\n    allSearches: [],\n\n    noSearch: false,\n    searchHistory: [],\n    result: [],\n    change: false\n  };\n  mixins = [allSearch];\n  watch = {\n    keyWord(curVal, oldVal) {\n      this.$apply();\n      if (curVal === \"\") {\n        this.noSearch = false;\n      } else {\n        this.noSearch = true;\n      }\n    }\n  };\n  methods = {\n    search(e) {\n      if (!wepy.getStorageSync(\"searchHistory\")) {\n        wepy.setStorageSync(\"searchHistory\", []);\n      }\n      this.keyWord = e.detail.value;\n      if (this.keyWord !== \"\") {\n        this.find(this.keyWord);\n      }\n    },\n    goBack() {\n      wepy.navigateBack();\n    },\n    clearHistory() {\n      wepy.setStorageSync(\"searchHistory\", []);\n      this.searchHistory = [];\n      this.$apply();\n    },\n    quickSearch(e) {\n      let name = e.currentTarget.dataset.name;\n      if (!wepy.getStorageSync(\"searchHistory\")) {\n        wepy.setStorageSync(\"searchHistory\", []);\n      }\n      this.keyWord = name;\n      this.find(name);\n      this.$apply();\n    },\n    navTo(e) {\n      let path = e.currentTarget.dataset.path;\n      wepy.navigateTo({\n        url: \"../../../../\" + path\n      });\n    }\n  };\n  find(e) {\n    let name = e;\n    this.result = [];\n    this.allSearches.forEach((i, keyWord) => {\n      if (i.name.indexOf(name) !== -1) {\n        let index = i.name.indexOf(name);\n        let before = i.name.substr(0, index);\n        let leftWord = i.name.substr(before.length + this.keyWord.length);\n        i.before = before;\n        i.leftWord = leftWord;\n        this.result.unshift(i);\n        if (this.searchHistory.indexOf(i.name) === -1) {\n          this.searchHistory.unshift(i.name);\n          wepy.setStorageSync(\"searchHistory\", this.searchHistory);\n        }\n      }\n    });\n    this.$apply();\n  }\n  onLoad() {\n    let tempHistory = wepy.getStorageSync(\"searchHistory\");\n    if (!tempHistory) {\n      tempHistory = [];\n      wepy.setStorageSync(\"searchHistory\", []);\n    }\n    this.searchHistory = tempHistory;\n    this.allSearches = this.allSearchThing();\n    findIcons().then(res => {\n      this.hotSearch.push(...res.data.data);\n      this.hotSearch.forEach((item, index) => {\n        if (index <= 2) {\n          this.hotSearch[index].hotIcon = true;\n        } else {\n          this.hotSearch[index].hotIcon = false;\n        }\n      });\n      this.$apply();\n    });\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\n@import '../../css/search-input'\n.search-bar\n  box-shadow 0 10rpx 8rpx 0 rgba(0, 0, 0, 0.05)\n  padding 20rpx\n  position relative\n  font-size 30rpx\n  .search-icon\n    position absolute\n    width 30rpx\n    height 30rpx\n    top 35rpx\n    left 34rpx\n    z-index 1\n  .search-cancel\n    margin-top 10rpx\n    float right\n    color #47CFF5\n.hot-search\n  position relative\n  width 700rpx\n  margin 0 auto\n  padding-top 30rpx\n  .search-title\n    color #353535\n    font-size 30rpx\n    line-height 30rpx\n    height 30rpx\n    font-weight bold\n    margin-bottom 30rpx\n    .get-rid\n      position absolute\n      right 25rpx\n      width 30rpx\n      height 30rpx\n      background-image url('https://static.airbob.org/under-graduate/%E6%B8%85%E7%A9%BA.png')\n      background-position center\n      background-repeat no-repeat\n      background-size contain\n  .hot-search-item\n    display flex\n    flex-wrap wrap\n    justify-content flex-start\n    .search-item\n      display flex\n      justify-content center\n      flex-grow 0\n      font-size 28rpx\n      height 40rpx\n      padding 10rpx 34rpx\n      margin-bottom 30rpx\n      margin-right 30rpx\n      background #F5F5F5\n      color #353535\n      border-radius 50rpx\n      .hot-search-image\n        width 40rpx\n        height 40rpx\n        margin-right 10rpx\n.result-page\n  position relative\n  padding-top 30rpx\n  width 700rpx\n  margin 0 auto\n  .result-title\n    color #353535\n    font-size 30rpx\n    line-height 30rpx\n    height 30rpx\n    font-weight bold\n    margin-bottom 30rpx\n  .result-item\n    position relative\n    font-size 28rpx\n    color #353535\n    width 700rpx\n    height 50rpx\n    line-height 50rpx\n    margin-top 30rpx\n    .result-image\n      position relative\n      display inline-block\n      width 50rpx\n      height 50rpx\n      margin-left 15rpx\n      background-position center\n      background-repeat no-repeat\n      background-size contain\n    .result-content\n      margin-left 20rpx\n      position absolute\n      display inline-block\n      width 600rpx\n      height 50rpx\n      line-height 50rpx\n      font-weight bold\n      .result-color\n        color #47CFF5\n  .no-result\n    position relative\n    top 200rpx\n    width 400rpx\n    height 287rpx\n    background-image url('https://static.airbob.org/under-graduate/%E7%BC%BA%E7%9C%81%E9%A1%B5_%E7%A9%BA.png')\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n    margin 0 auto\n  .no-result-content\n    position relative\n    margin 0 auto\n    text-align center\n    color #999CA0\n    font-size 28rpx\n    top 270rpx\n</style>\n"
  },
  {
    "path": "src/others-page/pages/tuition.wpy",
    "content": "<template>\n  <BaseContainer :navTitle=\"navTitle\">\n    <view slot=\"qy-content\">\n      <view class=\"container\">\n        <image class=\"tuition-bg\" mode=\"aspectFill\" src=\"https://static.airbob.org/under-graduate/tuition/tuition.png\" />\n        <scroll-view scroll-x class=\"year-container\">\n          <repeat for=\"{{years}}\" index=\"index\" key=\"key\" item=\"item\">\n            <view class=\"year-btn {{ index==tapYear?'year-ontap':'' }}\" data-index=\"{{index}}\" data-item=\"{{ item }}\" @tap=\"changeYear\">{{ item }}</view>\n          </repeat>\n        </scroll-view>\n        <view class=\"boxLoading\" wx:if=\"{{ showLoading }}\"></view>\n        <view class=\"table-container\" wx:if=\"{{ !showBlank }}\">\n          <scroll-view scroll-x class=\"table\">\n            <view class=\"tr\">\n              <view class=\"th\">费用名称</view>\n              <view class=\"th\">应缴金额</view>\n              <view class=\"th\">已交金额</view>\n              <view class=\"th\">退款金额</view>\n              <view class=\"th\">欠缴金额</view>\n            </view>\n            <repeat for=\"{{ categories }}\" index=\"index\" key=\"key\" item=\"item\">\n              <view class=\"tr\">\n                <view class=\"td\">{{ item }}</view>\n                <view class=\"td\">{{ dues[index] }}</view>\n                <view class=\"td\">{{ paid[index] }}</view>\n                <view class=\"td\">{{ refunds[index] }}</view>\n                <view class=\"td\">{{ debts[index] }}</view>\n              </view>\n            </repeat>\n          </scroll-view>\n          <image class=\"table-gradual\" mode=\"aspectFill\" src=\"https://static.airbob.org/under-graduate/tuition/gradual.png\" />\n        </view>\n        <view class=\"abnormal-container\" wx:if=\"{{ abnormal }}\">\n          <image class=\"abnormal\" mode=\"aspectFit\" src=\"https://static.airbob.org/under-graduate/tuition/abnormal.png\" />\n          <span>暂无相关信息哟～</span>\n        </view>\n        <QyModal width=\"500rpx\">\n          <view slot=\"content\" class=\"bind-container\">\n            <input class=\"bind-input\" placeholder=\"{{placeholder}}\" password=\"true\" @input=\"bindCardPassword\" placeholder-style=\"color: #999CA0\" />\n            <button class=\"bind-button\" @tap.stop=\"bindHandle\" hover-class=\"button-click\">立即绑定</button>\n          </view>\n        </QyModal>\n        <!-- <view class=\"web-view\" wx:if=\"{{ showWeb }}\">\n          <web-view src=\"https://wechat.njupt.edu.cn/tuition/\"></web-view>\n        </view> -->\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport QyModal from \"@/components/qy-modal\";\nimport { changeSecretCode, schoolFeeFresh, getSchoolFee } from \"@/api/common\";\nimport JudgeStatus from \"@/mixins/module\";\nimport BaseContainer from \"@/components/baseContainer\";\n\nexport default class extends wepy.page {\n  config = {\n    navigationBarTitleText: \"学费查询\"\n  };\n  components = {\n    QyModal: QyModal,\n    BaseContainer\n  };\n  data = {\n    navTitle: \"学费查询\",\n    tapYear: \"\",\n    showLoading: false,\n    abnormal: false,\n    showBlank: true,\n    years: [],\n    categories: [],\n    dues: [],\n    paid: [],\n    refunds: [],\n    debts: [],\n    tuition: [],\n    password: \"\",\n    refresh: false,\n    placeholder: \"\",\n    visitorModeStatus: false\n    // count: 0,\n    // showWeb: false\n  };\n  mixins = [JudgeStatus];\n  methods = {\n    changeYear(e) {\n      let index = e.currentTarget.dataset.index;\n      this.categories = [];\n      this.dues = [];\n      this.paid = [];\n      this.refunds = [];\n      this.debts = [];\n      this.setTuition(index);\n      this.tapYear = parseInt(index);\n      this.$apply();\n    },\n    bindCardPassword(e) {\n      this.password = e.detail.value;\n    },\n    async bindHandle() {\n      let that = this;\n      if (this.password) {\n        let updatePassword = await changeSecretCode(\"\", this.password, 16);\n        if (updatePassword.data.success) {\n          that.placeholder = \"\";\n          that.$invoke(\"QyModal\", \"close\");\n          that.init();\n        } else {\n          wepy.showModal({\n            content: \"密码错误\",\n            confirmText: \"知道了\",\n            showCancel: false,\n            confirmColor: \"#353535\"\n          });\n        }\n      } else {\n        wepy.showModal({\n          content: \"密码为空\",\n          confirmText: \"知道了\",\n          showCancel: false,\n          confirmColor: \"#353535\"\n        });\n      }\n    }\n  };\n  async getTuition() {\n    let that = this;\n    let currentYearTuition;\n    if (this.refresh) {\n      currentYearTuition = await schoolFeeFresh();\n    } else {\n      currentYearTuition = await getSchoolFee();\n    }\n    setTimeout(() => {\n      that.showLoading = false;\n      if (currentYearTuition.data.success && currentYearTuition.data.data) {\n        that.showBlank = false;\n        that.tuition = currentYearTuition.data.data.data;\n        that.years = [];\n        that.abnormal = false;\n        for (let i = 0; i < that.tuition.length; i++) {\n          let yearItem = this.tuition[i].year.substr(0, 9) + \" 学年\";\n          that.years.push(yearItem);\n        }\n        that.setTuition(0);\n        that.$apply();\n      } else if (\n        currentYearTuition.data.success &&\n        !currentYearTuition.data.data\n      ) {\n        that.abnormal = true;\n      } else if (!currentYearTuition.data) {\n        that.abnormal = true;\n        that.placeholder = \"统一身份认证密码(默认身份证后六位)\";\n        that.$invoke(\"QyModal\", \"open\");\n      }\n      that.$apply();\n    }, 1000);\n    this.$apply();\n  }\n  setTuition(e) {\n    this.showBlank = false;\n    let categories = this.tuition[e].items;\n    let dues = this.tuition[e].shouldPay;\n    let paid = this.tuition[e].payed;\n    let refunds = this.tuition[e].refund;\n    let debts = this.tuition[e].arrears;\n    this.categories = categories;\n    for (let key in categories) {\n      this.dues.push(dues[categories[key]]);\n      this.paid.push(paid[categories[key]]);\n      this.refunds.push(refunds[categories[key]]);\n      this.debts.push(debts[categories[key]]);\n    }\n    this.$apply();\n  }\n  getYears() {\n    let that = this;\n    return new Promise(resolve => {\n      let userInfo = wepy.getStorageSync(\"User\");\n      let nowYear = parseInt(\n        new Date()\n          .getFullYear()\n          .toString()\n          .substr(2, 3)\n      );\n      let enterYear = parseInt(userInfo.studentId.substr(1, 2));\n      let allYears = parseInt(nowYear - enterYear);\n      for (let i = 0; i < allYears; i++) {\n        that.years.unshift(\n          `20${enterYear + i}-20${parseInt(enterYear + i + 1)} 学年`\n        );\n      }\n      that.$apply();\n      resolve();\n    });\n  }\n  onPullDownRefresh() {\n    if (!this.visitorModeStatus) {\n      this.refresh = true;\n      this.getTuition();\n    }\n  }\n  async init() {\n    try {\n      this.years = [];\n      this.showLoading = true;\n      this.abnormal = false;\n      this.showBlank = true;\n      this.getYears();\n      await this.getTuition();\n      this.$apply();\n    } catch (error) {\n      console.log(error);\n    }\n  }\n  async onLoad(op) {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    if (!this.visitorModeStatus) {\n      this.judgeStatus(op.name).then(() => {\n        this.init();\n      });\n    } else {\n      this.years = [];\n      this.showLoading = false;\n      this.abnormal = true;\n      this.showBlank = true;\n      this.$apply();\n    }\n  }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n\n@import '../../css/loading'\n\n.container\n  display flex\n  flex-direction column\n  align-items center\n  image\n    width 720rpx\n    height 420rpx\n    margin 0 auto\n  .year-container\n    width 100%\n    margin 20rpx 0\n    display flex\n    flex-direction row\n    justify-content center\n    white-space nowrap\n    .year-btn\n      display inline-block\n      box-sizing border-box\n      height 78rpx\n      width 316rpx\n      border-radius 6rpx\n      border solid 2rpx #eb865f\n      font-size 32rpx\n      text-align center\n      line-height 78rpx\n      color #ea875e\n      font-family PingFangSC-Regular\n      margin-left 24rpx\n      margin-bottom 30rpx\n    .year-btn:last-child\n      margin-right 24rpx\n    .year-ontap\n      background-image linear-gradient(90deg, #ebba2e 0%, #ea845f 100%)\n      border 0\n      padding 2rpx 2rpx 0 0\n      color #fff\n  .boxLoading\n    position fixed\n    top 50vh\n  .table-container\n    width 100%\n    position relative\n    .table\n      display flex\n      flex-direction column\n      width 100%\n      .tr\n        width 150%\n        min-height 96rpx\n        display flex\n        flex-direction row\n        align-items center\n        border-bottom solid 2rpx #e0e0e0\n        margin 0 20rpx\n        .th,\n        .td\n          display inline-block\n          width 128rpx\n          font-family PingFangSC-Medium\n          color #353535\n          font-size 32rpx\n          line-height 32rpx\n          margin 0 40rpx 0 40rpx\n      .tr:first-child\n        background-color #efefef\n        border 0\n        border-radius 6rpx\n      .tr:last-child\n        margin-bottom 30rpx\n    .table-gradual\n      position absolute\n      top 0\n      right 0\n      bottom 0\n      width 170rpx\n      height 100%\n  .abnormal-container\n    height calc(100vh - 568rpx)\n    display flex\n    flex-direction row\n    align-items center\n    image\n      height 64rpx\n      width 64rpx\n    span\n      margin-left 32rpx\n      font-family PingFangSC-Regular\n      color #eb994c\n      font-size 28rpx\n  .bind-container\n    display flex\n    flex-direction column\n    align-items center\n    background-image url('https://static.airbob.org/under-graduate/model_pic_password.png')\n    background-repeat no-repeat\n    height 485rpx\n    border-radius 30rpx\n    background-size cover\n    .bind-input\n      font-size 26rpx\n      margin 221rpx 0 56rpx\n      width 438rpx\n      border-bottom 2rpx solid #999CA0\n    .bind-button\n      margin-top 26rpx\n      background-color #6AE4FF\n      text-align center\n      width 410rpx\n      height 80rpx\n      line-height 80rpx\n      color #ffffff\n      border-radius 50px\n  .button-click\n    background-image none\n    background-color #D0F5FF\n</style>"
  },
  {
    "path": "src/others-page/wxs/filter.wxs",
    "content": "module.exports = {\n  filter: function(name) {\n    if (name.indexOf(\"doc\") > -1) {\n      return \"https://static.airbob.org/admin/news_pic_word.png\";\n    }\n    if (name.indexOf(\"xls\") > -1) {\n      return \"https://static.airbob.org/admin/news_pic_excel.png\";\n    }\n    if (name.indexOf(\"pdf\") > -1) {\n      return \"https://static.airbob.org/admin/news_pic_pdf.png\";\n    }\n  }\n};\n"
  },
  {
    "path": "src/pages/index.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"NJUPT\" :openPage.sync=\"openPage\">\n    <view slot=\"qy-content\">\n      <view wx:if=\"{{hiGraduateModal}}\" class=\"hi-graduate\" @tap=\"hideHiGraduate\">\n        <image src=\"https://static.airbob.org/under-graduate/memory/xiao.png\" class=\"hi-graduate-img\">\n        <view class=\"hi-graduate-talk\">\n          <view class=\"graduate-talk-title\">南邮记忆</view>\n          <view class=\"graduate-talk-content\">亲爱的{{graduateName}}</view>\n          <view class=\"graduate-talk-content\">欢迎回来！</view>\n          <view class=\"graduate-divide\"></view>\n          <view class=\"graduate-talk-content\">小程序将永久安全地保存你校园记忆，</view>\n          <view class=\"graduate-talk-content\">你可以随时查看，</view>\n          <view class=\"graduate-talk-content\">但无法再次刷新这些数据。</view>\n          <view class=\"graduate-divide\"></view>\n          <view class=\"graduate-talk-content\">你可以在“我的”中关闭记忆模式，</view>\n          <view class=\"graduate-talk-content\">关闭后数据将全部清空，</view>\n          <view class=\"graduate-talk-content\">且操作不可逆。</view>\n        </view>\n      </view>\n      <!-- <QyPopUp :openPage.sync=\"openPage\" link=\"https://qingyou.njupt.edu.cn/bgd3\" /> -->\n      <view class=\"perfect-info\" wx:if=\"{{commandInfoStatus}}\" @tap=\"closeCommandInfo\">\n        <view class=\"perfect-info-body\">\n          <view class=\"perfect-img\">\n            <image src=\"https://static.airbob.org/under-graduate/kl.png\">\n          </view>\n          <view class=\"perfect-info-card\">\n            <view class=\"command-avatar\">\n              <view>\n                <image class=\"command-avatar-img\" src=\"{{assoInfo.avatar}}\">\n              </view>\n            </view>\n            <view class=\"perfect-info-tip\">发现了社团口令{{assoInfo.command}}</view>\n            <view class=\"command-name\">{{assoInfo.info.fullname}}</view>\n            <view class=\"submission\" @tap.stop=\"codeToDetail\">\n              <view>点击查看</view>\n            </view>\n          </view>\n        </view>\n      </view>\n      <view class=\"perfect-info\" wx:if=\"{{importantInfoStatus}}\" @tap.stop=\"closeNotification\" data-id=\"{{importantInfo.id}}\">\n        <view class=\"perfect-info-body notification\" @tap.stop=\"prevent\">\n          <view class=\"perfect-img notification\">\n            <image src=\"https://static.airbob.org/under-graduate/QjE2MDEyMzI3LXl1cm9uZy5wbmc=?tdsourcetag=s_pctim_aiomsg\">\n          </view>\n          <view class=\"perfect-info-card notification\">\n            <view class=\"perfect-info-tip notification\">{{importantInfo.title}}</view>\n            <view class=\"notification-info\">\n              <repeat for=\"{{importantInfo.content}}\" key=\"index\" index=\"index\" item=\"content\">\n                <view>{{content}}</view>\n              </repeat>\n            </view>\n            <view class=\"notification-close\" @tap.stop=\"closeNotification\" data-id=\"{{importantInfo.id}}\">\n              我知道了\n            </view>\n          </view>\n        </view>\n      </view>\n      <navigator\n        class=\"open-page-container\"\n        target=\"{{navigatorTarget}}\"\n        app-id=\"{{navigatorAppId}}\"\n        url=\"{{navigatorUrl}}\"\n        style=\"background-image:url('{{displayPic}}');\"\n        hidden=\"{{!openPage}}\"\n      >\n        <view class=\"pass-open-page-container\" @tap.stop=\"passOpenPage\">\n          <view class=\"pass-open-page\">跳过{{passTime}}秒</view>\n        </view>\n      </navigator>\n      <view\n        class=\"container\"\n        hidden=\"{{openPage}}\"\n        style=\"position: {{commandInfoStatus || annualStatus ? 'fixed' : 'static'}}\"\n      >\n        <view class=\"navbar\">\n          <view class=\"search-bar\" @tap=\"goSearch\">\n            <view class=\"virsual-placeholder\">\n              <image\n                src=\"https://static.airbob.org/under-graduate/%E6%90%9C%E7%B4%A2.png\"\n                class=\"search-icon\"\n              >\n              <text>{{schoolTalkText}}</text>\n            </view>\n            <input type=\"text\" class=\"search-input\" @focus=\"focus\">\n          </view>\n          <!-- <image src=\"{{isNewInfo ? 'https://static.airbob.org/under-graduate/alert-active.png' : 'https://static.airbob.org/under-graduate/alert.png'}}\" class=\"alert-img {{isNewInfo ? 'shake' : ''}}\" @tap=\"goInfobox\"/> -->\n        </view>\n        <view class=\"functional\">\n          <repeat for=\"{{functionalList}}\">\n            <view\n              class=\"functional-item\"\n              @tap=\"moveTo\"\n              data-path=\"{{item.path}}\"\n              data-module=\"{{item.module}}\"\n              data-name=\"{{item.name}}\"\n              data-isnew=\"{{item.isNew}}\"\n            >\n              <image src=\"{{item.src}}\" class=\"functional-item-image\">\n              {{item.name}}\n              <view class=\"image-red-dot\" hidden=\"{{ !item.isNew }}\"></view>\n            </view>\n          </repeat>\n        </view>\n        <view class=\"splitLine\"></view>\n        <!-- <navigator open-type=\"navigate\" target=\"miniProgram\" app-id=\"wx7d66d77988bbeab3\" style=\"width:750rpx;\">\n        <view class=\"school-talk-container\">\n          <image src=\"https://static.airbob.org/under-graduate/跳转bar.png\" mode=\"aspectFit\" class=\"school-talk\" />\n        </view>\n        </navigator>-->\n        <view class=\"notification-container\" @tap=\"goInfobox\" wx:if=\"{{!swiperInfo[0]}}\">\n          <view class=\"notification-image\"></view>\n          <view class=\"notification-content\">\n            <view class=\"swiper-content\">你没有新消息哟～</view>\n            <view class=\"notification-arrow\"></view>\n          </view>\n        </view>\n        <view class=\"notification-container\" @tap=\"goInfobox\" wx:else>\n          <view class=\"notification-image\">\n            <view class=\"notification-oval {{isNewInfo?'move':''}}\">\n              <span>{{swiperInfo.length}}</span>\n            </view>\n          </view>\n          <swiper class=\"notification-content\" autoplay=\"true\" vertical=\"true\" circular=\"true\">\n            <repeat for=\"{{swiperInfo}}\" item=\"item\" index=\"index\" key=\"key\">\n              <swiper-item>\n                <view class=\"swiper-content\">{{item.title}}</view>\n              </swiper-item>\n            </repeat>\n          </swiper>\n          <view class=\"notification-arrow\"></view>\n        </view>\n        <!-- <navigator open-type=\"navigate\" target=\"miniProgram\" app-id=\"wxa16acae9f9d131fb\" style=\"width:750rpx;\">\n                            <view class=\"school-talk-container\">\n                                <image src=\"https://static.airbob.org/under-graduate/home-bannerbar-chat@3x.png\" mode=\"aspectFit\" class=\"school-talk\"/>\n                            </view>\n        </navigator>-->\n        <!-- <navigator url=\"../others-page/pages/association\" style=\"width:750rpx;\">\n                            <view class=\"school-talk-container\">\n                                <image src=\"https://static.airbob.org/club-enter.png\" mode=\"aspectFill\" class=\"school-talk\"/>\n                            </view>\n        </navigator>-->\n        <!-- <navigator url=\"../others-edu-page/pages/avatar\" style=\"width:750rpx;\">\n                            <view class=\"school-talk-container\">\n                                <image src=\"https://static.airbob.org/under-graduate/wsj_index.png\" mode=\"aspectFit\" class=\"school-talk\"/>\n                            </view>\n        </navigator>-->\n        <view class=\"split-line\"></view>\n        <view class=\"course-container\">\n          <view class=\"container-top\">\n            <view class=\"container-top-title\">今日课表</view>\n            <span @tap=\"showAllCourse\" data-name=\"课表\">完整课表</span>\n            <view class=\"arrow\"></view>\n          </view>\n          <view class=\"boxLoading\" hidden=\"{{loadHide}}\"></view>\n          <view class=\"nocourse-list\" wx:if=\"{{noCourseItem}}\">\n            <view class=\"nocourse-image\"></view>\n            <view class=\"nocourse-word\" wx:if=\"{{!graduateIdentity}}\">今日无课，要合理安排时间哦</view>\n            <view class=\"graduate-word\" wx:else>\n              <view>毕业的你，已经不会再有新的大学课程</view>\n              <view>但人生处处都是课堂</view>\n            </view>\n          </view>\n          <scroll-view class=\"course-list\" scroll-x=\"true\" wx:if=\"{{!noCourseItem}}\" scroll-into-view=\"{{courseToView}}\" scroll-with-animation=\"true\">\n            <repeat for=\"{{courses}}\" index=\"index\" key=\"key\" item=\"item\">\n              <view class=\"course-item\" style=\"background: {{item.bgc}}\" id=\"course{{index+1}}\">\n                <view class=\"course-thing\">\n                  <view style=\"font-size:28rpx;\">{{item.name}}</view>\n                  <view>{{item.time}}</view>\n                  <view>\n                    {{item.locale}}\n                    <span wx:if=\"{{item.locale}}\">| {{item.teacher}}</span>\n                  </view>\n                </view>\n              </view>\n            </repeat>\n          </scroll-view>\n        </view>\n        <view class=\"split-line\"></view>\n        <view class=\"card-container\">\n          <view class=\"container-top\">\n            <view class=\"container-top-title\">一卡通</view>\n            <span @tap.stop=\"goYkt\" data-name=\"一卡通\">完整记录</span>\n            <view class=\"arrow\"></view>\n          </view>\n          <view class=\"campus-card\">\n            <view class=\"content\">\n              <view class=\"content-container\" >\n                <view wx:if=\"{{isBalanceOk}}\">\n                  <span>余额:</span>\n                  <span class=\"bigger\">{{balance}}</span>\n                  <span>元</span>\n                  <view>更新时间：{{time}}</view>\n                </view>\n                <view wx:else>\n                  <span class=\"bigger\">{{balance}}</span>\n                </view>\n                <view class=\"refresh-container\">\n                  <image class=\"refresh {{isRefreshYkt?'refresh-rolling':''}}\" @tap.stop=\"refreshYtkInfo\" src=\"https://static.airbob.org/index_fresh/QjE2MDEyMzI3LeWIt+aWsEAzeC5wbmc=\" />\n                </view>\n              </view>\n            </view>\n          </view>\n        </view>\n        <view class=\"split-line\"></view>\n        <view class=\"card-container\" style=\"border:none\">\n          <view class=\"container-top\">\n            <view class=\"container-top-title\">晨跑</view>\n            <span @tap=\"showRuntime\" data-name=\"晨跑\">完整记录</span>\n            <view class=\"arrow\"></view>\n          </view>\n          <view class=\"run-card\">\n            <view class=\"run-detail\">\n              <view wx:if=\"{{runTime !== -1 && runTime !== '-1'}}\">\n                <view>\n                  跑操总数：\n                  <span>{{runTime}}</span>次\n                </view>\n              </view>\n              <view wx:else>抱歉,查询失败了呢。。。</view>\n            </view>\n          </view>\n        </view>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport { associationDetail } from \"@/api/recruit\";\nimport { getNotification, setMessageRead } from \"@/api/notification\";\nimport { mockGetNotification } from \"@/mock/notification\";\nimport {\n  getDisplay,\n  getUserInfo,\n  commonInformation,\n  getModuleStatus,\n  runningCount,\n  getPromotionInformation\n} from \"@/api/common\";\nimport { mockGetExercise } from \"@/mock/common\";\nimport { classSchedule, getCourses, assignTimetable } from \"@/api/education\";\nimport { campusCardRequestInfo } from \"@/api/campusCard\";\nimport { educationSystemInformation } from \"@/api/education\";\nimport { mockClassSchedule } from \"@/mock/education\";\nimport { mockCampusCardRequestInfo } from \"@/mock/campusCard\";\nimport { connect } from \"wepy-redux\";\nimport ClassMixin from \"../mixins/class.js\";\nimport QyPopUp from \"@/components/qy-popup\";\nimport {\n  judgeMemoryModeStatus,\n  judgeGraduateStatus\n} from \"@/store/actions/index\";\n\n@connect(\n  {\n    graduateIdentity(state) {\n      return state.graduateReducer.graduateIdentity;\n    },\n    chooseMemoryMode(state) {\n      return state.graduateReducer.chooseMemoryMode;\n    }\n  },\n  {\n    judgeMemoryModeStatus,\n    judgeGraduateStatus\n  }\n)\nexport default class Index extends wepy.page {\n  config = {\n    navigationBarTitleText: \"NJUPT\"\n    // enablePullDownRefresh: true\n  };\n  mixins = [];\n  components = {\n    QyPopUp,\n    BaseContainer\n  };\n  data = {\n    moreFunc: {},\n    courseColor: [\"#6AD5E1\", \"#87E5DA\", \"#F7C562\", \"#FFB677\", \"#FF8364\"],\n    courses: [],\n    noCourseItem: false,\n    balance: \"正在加载...\",\n    time: \"\",\n    functionalList: \"\",\n    swiperInfo: [],\n    isNewInfo: false,\n    runTime: \"\",\n    loadHide: false,\n    openPage: false,\n    passTime: 5,\n    schoolTalkText: \"搜点什么吧~\",\n    // 是否检测到口令\n    commandInfoStatus: false,\n    // 是否有重要通知\n    importantInfoStatus: false,\n    // 重要通知\n    importantInfo: {},\n    // 社团信息\n    assoInfo: {},\n    showLaboratory: true,\n    annualStatus: false, // 年报弹窗\n    //开屏跳转\n    navigatorTarget: \"\",\n    navigatorAppId: \"\",\n    navigatorUrl: \"\",\n    displayPic: \"\",\n    displayColor: \"\",\n    avatarUrl: [\n      \"https://static.airbob.org/under-graduate/profile/avatar1.png\",\n      \"https://static.airbob.org/under-graduate/profile/avatar2.png\",\n      \"https://static.airbob.org/under-graduate/profile/avatar3.png\"\n    ],\n    hiGraduateModal: false,\n    graduateName: \"\",\n    visitorModeStatus: false,\n    classInfo: {},\n    isRefreshYkt: false,\n    courseToView: \"course0\"\n  };\n  computed = {\n    isBalanceOk() {\n      const exceptions = [\n        \"暂停服务\",\n        \"密码需要更新\",\n        \"请求失败\",\n        \"正在加载...\",\n        \"需要绑定一卡通\"\n      ];\n      return !exceptions.includes(this.balance);\n    }\n  };\n  // 首页广告\n  watch = {\n    openPage(newValue, oldValue) {\n      if (newValue) {\n        wepy.setNavigationBarColor({\n          frontColor: \"#ffffff\",\n          backgroundColor:\n            this.displayColor || wepy.getStorageSync(\"display\").displayColor,\n          animation: {\n            duration: 0,\n            timingFunc: \"easeIn\"\n          }\n        });\n        wepy.setNavigationBarTitle({\n          title: \"\"\n        });\n        wepy.hideTabBar();\n        let timer = setInterval(() => {\n          this.passTime--;\n          if (Number(this.passTime) <= 0) {\n            clearInterval(timer);\n            this.openPage = false;\n            wepy.showTabBar();\n            wepy.setNavigationBarColor({\n              frontColor: \"#000000\",\n              backgroundColor: \"#fff\",\n              animation: {\n                duration: 0,\n                timingFunc: \"easeIn\"\n              }\n            });\n            wepy.setNavigationBarTitle({\n              title: \"NJUPT\"\n            });\n            this.$apply();\n          }\n          this.$apply();\n        }, 1000);\n      }\n    },\n    classInfo(newValue) {\n      const { extraCourse, timetable, assign } = newValue;\n      if (timetable) {\n        const mergedCourse = extraCourse\n          ? timetable.concat(extraCourse)\n          : timetable;\n        if (assign) {\n          const { week, specialDayNum } = assign;\n          this.dealCourse(mergedCourse, week, specialDayNum);\n        } else {\n          this.dealCourse(mergedCourse);\n        }\n        this.loadHide = true;\n        this.$apply();\n      }\n    }\n  };\n  methods = {\n    goSearch() {\n      this.$navigate({\n        url: \"../others-page/pages/search\"\n      });\n    },\n    goInfobox() {\n      this.$navigate({\n        url: \"../others-page/pages/information-box\"\n      });\n    },\n    goYkt(e) {\n      const name = e.currentTarget.dataset.name;\n      this.$navigate({\n        url: `../campus-card-page/pages/campus-card-index?name=${name}`\n      });\n    },\n    async moveTo(e) {\n      const name = e.currentTarget.dataset.name;\n      if (e.currentTarget.dataset.isnew) {\n        let newModule = wepy.getStorageSync(\"newModule\");\n        for (let i in newModule) {\n          if (newModule[i].moduleName === name) {\n            newModule.splice(i, 1);\n            wepy.setStorageSync(\"newModule\", newModule);\n            break;\n          }\n        }\n        for (let j of this.functionalList) {\n          if (j.name === name) {\n            j.isNew = false;\n          }\n        }\n      }\n      if (\n        e.currentTarget.dataset.path === \"../others-page/pages/more\" &&\n        wepy.getStorageSync(\"indexIcon\") === \"\"\n      ) {\n        wepy.setStorageSync(\"indexIcon\", this.functionalList);\n      }\n      this.$navigate({\n        url: `${e.currentTarget.dataset.path}?name=${\n          e.currentTarget.dataset.name\n        }`\n      });\n    },\n    showAllCourse(e) {\n      const name = e.currentTarget.dataset.name;\n      this.$navigate({\n        url: `../edu-admin-page/pages/course?name=${name}`\n      });\n    },\n    showRuntime(e) {\n      const name = e.currentTarget.dataset.name;\n      this.$navigate({\n        url: `../others-page/pages/run?name=${name}`\n      });\n    },\n    // 首页广告\n    passOpenPage() {\n      this.openPage = false;\n      wepy.setNavigationBarColor({\n        frontColor: \"#000000\",\n        backgroundColor: \"#fff\",\n        animation: {\n          duration: 0\n        }\n      });\n      wepy.setNavigationBarTitle({\n        title: \"NJUPT\"\n      });\n      wepy.showTabBar();\n    },\n    // 通过口令跳转到社团详情\n    codeToDetail() {\n      this.commandInfoStatus = false;\n      this.$apply();\n      wepy.navigateTo({\n        url: `../others-page/pages/associationPages/association-detail?associationName=${\n          this.assoInfo.info.associationName\n        }&koulingStatus=true&command=${this.assoInfo.command}&fullname=${\n          this.assoInfo.info.fullname\n        }`\n      });\n      wepy.setClipboardData({\n        data: \"剪贴板清空惹~\"\n      });\n    },\n    hideHiGraduate() {\n      this.hiGraduateModal = false;\n      wepy.setStorageSync(\"graduateModal\", true);\n    },\n    closeCommandInfo() {\n      this.commandInfoStatus = false;\n    },\n    async refreshYtkInfo() {\n      const moduleStatus = wepy.getStorageSync(\"moduleStatus\");\n      const ytkModuleStatus = moduleStatus.find(x => x.moduleName === \"一卡通\");\n      if (ytkModuleStatus && !ytkModuleStatus.open) {\n        this.balance = \"暂停服务\";\n        this.$apply();\n      } else {\n        this.isRefreshYkt = true;\n        this.$apply();\n        const { data: response } = await this.judgeCampusCard();\n        this.isRefreshYkt = false;\n        this.$apply();\n        if (response.data) {\n          const yktInfoCache = { data: response.data, time: new Date() };\n          wepy.setStorageSync(\"yktInfo\", yktInfoCache);\n          const { data, time } = yktInfoCache;\n          const tempDate = new Date(time);\n          const formatTimeString = raw =>\n            raw.toString().length < 2 ? \"0\" + raw.toString() : raw.toString();\n          this.time = this.graduateIdentity\n            ? `2019-6-20 毕业典礼`\n            : `${tempDate.getFullYear()}-${tempDate.getMonth() +\n                1}-${tempDate.getDate()} ${formatTimeString(\n                tempDate.getHours()\n              )}:${formatTimeString(tempDate.getMinutes())}:${formatTimeString(\n                tempDate.getSeconds()\n              )}`;\n\n          if (this.graduateIdentity) {\n            this.balance =\n              (Number(data.db_balance) + Number(data.unset_balance)) / 100;\n          } else {\n            this.balance =\n              (Number(data.db_balance) + Number(data.unsettle_amount)) / 100;\n          }\n          this.$apply();\n          wepy.setStorageSync(\"sno\", data.sno);\n        } else {\n          if (response.errCode === 24) {\n            this.balance = \"密码需要更新\";\n          } else if (response.errCode === 34) {\n            this.balance = \"需要绑定一卡通\";\n          } else if (response.errCode === 668) {\n            this.$parent.showTip(response.errMsg);\n          } else {\n            this.balance = \"请求失败\";\n          }\n          this.$apply();\n        }\n      }\n    },\n    prevent() {},\n    async closeNotification(e) {\n      const { id } = e.currentTarget.dataset;\n      this.importantInfoStatus = false;\n      const res = await setMessageRead(id);\n      if (res.data && res.data.data) {\n        this.swiperInfo = this.swiperInfo.filter(info => info.id !== id);\n        this.$apply();\n      }\n    }\n  };\n  events = {\n    changeAnnualStatus() {\n      this.annualStatus = false;\n    }\n  };\n  mixins = [ClassMixin];\n  async getBalance() {\n    let yktInfoCache = wepy.getStorageSync(\"yktInfo\");\n    if (!yktInfoCache) {\n      const moduleStatus = wepy.getStorageSync(\"moduleStatus\");\n      const ytkModuleStatus = this.visitorModeStatus\n        ? { open: true }\n        : moduleStatus.find(x => x.moduleName === \"一卡通\");\n      if (ytkModuleStatus && !ytkModuleStatus.open) {\n        this.balance = \"暂停服务\";\n        this.$apply();\n      } else {\n        const { data: response } = await this.judgeCampusCard();\n        if (response.data) {\n          yktInfoCache = { data: response.data, time: new Date() };\n          wepy.setStorageSync(\"yktInfo\", yktInfoCache);\n        } else {\n          if (response.errCode === 24) {\n            this.balance = \"密码需要更新\";\n          } else if (response.errCode === 34) {\n            this.balance = \"需要绑定一卡通\";\n          } else {\n            this.balance = \"请求失败\";\n          }\n          this.$apply();\n          return;\n        }\n      }\n    }\n    const { data, time } = yktInfoCache;\n    const tempDate = new Date(time);\n    const formatTimeString = raw =>\n      raw.toString().length < 2 ? \"0\" + raw.toString() : raw.toString();\n    this.time = this.graduateIdentity\n      ? `2019-6-20 毕业典礼`\n      : `${tempDate.getFullYear()}-${tempDate.getMonth() +\n          1}-${tempDate.getDate()} ${formatTimeString(\n          tempDate.getHours()\n        )}:${formatTimeString(tempDate.getMinutes())}:${formatTimeString(\n          tempDate.getSeconds()\n        )}`;\n    if (this.graduateIdentity) {\n      this.balance =\n        (Number(data.db_balance) + Number(data.unset_balance)) / 100;\n    } else {\n      this.balance =\n        (Number(data.db_balance) + Number(data.unsettle_amount)) / 100;\n    }\n    this.$apply();\n    wepy.setStorageSync(\"sno\", data.sno);\n  }\n  dealCourse(course, assignWeek = 0, assignDayNum = 0) {\n    const now = new Date();\n    let common = wepy.getStorageSync(\"common\");\n    let nowWeek =\n      assignWeek !== 0\n        ? assignWeek\n        : this.visitorModeStatus\n        ? 4\n        : parseInt(common.week);\n    let todayCourse = this.handleCourses(course, nowWeek);\n    let today = assignDayNum !== 0 ? assignDayNum - 1 : now.getDay() - 1;\n    today = today === -1 ? 6 : today;\n    let allcourses = todayCourse[0][today];\n    if (todayCourse[1][today].length >= 1) {\n      allcourses.push(...todayCourse[1][today]);\n    }\n    let colorArr = this.courseColor;\n    let nowCourses = [];\n    for (let i in allcourses) {\n      if (\n        allcourses[i].weekarr.indexOf(nowWeek) !== -1 &&\n        allcourses[i].weekarr.indexOf(nowWeek) !== \"-1\"\n      ) {\n        allcourses[i].time =\n          \"第\" +\n          allcourses[i].sectionstart +\n          \"-\" +\n          allcourses[i].sectionend +\n          \"节\";\n        allcourses[i].bgc = colorArr[i % 5];\n        nowCourses.push(allcourses[i]);\n      }\n    }\n    this.courses = nowCourses;\n    if (this.courses.length >= 0) {\n      this.courses.sort((a, b) => {\n        return a.sectionstart - b.sectionstart;\n      });\n    }\n    this.noCourseItem = this.courses.length === 0;\n    this.loadHide = true;\n    const allMinutes = now.getHours() * 60 + now.getMinutes();\n    let courseIndex =\n      [\n        [8, 45],\n        [9, 35],\n        [10, 35],\n        [11, 25],\n        [12, 15],\n        [14, 30],\n        [15, 20],\n        [16, 20],\n        [17, 10],\n        [19, 15],\n        [20, 10],\n        [21, 5]\n      ].findIndex(x => x[0] * 60 + x[1] > allMinutes) + 1;\n    if (courseIndex === 0) {\n      courseIndex = 12;\n    }\n    let currentCourse =\n      this.courses.findIndex(x => x.sectionend >= courseIndex) + 1;\n    if (currentCourse === 0) {\n      currentCourse = this.courses.length + 1;\n    }\n    for (let i = 0; i < currentCourse - 1; i++) {\n      this.courses[i].bgc = \"#D8D8D8\";\n    }\n    this.$apply();\n    setTimeout(() => {\n      this.courseToView = `course${Math.min(\n        currentCourse,\n        this.courses.length\n      )}`;\n      this.$apply();\n    }, 200);\n  }\n  async moduleStatusJudge() {\n    const moduleStatus = await getModuleStatus();\n    const newModule = wepy.getStorageSync(\"newModule\")\n      ? wepy.getStorageSync(\"newModule\")\n      : [];\n    if (moduleStatus.data) {\n      const moduleStatusData = moduleStatus.data.data;\n      if (wepy.getStorageSync(\"moduleStatus\")) {\n        const preModuleStatus = wepy.getStorageSync(\"moduleStatus\");\n        for (let i of moduleStatusData) {\n          for (let j of preModuleStatus) {\n            if (i.moduleName === j.moduleName) {\n              if (\n                i.isNew &&\n                i.notificationHash !== j.notificationHash &&\n                !newModule.includes(i)\n              ) {\n                newModule.push(i);\n              }\n            }\n          }\n        }\n        if (newModule.length) {\n          wepy.setStorageSync(\"newModule\", newModule);\n          for (let i of newModule) {\n            for (let j of this.functionalList) {\n              if (i.moduleName === j.name || j.name === \"更多\") {\n                j.isNew = true;\n              }\n            }\n          }\n        }\n      }\n      wepy.setStorageSync(\"moduleStatus\", moduleStatusData);\n    }\n    const functionalItem = this.functionalList.find(item => item.id === 15);\n    if (functionalItem) {\n      functionalItem.module = \"正方\";\n    }\n  }\n  async mockInit() {\n    this.functionalList = this.$parent.globalData.modules.slice(0, 8);\n    wepy.setStorageSync(\"indexIcon\", this.functionalList);\n    this.getBalance();\n    mockClassSchedule().then(res => {\n      if (res.data) {\n        wepy.setStorageSync(\"timetable\", res.data.data);\n        this.dealCourse(res.data.data);\n        this.loadHide = true;\n        this.$apply();\n      }\n    });\n    mockGetNotification().then(res => {\n      if (res.data) {\n        const {\n          data: { data: notificationList }\n        } = res;\n        this.swiperInfo = notificationList\n          .filter(notification => {\n            return !notification.read;\n          })\n          .sort((prev, next) => prev.createDate < next.createDate);\n        if (this.swiperInfo.length > 0) {\n          this.isNewInfo = true;\n        }\n        this.$apply();\n      }\n    });\n    mockGetExercise().then(res => {\n      if (res.data.data) {\n        this.runTime = res.data.data.totalCount;\n        this.$apply();\n      }\n    });\n  }\n\n  async init() {\n    const indexIconList = wepy.getStorageSync(\"indexIcon\");\n    if (indexIconList && indexIconList.length === 8) {\n      this.functionalList = indexIconList;\n    } else {\n      this.functionalList = this.$parent.globalData.modules.slice(0, 8);\n    }\n    // this.functionalList = this.$parent.globalData.modules.slice(0, 8);\n    wepy.setStorageSync(\"indexIcon\", this.functionalList);\n    const userInfoResponse = await getUserInfo();\n    if (userInfoResponse.data) {\n      await this.methods.judgeGraduateStatus(\n        userInfoResponse.data.data.graduate\n      );\n      let userInfo = userInfoResponse.data.data;\n      userInfo.nativeInformation.avatar = this.avatarUrl[\n        Math.floor(Math.random() * 3)\n      ];\n      wepy.setStorageSync(\"User\", userInfo);\n\n      if (!wepy.getStorageSync(\"token\") || !userInfo.enabled) {\n        wepy.reLaunch({\n          url: \"/others-page/pages/login\"\n        });\n      } else {\n        // 获取消息\n        getNotification().then(res => {\n          if (res.data) {\n            const {\n              data: { data: notificationList }\n            } = res;\n            this.swiperInfo = notificationList\n              .filter(notification => {\n                return !notification.read;\n              })\n              .sort((prev, next) => prev.createDate < next.createDate);\n            if (this.swiperInfo.length > 0) {\n              //  判断未读消息中是否有重要通知\n              const importantMsg = this.swiperInfo.find(msg => msg.type === 0);\n              if (importantMsg) {\n                this.importantInfoStatus = true;\n                this.importantInfo = {\n                  ...importantMsg,\n                  content: importantMsg.content.trim().split(\"\\n\")\n                };\n              }\n              this.isNewInfo = true;\n            }\n            this.$apply();\n          }\n        });\n        this.moduleStatusJudge();\n        runningCount().then(res => {\n          if (res.data.data) {\n            this.runTime = res.data.data.totalCount;\n            this.$apply();\n          }\n        });\n        commonInformation().then(common => {\n          common.data && wepy.setStorageSync(\"common\", common.data.data);\n        });\n\n        this.methods.judgeMemoryModeStatus().then(() => {\n          this.checkGraduateMode(userInfo.name);\n\n          this.getBalance();\n\n          // 本科生走 if 里的逻辑\n          if (!this.graduateIdentity) {\n            classSchedule().then(timetable => {\n              if (timetable.data && timetable.data.data) {\n                const timetableData = timetable.data.data.timetable;\n                wepy.setStorageSync(\"timetable\", timetableData);\n                this.classInfo.timetable = timetableData;\n                this.$apply();\n              }\n            });\n            getCourses().then(extraCourse => {\n              if (extraCourse.data && extraCourse.data.data) {\n                const extraCourseData = extraCourse.data.data.map(\n                  item => item.courseModel\n                );\n                wepy.setStorageSync(\"extraCourse\", extraCourseData);\n                this.classInfo.extraCourse = extraCourseData;\n                this.$apply();\n              }\n            });\n            assignTimetable().then(assign => {\n              if (assign.data && assign.data.data) {\n                const {\n                  semester,\n                  specialDayNum,\n                  week,\n                  year\n                } = assign.data.data;\n                this.classInfo.assign = { week, specialDayNum };\n              }\n            });\n            const userInfoCache = wepy.getStorageSync(\"userInfo\");\n\n            if (!userInfoCache || !userInfoCache.studentId) {\n              educationSystemInformation().then(res => {\n                if (res.data && res.data.data) {\n                  wepy.setStorageSync(\"userInfo\", res.data.data);\n                }\n              });\n            }\n          }\n        });\n      }\n    }\n  }\n\n  /**\n   * 检查毕业生身份相关逻辑\n   */\n  checkGraduateMode(name) {\n    this.graduateName = name;\n    if (this.graduateIdentity && !this.chooseMemoryMode) {\n      wepy.navigateTo({\n        url: `../others-edu-page/graduatePages/index?name=${name}`\n      });\n    }\n    if (\n      this.graduateIdentity &&\n      this.chooseMemoryMode &&\n      !wepy.getStorageSync(\"graduateModal\")\n    ) {\n      this.hiGraduateModal = true;\n    }\n    if (this.graduateIdentity) {\n      this.noCourseItem = true;\n      this.loadHide = true;\n    }\n    this.$apply();\n  }\n\n  judgeCampusCard() {\n    return this.visitorModeStatus\n      ? mockCampusCardRequestInfo()\n      : campusCardRequestInfo(this.geaduateIdentity);\n  }\n  async onShow() {\n    wepy.setNavigationBarColor({\n      frontColor: \"#000000\",\n      backgroundColor: \"#fff\",\n      animation: {\n        duration: 0\n      }\n    });\n    wepy.setNavigationBarTitle({\n      title: \"NJUPT\"\n    });\n    wepy.showTabBar();\n    const token = wepy.getStorageSync(\"token\");\n    const userInfo = wepy.getStorageSync(\"User\");\n    if (!this.visitorModeStatus && userInfo) {\n      if (token && userInfo && userInfo.enabled) {\n        this.getBalance();\n        const timetable = wepy.getStorageSync(\"timetable\");\n        if (timetable) {\n          this.loadWrong = false;\n        }\n        // 判断口令\n        const copyData = await wepy.getClipboardData();\n        const filterStr = copyData.data.match(/€(.+?)€/g);\n        if (filterStr !== null) {\n          const filterCommand = filterStr[0].substring(\n            1,\n            filterStr[0].length - 1\n          );\n          if (this.assoInfo && filterCommand !== this.assoInfo.command) {\n            associationDetail(filterCommand).then(res => {\n              if (res.data.data) {\n                this.commandInfoStatus = true;\n                const { assoInfo, assoInfoDetails } = res.data.data;\n                const associationItem = assoInfoDetails.find(x => x.type === 1);\n                if (associationItem) {\n                  const avatar = associationItem.picUrl;\n                  this.assoInfo = {\n                    avatar,\n                    command: filterCommand,\n                    info: assoInfo\n                  };\n                  this.commandInfoStatus = true;\n                  this.$apply();\n                }\n              }\n            });\n          }\n        }\n        //  刷新消息\n        getNotification().then(res => {\n          if (res.data) {\n            const {\n              data: { data: notificationList }\n            } = res;\n            this.swiperInfo = notificationList\n              .filter(notification => {\n                return !notification.read;\n              })\n              .sort((prev, next) => prev.createDate < next.createDate);\n            if (this.swiperInfo.length > 0) {\n              this.isNewInfo = true;\n            }\n            this.$apply();\n          }\n        });\n      }\n    }\n  }\n  /**\n   * onLoad后主要是先判断是否为游客模式\n   *  如果不是就同时获取开屏，资讯页信息，调用init\n   */\n  onLoad() {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    if (this.visitorModeStatus) {\n      wepy.$store.dispatch({ type: `SET_GRADUATE_FALSE` });\n      this.mockInit();\n    } else {\n      const token = wepy.getStorageSync(\"token\");\n      if (token) {\n        // 首页开屏\n        getDisplay().then(res => {\n          const display = wepy.getStorageSync(\"display\");\n          if (res.data && res.data.data !== null) {\n            const {\n              displayId,\n              color,\n              picture,\n              link,\n              appId,\n              type\n            } = res.data.data;\n            if (type === 0) {\n              this.navigatorTarget = \"miniProgram\";\n              this.navigatorAppId = appId;\n            } else if (type === 1) {\n              this.navigatorTarget = \"self\";\n              this.navigatorUrl =\n                `../others-page/pages/display-webview?link=` + link;\n            } else if (type === 4) {\n              this.navigatorTarget = \"self\";\n              this.navigatorUrl = link;\n            }\n            let count = wepy.getStorageSync(\"openthePage\") || 0;\n            switch (true) {\n              case displayId !== display.displayId:\n                count = 0;\n                wepy.setStorageSync(\"display\", {\n                  displayPic: picture,\n                  displayColor: color,\n                  displayId\n                });\n              case count < 5:\n                this.openPage = true;\n                this.displayPic = picture;\n                this.displayColor = color;\n                count++;\n                wepy.setStorageSync(\"openthePage\", count);\n                break;\n              default:\n                break;\n            }\n            this.$apply();\n          }\n        });\n        getPromotionInformation(1, 10).then(res => {\n          const { success, data } = res.data;\n          if (success) {\n            if (data.totalAdCount !== wepy.getStorageSync(\"newsListSum\")) {\n              wepy.showTabBarRedDot({\n                index: 1\n              });\n            }\n          }\n        });\n      }\n      this.init();\n    }\n  }\n  // async onPullDownRefresh() {\n  //   if (!this.openPage) {\n  //     await this.init();\n  //   }\n  //   wepy.stopPullDownRefresh();\n  // }\n}\n</script>\n\n<style lang=\"stylus\" scoped>\nvendors = official\n@import '../css/search-input'\n@import '../css/loading'\n.hi-graduate\n  position fixed\n  background-color rgba(0,0,0,0.8)\n  z-index 30000\n  width 100vw\n  height 100vh\n  .hi-graduate-img\n    width 311rpx\n    height 413rpx\n    position absolute\n    top 244rpx\n    left 318rpx\n  .hi-graduate-talk\n    width 450rpx\n    position absolute\n    top 544rpx\n    left 151rpx\n    color #ffffff\n    .graduate-talk-title\n      font-weight 400\n      font-size 36rpx\n      margin-bottom 23rpx\n    .graduate-talk-content\n      font-size 24rpx\n      font-weight 200\n    .graduate-divide\n      height 23rpx\n.split-line\n  width 750rpx\n  height 15rpx\n  background #f5f5f5\n.splitLine\n  width 710rpx\n  height 2rpx\n  margin 0 auto\n  background rgb(239, 238, 239)\n.open-page-container\n  height 100vh\n  width 100vw\n  background-size cover\n  background-repeat no-repeat\n  background-position bottom center\n  .pass-open-page-container\n    position absolute\n    width 87px\n    height 87px\n    bottom 0\n    right 10px\n  .pass-open-page\n    position absolute\n    right 54rpx\n    padding 0rpx 6rpx\n    bottom 54rpx\n    height 44rpx\n    line-height 44rpx\n    font-size 24rpx\n    color #AAAAAA\n    text-align center\n    border-radius 20rpx\n    border 1rpx solid #AAAAAA\n    background #fff\n.navbar\n  box-shadow 0 6rpx 4rpx 0 rgba(0, 0, 0, 0.05)\n  display flex\n  align-items center\n.search-bar\n  padding 20rpx\n  position relative\n  font-size 30rpx\n  width 100%\n  box-sizing border-box\n  .virsual-placeholder\n    width calc(100% - 20px)\n    position absolute\n    display inline-block\n    z-index 1\n    color #999CA0\n    top 32rpx\n    left 30rpx\n    text-align center\n    .search-icon\n      width 30rpx\n      height 30rpx\n      margin-right 25rpx\n      position relative\n      top 4rpx\n  .search-input\n    pointer-events none\n    width 100%\n.alert-img\n  width 45rpx\n  height 48rpx\n  margin-left 35rpx\n  margin-top -8rpx\n  &.shake\n    animation shaking 1.5s ease-in 1s infinite normal\n    transform-origin 50% -20%\n    animation-iteration-count 3\n    @keyframes shaking\n      0%\n        transform rotate(0)\n      20%\n        transform rotate(-10deg)\n      40%\n        transform rotate(16deg)\n      50%\n        transform rotate(-16deg)\n      60%\n        transform rotate(16deg)\n      70%\n        transform rotate(-16deg)\n      80%\n        transform rotate(10deg)\n      100%\n        transform rotate(0)\n.functional\n  width 750rpx\n  display flex\n  font-size 28rpx\n  flex-wrap wrap\n  margin-top 50rpx\n  margin-bottom 7rpx\n  .functional-item\n    width 25%\n    margin-bottom 41rpx\n    text-align center\n    position relative\n    .functional-item-image\n      width 60rpx\n      height 60rpx\n      display block\n      margin 0 auto\n      margin-bottom 10rpx\n    .image-red-dot\n      position absolute\n      top -10rpx\n      right 30rpx\n      height 25rpx\n      width 25rpx\n      border-radius 50%\n      background #fd2200\n.school-talk-container\n  width 550rpx\n  margin 0 auto\n  .school-talk\n    width 550rpx\n    min-height 0rpx\n    height 130rpx\n.notification-container\n  position relative\n  width 710rpx\n  margin 0 auto\n  min-height 120rpx\n  display flex\n  align-items center\n  .notification-image\n    height 100rpx\n    width 100rpx\n    background-image url('https://static.airbob.org/under-graduate/%E8%82%96%E8%BE%B0%E6%97%AD%E6%89%81%E5%B9%B3%E5%8C%96.png')\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n    margin-left 20rpx\n    margin-right 55rpx\n    position relative\n    .notification-oval\n      color #fff\n      font-size 26rpx\n      width 40rpx\n      height 32rpx\n      display flex\n      align-items center\n      justify-content center\n      border-radius 100rpx\n      border 5rpx solid #fff\n      background #fd2200\n      position absolute\n      top -2px\n      right 0\n    .move\n      animation move 1.2s ease 1s infinite normal\n      @keyframes move\n        0%\n          transform translateY(0)\n        50%\n          transform translateY(3px)\n        100%\n          transform translateY(0)\n  .notification-content\n    position relative\n    height 80rpx\n    line-height 80rpx\n    width 600rpx\n    font-size 28rpx\n    .swiper-content\n      width 500rpx\n      height 80rpx\n      line-height 80rpx\n      overflow hidden\n      text-overflow ellipsis\n      white-space nowrap\n  .notification-arrow\n    position absolute\n    right 0\n    top 50%\n    margin-top -13rpx\n    width 26rpx\n    height 26rpx\n    background-image url('https://static.airbob.org/under-graduate/%E5%8F%B3%E7%AE%AD%E5%A4%B4.png')\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n.laboratory-container\n  width 750rpx\n  padding 30rpx 0\n  margin 0 auto\n  .container-top\n    margin 0 20rpx\n  .newfunction-container\n    width 100%\n    display flex\n    font-size 28rpx\n    flex-wrap wrap\n    margin-top 50rpx\n    margin-bottom 7rpx\n    .functional-item\n      width 25%\n      margin-bottom 41rpx\n      text-align center\n      .functional-item-image\n        width 60rpx\n        height 60rpx\n        display block\n        margin 0 auto\n        margin-bottom 10rpx\n.course-container\n  width 710rpx\n  margin 0 auto\n  padding 30rpx 0\n  .nocourse-list\n    width 710rpx\n    height 150rpx\n    display flex\n    align-items center\n    background #FFFFFF\n    box-shadow 0 0 20rpx 0 rgba(0, 0, 0, 0.1)\n    border-radius 30rpx\n    .nocourse-image\n      width 200rpx\n      height 100rpx\n      margin 25rpx 35rpx\n      background-image url('https://static.airbob.org/under-graduate/pic_noclass.png')\n      background-position center\n      background-size contain\n      background-repeat no-repeat\n    .nocourse-word\n      text-align center\n      font-family PingFangSC-Regular\n      font-size 28rpx\n      line-height 150rpx\n      color #353535\n      letter-spacing -0.62px\n    .graduate-word\n      font-size 26rpx\n      font-family PingFangSC-Regular\n      color #353535\n  .course-list\n    width 100%\n    white-space nowrap\n    color #fff\n    .course-item\n      display inline-block\n      margin-right 10rpx\n      width 270rpx\n      height 150rpx\n      font-size 24rpx\n      border-radius 16rpx\n      padding 20rpx\n      box-sizing border-box\n      .course-thing\n        width 270rpx\n        display flex\n        flex-direction column\n        justify-content space-between\n        view\n          line-height 38rpx\n          overflow hidden\n          text-overflow ellipsis\n          white-space nowrap\n.container-top\n  position relative\n  display flex\n  align-items center\n  font-size 30rpx\n  height 30rpx\n  margin-bottom 20rpx\n  .container-top-title\n    color #353535\n    font-weight bold\n  span\n    position absolute\n    font-size 24rpx\n    right 35rpx\n    color #888888\n  .arrow\n    position absolute\n    top 2rpx\n    right 0rpx\n    width 26rpx\n    height 26rpx\n    background-image url('https://static.airbob.org/under-graduate/%E5%8F%B3%E7%AE%AD%E5%A4%B4.png')\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n.card-container\n  width 710rpx\n  margin 0 auto\n  padding 30rpx 0\n.campus-card\n  width 710rpx\n  height 280rpx\n  background-image url('https://static.airbob.org/under-graduate/%E4%B8%80%E5%8D%A1%E9%80%9A%E5%8D%A1%E7%89%87.png')\n  background-position center\n  background-repeat no-repeat\n  background-size contain\n  font-size 28rpx\n  text-align center\n  .content\n    padding-top 50rpx\n    .bigger\n      font-size 40rpx\n      font-weight 600\n    .content-container\n      display flex\n      justify-content center\n      align-items center\n      flex-direction column\n      .refresh-container\n        width 160rpx\n        height 60rpx\n        background-color rgba(255,255,255,0.8)\n        display flex\n        align-items center\n        justify-content center\n        border-radius 30rpx\n        margin-top 10rpx\n        box-shadow 1rpx 1rpx 3rpx rgba(84,218,255,0.5)\n        .refresh\n          width 40rpx\n          height 40rpx\n        .refresh-rolling\n          animation rolling 0.4s linear 0s infinite;\n.run-card\n  width 710rpx\n  height 280rpx\n  background-image url('https://static.airbob.org/under-graduate/%E6%99%A8%E8%B7%91%E5%8D%A1%E7%89%87.png')\n  background-position center\n  background-repeat no-repeat\n  background-size contain\n  .run-detail\n    padding-top 80rpx\n    margin-left 40rpx\n    font-size 28rpx\n    span\n      font-weight 600\n      font-size 40rpx\n.perfect-info\n  position fixed\n  z-index 99\n  top 0\n  bottom 0\n  left 0\n  right 0\n  background rgba(0, 0, 0, 0.5)\n  display flex\n  justify-content center\n  .perfect-info-body\n    margin auto\n    height 300px\n    &.notification\n      height auto\n      .notification-tip\n        height 60rpx\n        font-size 1rem\n        margin-top 20rpx\n        line-height 60rpx\n        text-align center\n        color #cecece\n      .notification-close\n        width 90%\n        height 70rpx\n        display flex\n        align-items center\n        justify-content center\n        border-top 2rpx solid #e3e3e3\n        font-size 30rpx\n        color #1d1d1d\n        font-weight 800\n    .perfect-img\n      display flex\n      justify-content center\n      margin-bottom -18px\n      image\n        width 186px\n        height 152px\n      &.notification\n        transform translateY(70rpx)\n        image\n          width 360rpx\n          height 340rpx\n    .perfect-info-card\n      width 250px\n      height 188px\n      background #ffffff\n      border-radius 9px\n      display flex\n      align-items center\n      flex-direction column\n      position relative\n      &.notification\n        height auto\n        min-height 376rpx\n        border-top 32rpx solid #50b3cc\n        justify-content flex-start\n        border-radius 24rpx\n      .command-avatar\n        position absolute\n        top -20px\n        view\n          background-image url('https://static.airbob.org/under-graduate/face.png')\n          background-size 100%\n          width 50px\n          height 49px\n          display flex\n          justify-content center\n          align-items center\n          .command-avatar-img\n            width 46px\n            height 45px\n            background-color #ffffff\n            border-radius 50%\n      .submission\n        width 202px\n        height 49px\n        margin-bottom 0\n        background-image linear-gradient(135deg, #a7f3d5 0%, #45d3fb 100%)\n        box-shadow 0px 0px 25px 0px rgba(168, 168, 168, 0.5)\n        border-radius 14px\n        display flex\n        justify-content center\n        align-items center\n        view\n          font-family 'PingFangSC-Semibold'\n          font-size 18px\n          color #ffffff\n      .command-name\n        height 28px\n        font-family 'PingFangSC-Semibold'\n        font-size 20px\n        color #606266\n        padding-bottom 22px\n      .notification-info\n        width 85%\n        text-align left\n        min-height 205rpx\n        max-height 50vh\n        font-size 1rem\n        color #787777\n        margin 15rpx\n        overflow hidden\n        text-overflow ellipsis\n        display -webkit-box\n        -webkit-line-clamp 16\n        -webkit-box-orient vertical\n      .perfect-info-tip\n        font-size 14px\n        color #606266\n        font-family 'PingFangSC-Regular'\n        height 20px\n        text-align center\n        padding 43px 0 3px 0\n        &.notification\n          padding 16rpx 0 0 20rpx\n          border-bottom 2rpx solid #e3e3e3\n          width 90%\n          height auto\n          color #1d1d1d\n          text-align left\n          font-weight 800\n          overflow hidden\n          text-overflow ellipsis\n          display -webkit-box\n          -webkit-line-clamp 2\n          -webkit-box-orient vertical\n@keyframes rolling{\n  0% {\n    transform rotate(0deg);\n  }\n  50% {\n    transform rotate(180deg);\n  }\n  100% {\n    transform rotate(360deg);\n  }\n}\n</style>\n"
  },
  {
    "path": "src/pages/news-list.wpy",
    "content": "<template>\n  <view class=\"container\">\n    <qy-navigation :title=\"navTitle\"></qy-navigation>\n    <qy-tip :on.sync=\"isWrong\" :content=\"tip\"/>\n    <view class=\"top-scroll-container\">\n      <scroll-view class=\"top-scroll\" scroll-x=\"true\">\n        <repeat for=\"{{HeadScroll}}\" index=\"index\" key=\"key\" item=\"item\">\n          <view style=\"display:inline-block\">\n            <view data-index=\"{{index}}\" @tap=\"changeClass\" class=\"scroll-item\" style=\"background-image:url({{item.background}});opacity:{{chosenIndex === index ?'1':'0.6'}};margin-right:{{index === 5? '20rpx' : '0rpx'}}\">\n            </view>\n          </view>\n        </repeat>\n      </scroll-view>\n    </view>\n    <block wx:if=\"{{chosenIndex === 0}}\">\n      <qy-swiper :imgUrls.sync=\"imgUrls\"></qy-swiper>\n    </block>\n    <repeat for=\"{{newsItem[chosenIndex]}}\" index=\"index\" key=\"key\" item=\"item\">\n      <navigator url=\"../others-page/pages/news?title={{item.title}}&&newsId={{item.newsId}}\">\n        <view wx:if=\"{{item.adContent !== undefined && item.isCarousel !== 1}}\" class=\"adItem\" catchtap=\"goToAds({{item.id}})\">\n          <view class=\"adLeft\">\n            <view class=\"ads-title\">\n              {{item.adTitle}}\n            </view>\n            <view class=\"ads-time\">\n              {{item.gmtCreate}}\n              <view class=\"ads-tip\" wx:if=\"{{item.adType === 1}}\">推广资讯</view>\n            </view>\n          </view>\n          <image src=\"{{item.adPicUrl}}\" mode=\"aspectFill\" class=\"adPic\"/>\n        </view>\n        <view wx:else class=\"item\" data-id=\"{{index}}\">\n          <view class=\"item-title\">\n            {{item.title}}\n          </view>\n          <view class=\"item-time\">\n            {{item.createTime}}\n          </view>\n        </view>\n      </navigator>\n    </repeat>\n  </view>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport QyTip from \"@/components/qy-tip\";\nimport QySwiper from \"@/components/qy-swiper\";\nimport navigation from \"@/components/qy-navigation\";\n\nimport {\n  getCarousel,\n  getPromotionInformation,\n  getNewsInformationTopic\n} from \"@/api/common\";\n// import { connect } from \"wepy-redux\";\n\n// @connect({})\nexport default class NewsList extends wepy.page {\n  config = {\n    navigationBarTitleText: \"资讯\"\n  };\n  data = {\n    navTitle: \"资讯\",\n    isWrong: false,\n    tip: \"请求有误！\",\n    chosenIndex: 0,\n    pageNum: 1,\n    isEnd: false,\n    HeadScroll: [\n      {\n        id: \"0\",\n        text: \"活动资讯\",\n        background: \"https://static.airbob.org/under-graduate/ad/news_pic_1.png\"\n      },\n      {\n        id: \"1\",\n        text: \"教务通知\",\n        background: \"https://static.airbob.org/under-graduate/ad/news_pic_2.png\"\n      },\n      {\n        id: \"2\",\n        text: \"南邮要闻\",\n        background: \"https://static.airbob.org/under-graduate/ad/news_pic_3.png\"\n      },\n      {\n        id: \"3\",\n        text: \"通知公告\",\n        background: \"https://static.airbob.org/under-graduate/ad/news_pic_4.png\"\n      },\n      {\n        id: \"4\",\n        text: \"学术文化\",\n        background: \"https://static.airbob.org/under-graduate/ad/news_pic_5.png\"\n      },\n      {\n        id: \"5\",\n        text: \"招聘公告\",\n        background: \"https://static.airbob.org/under-graduate/ad/news_pic_6.png\"\n      }\n    ],\n    newsItem: [[], [], [], [], [], []],\n    adsTitle: \"\",\n    adsCreateTime: \"\",\n    imgUrls: []\n  };\n\n  methods = {\n    changeClass(e) {\n      if (this.chosenIndex !== e.currentTarget.dataset.index) {\n        this.chosenIndex = e.currentTarget.dataset.index;\n        this.isEnd = false;\n        // 判断对应数组的长度\n        let pageNum = this.newsItem[this.chosenIndex].length / 10;\n        if (pageNum === Math.floor(pageNum)) {\n          this.pageNum = pageNum + 1;\n          if (this.chosenIndex === 0) {\n            this.getAds(this.pageNum, 10);\n          } else {\n            this.getNewsList(this.chosenIndex, this.pageNum);\n          }\n        }\n      }\n    },\n\n    goToAds(adId) {\n      wepy.navigateTo({\n        url: \"../others-page/pages/advertisement?adId=\" + adId\n      });\n    }\n  };\n\n  components = {\n    \"qy-tip\": QyTip,\n    \"qy-swiper\": QySwiper,\n    \"qy-navigation\": navigation\n  };\n\n  onLoad() {\n    wepy.hideTabBarRedDot({\n      index: 1\n    });\n    this.getNewsList();\n    this.getAds();\n    this.getCarouselAds();\n  }\n\n  async getCarouselAds() {\n    let that = this;\n    const res = await getCarousel();\n    if (res.data) {\n      let i = 0;\n      res.data.data.map(item => {\n        this.imgUrls.push({\n          on: \"dot\",\n          id: i++,\n          url: this.formatImageUrl(item.adPicUrl),\n          adId: item.id\n        });\n      });\n      this.imgUrls[0].on = \"activeDot\";\n      this.$apply();\n    }\n  }\n\n  async getAds(pageNum = 1, pageSize = 10) {\n    let that = this;\n    if (this.totalAdCount < pageNum * pageSize) {\n      return;\n    }\n    const {\n      data: {\n        data: { adnewsModelList: adList, totalAdCount },\n        success,\n        ...err\n      }\n    } = await getPromotionInformation(pageNum, pageSize);\n    if (success) {\n      wepy.setStorageSync(\"newsListSum\", totalAdCount);\n      this.totalAdCount = totalAdCount;\n      if (adList.length === 0) {\n        this.isEnd = true;\n      } else {\n        this.newsItem[0] = [...this.newsItem[0], ...adList];\n        this.newsItem[0].forEach(({ gmtCreate, adPicUrl }, i) => {\n          this.newsItem[0][i].gmtCreate = this.$parent.timeToDate(gmtCreate);\n          this.newsItem[0][i].adPicUrl = this.formatImageUrl(adPicUrl);\n        });\n      }\n      this.$apply();\n    } else {\n      this.doWrong && this.doWrong(err);\n    }\n  }\n\n  async getNewsList(type = 1, pageNum = 1, pageSize = 10) {\n    let that = this;\n    if (!this.isEnd) {\n      const res = await getNewsInformationTopic(type, pageNum, pageSize);\n      if (res.data) {\n        if (res.data.data.length === 0) {\n          this.isEnd = true;\n        } else {\n          if (pageNum === 1) {\n            this.newsItem[type] = res.data.data;\n          } else {\n            this.newsItem[type] = [...this.newsItem[type], ...res.data.data];\n          }\n        }\n        this.$apply();\n      } else {\n        this.doWrong && this.doWrong(res.data.errMsg);\n      }\n    }\n  }\n\n  // TODO: 后端要记得改 url，前端之后要么删除这个方法要么把 http:// 改成 https://\n  formatImageUrl(url) {\n    return /https?:\\/\\//.test(url) ? url : `http://${url}`;\n  }\n\n  onReachBottom() {\n    this.pageNum++;\n    if (this.chosenIndex === 0) {\n      this.getAds(this.pageNum, 10);\n    } else {\n      this.getNewsList(this.chosenIndex, this.pageNum, 10);\n    }\n  }\n  doWrong(err) {\n    this.isWrong = true;\n    this.$apply();\n  }\n}\n</script>\n<style lang=\"stylus\">\n.container\n  color #353535\n  font-family 'SimHei'\n.top-scroll-container\n  position relative\n  width 750rpx\n  height 110rpx\n  border-bottom 20rpx solid #F5F5F5\n  .top-scroll\n    width 100%\n    height 100%\n    white-space nowrap\n  .scroll-item\n    display flex\n    justify-content flex-end\n    align-items flex-end\n    height 50rpx\n    width 100rpx\n    padding 30rpx 20rpx 20rpx 52rpx\n    margin 0rpx 0rpx 17rpx 20rpx\n    font-size 34rpx\n    padding-right 20rpx\n    color #fff\n    background-size contain\n    background-repeat no-repeat\n    background-position center\n.item\n  position relative\n  padding 30rpx 60rpx 0 60rpx\n  border-bottom 1rpx solid #E3E3E3\n  &:after\n    clear both\n    content '.'\n    display block\n    width 0\n    height 0\n    visibility hidden\n  .item-title\n    font-family PingFangSC-Regular\n    font-size 30rpx\n    color #353535\n  .item-time\n    float right\n    font-size 24rpx\n    color #999CA0\n    margin 10rpx 0\n  .ads-title\n    font-weight bold\n  .ads-tip\n    display inline-block\n    color #00b8ec\n    border 1rpx solid #00b8ec\n    border-radius 10px\n    padding 4rpx 8rpx\n    margin-right 6rpx\n.adItem\n  display flex\n  justify-content space-between\n  width 704rpx\n  height 180rpx\n  margin 30rpx 20rpx 0 26rpx\n  padding 0 0 30rpx 0\n  border-bottom 1rpx solid #E3E3E3\n  .adPic\n    width 180rpx\n    height 180rpx\n    border-radius 40rpx\n  .adLeft\n    display flex\n    flex-direction column\n    justify-content space-between\n    align-items flex-start\n    width 460rpx\n    .ads-title\n      font-family PingFangSC-Regular\n      font-size 30rpx\n      color #353535\n      letter-spacing 0.24rpx\n      display -webkit-box\n      -webkit-box-orient vertical\n      -webkit-line-clamp 3\n      overflow hidden\n    .ads-time\n      font-size 24rpx\n      color #888888\n      letter-spacing 0.12px\n      display flex\n      height 44rpx\n      line-height 44rpx\n      .ads-tip\n        width 120rpx\n        height 40rpx\n        text-align center\n        line-height 40rpx\n        border 2rpx solid #47CFF5\n        border-radius 40rpx\n        color #47CFF5\n        margin-left 8rpx\n</style>\n"
  },
  {
    "path": "src/pages/profile.wpy",
    "content": "<template>\n  <BaseContainer navTitle=\"我的\">\n    <view slot=\"qy-content\">\n      <view class=\"container\" slot=\"qy-content\">\n        <view class=\"info-card\" style=\"background-image:url({{graduateIdentity ? 'https://static.airbob.org/under-graduate/memory/card.png' : 'https://static.airbob.org/under-graduate/userpage/mine_pic_card.png'}})\">\n          <view class=\"main-info\">\n            <view class=\"main-info-avatar\">\n              <open-data type=\"userAvatarUrl\"></open-data>\n            </view>\n            <!-- <image class=\"main-info-avatar\" mode=\"aspectFit\" src=\"{{avatar}}\"/> -->\n            <view class=\"main-info-name\">\n              <view class=\"main-info-name-items\" style=\"font-size:32rpx\">{{name}}</view>\n              <view class=\"main-info-name-items\" style=\"margin-top:15rpx\">\n                已绑定的手机号：{{phoneNumber}}\n                <view class=\"change-phonenumber\" @tap=\"goChangePhone\"></view>\n              </view>\n            </view>\n          </view>\n        </view>\n        <view class=\"function-line\">\n          <view\n            class=\"function-line-image\"\n            style=\"background-image:url('https://static.airbob.org/under-graduate/userpage/mine_icon_help.png')\"\n          ></view>\n          <view class=\"function-line-content\" @tap=\"goFeedback\">\n            帮助与反馈\n            <view class=\"function-line-arrow\"></view>\n          </view>\n        </view>\n        <view class=\"function-line\">\n          <view\n            class=\"function-line-image\"\n            style=\"background-image:url('https://static.airbob.org/changePassword/QjE2MDEyMzI3LWNoYW5nZVBhc3N3b3JkLnBuZw==')\"\n          ></view>\n          <view class=\"function-line-content\" @tap=\"goChangePassword\">\n            修改密码\n            <view class=\"function-line-arrow\"></view>\n          </view>\n        </view>\n        <view class=\"function-line\">\n          <view\n            class=\"function-line-image\"\n            style=\"background-image:url('https://static.airbob.org/under-graduate/userpage/mine_icon_about.png')\"\n          ></view>\n          <view class=\"function-line-content\" @tap=\"goAboutUs\">\n            关于我们\n            <view class=\"function-line-arrow\"></view>\n          </view>\n        </view>\n        <!-- <view class=\"function-line\">\n          <view class=\"function-line-image\" style=\"background-image:url('https://static.airbob.org/under-graduate/userpage/mine_icon_join.png')\"></view>\n          <view class=\"function-line-content\">加入我们<view class=\"function-line-arrow\"></view></view>\n        </view>-->\n        <view class=\"function-line\">\n          <view\n            class=\"function-line-image\"\n            style=\"background-image:url('https://static.airbob.org/under-graduate/userpage/mine_icon_changelog.png')\"\n          ></view>\n          <view class=\"function-line-content\" @tap=\"goChangelog\">\n            更新日志\n            <view class=\"function-line-arrow\"></view>\n          </view>\n        </view>\n        <view class=\"cancel-bind\" @tap=\"bindJudge\">{{loginText}}</view>\n        <button wx:if=\"{{graduateIdentity}}\" class=\"btn close-btn\" @tap=\"close\"><span>关闭“记忆模式”</span></button>\n      </view>\n    </view>\n  </BaseContainer>\n</template>\n\n<script>\nimport wepy from \"wepy\";\nimport { signOut } from \"@/api/common\";\nimport navigation from \"@/components/qy-navigation\";\nimport BaseContainer from \"@/components/baseContainer\";\nimport { chooseMemoryMode } from \"@/api/graduateMode\";\nimport { connect } from \"wepy-redux\";\n@connect({\n  graduateIdentity(state) {\n    return state.graduateReducer.graduateIdentity;\n  }\n})\nexport default class Profile extends wepy.page {\n  config = {\n    navigationBarTitleText: \"我的\"\n  };\n  components = {\n    BaseContainer\n  };\n  mixins = [];\n\n  data = {\n    phoneNumber: \"\",\n    name: \"\",\n    loginText: \"退出登录\",\n    visitorModeStatus: false\n  };\n\n  computed = {};\n\n  methods = {\n    goChangePhone() {\n      if (this.visitorModeStatus) {\n        return this.$invoke(\"BaseContainer\", \"showVisitorTips\");\n      }\n      this.$navigate({\n        url: \"../others-page/pages/personalPages/change-phone\"\n      });\n    },\n    goFeedback() {\n      this.$navigate({\n        url: \"../others-page/pages/feedbackPages/feedback\"\n      });\n    },\n    goAboutUs() {\n      this.$navigate({\n        url: \"../others-page/pages/personalPages/aboutus\"\n      });\n    },\n    goChangelog() {\n      this.$navigate({\n        url: \"../others-page/pages/personalPages/changelog\"\n      });\n    },\n    async goChangePassword() {\n      this.$navigate({\n        url: \"../others-page/pages/personalPages/change-password\"\n      });\n    },\n    bindJudge() {\n      if (this.loginText === \"退出登录\") {\n        wepy\n          .showModal({\n            title: \"即将登出\",\n            content: \"您确定将登出吗\",\n            confirmColor: \"#47CFF5\"\n          })\n          .then(response => {\n            if (response.confirm) {\n              signOut().then(res => {\n                if (res.data.data) {\n                  wepy.clearStorage();\n                  wepy.redirectTo({\n                    url: \"/others-page/pages/login?step=1\"\n                  });\n                }\n              });\n            }\n          });\n      } else {\n        wepy.$store.dispatch({ type: `EXIT_VISITOR_MODE` });\n        wepy.redirectTo({ url: \"/others-page/pages/login?step=1\" });\n      }\n    },\n    async close() {\n      const modalData = await wepy.showModal({\n        content: \"操作不可逆，是否继续？\",\n        confirmColor: \"#dc8545\"\n      });\n      if (modalData.confirm) {\n        const {\n          data: { success }\n        } = await chooseMemoryMode(0);\n        if (success) {\n          wepy.clearStorage();\n        }\n      }\n    }\n  };\n\n  events = {};\n  onLoad() {\n    this.visitorModeStatus = this.$com.BaseContainer.visitorModeStatus;\n    const { nativeInformation, name, studentId } = wepy.getStorageSync(\"User\");\n    this.phoneNumber = nativeInformation\n      ? nativeInformation.phoneNumber\n      : \"xxxxxxxxxxx\";\n    this.loginText = nativeInformation ? \"退出登录\" : \"退出游客模式\";\n    this.name = name || wepy.getStorageSync(\"userInfo\").name || \"游客\";\n  }\n}\n</script>\n\n<style lang=\"stylus\">\n.container\n  width 750rpx\n  .btn\n    width 700rpx\n    height 80rpx\n    border-radius 80rpx\n    color #fff\n    font-size 32rpx\n    display flex\n    align-items center\n    justify-content center\n  .close-btn\n    background-image linear-gradient(82deg, #d78f58 0%, #ba6733 100%),linear-gradient(#f2f2f2, #f2f2f2)\n  .info-card\n    position relative\n    display flex\n    width 750rpx\n    height 390rpx\n    background-position center\n    background-repeat no-repeat\n    background-size contain\n    margin-bottom 60rpx\n    .main-info\n      position relative\n      width 750rpx\n      height 150rpx\n      margin-top 120rpx\n      display flex\n      .main-info-avatar\n        display inline-block\n        width 150rpx\n        height 150rpx\n        margin 0 30rpx 0 60rpx\n        border-radius 50%\n        overflow hidden\n      .main-info-name\n        display inline-block\n        margin-top 25rpx\n        height 100rpx\n        color #fff\n        font-size 24rpx\n        .main-info-name-items\n          height 50rpx\n          display flex\n          line-height 50rpx\n          .change-phonenumber\n            display inline-block\n            margin-left 16rpx\n            width 50rpx\n            height 50rpx\n            background-image url('https://static.airbob.org/under-graduate/phonenum.png')\n            background-repeat no-repeat\n            background-size contain\n            background-position center\n  .function-line\n    position relative\n    width 750rpx\n    height 80rpx\n    display flex\n    align-items center\n    .function-line-image\n      position relative\n      display inline-block\n      width 150rpx\n      height 40rpx\n      background-position center\n      background-repeat no-repeat\n      background-size contain\n    .function-line-content\n      position relative\n      display inline-block\n      font-size 32rpx\n      color #353535\n      width 600rpx\n      height 80rpx\n      line-height 80rpx\n      border-bottom 1rpx solid #F4F4F4\n      .function-line-arrow\n        position absolute\n        width 30rpx\n        height 30rpx\n        top 25rpx\n        right 25rpx\n        background-image url('https://static.airbob.org/under-graduate/userpage/button_right.png')\n        background-position center\n        background-repeat no-repeat\n        background-size contain\n  .cancel-bind\n    width 700rpx\n    font-size 32rpx\n    color #fff\n    height 80rpx\n    line-height 80rpx\n    margin-left 25rpx\n    margin-top 100rpx\n    margin-bottom 15rpx\n    border-radius 50rpx\n    text-align center\n    background linear-gradient(-255deg, #ABDCFF 0%, #6AE4FF 100%)\n</style>\n"
  },
  {
    "path": "src/store/actions/index.js",
    "content": "import {\n  SHOW_GRADUATE_MODAL,\n  HIDE_GRADUATE_MODAL,\n  JUDGE_MEMORY_MODE_STATUS,\n  SET_ISGRADUTE\n} from \"../types/graduate\";\nimport { createAction } from \"redux-actions\";\nimport { checkGraduate } from \"@/api/graduateMode\";\nimport wepy from \"wepy\";\n\nexport const showGraduateModal = createAction(SHOW_GRADUATE_MODAL);\n\nexport const hideGraduateModal = createAction(HIDE_GRADUATE_MODAL);\n\nexport const judgeMemoryModeStatus = createAction(\n  JUDGE_MEMORY_MODE_STATUS,\n  () => {\n    return new Promise(resolve => {\n      if (!wepy.getStorageSync(\"judgeMemoryModeStatus\")) {\n        checkGraduate().then(response => {\n          if (response && response.data) {\n            resolve({ chooseMemoryMode: response.data.data });\n            wepy.setStorageSync(\"judgeMemoryModeStatus\", {\n              chooseMemoryMode: response.data.data\n            });\n          }\n        });\n      } else {\n        resolve(wepy.getStorageSync(\"judgeMemoryModeStatus\"));\n      }\n    });\n  }\n);\n\nexport const judgeGraduateStatus = createAction(SET_ISGRADUTE, isGraduate => {\n  return new Promise(resolve => {\n    if (!wepy.getStorageSync(\"judgeIsGraduateStatus\")) {\n      resolve({ graduateIdentity: isGraduate });\n      wepy.setStorageSync(\"judgeIsGraduateStatus\", {\n        graduateIdentity: isGraduate\n      });\n    } else {\n      resolve(wepy.getStorageSync(\"judgeIsGraduateStatus\"));\n    }\n  });\n});\n"
  },
  {
    "path": "src/store/index.js",
    "content": "import { createStore, applyMiddleware } from \"redux\";\nimport promiseMiddleware from \"redux-promise\";\nimport { createLogger } from \"redux-logger\";\nimport rootReducer from \"./reducers/index\";\nconst middleware = [promiseMiddleware, createLogger()];\nexport default function configStore() {\n  const store = createStore(rootReducer, applyMiddleware(...middleware));\n  return store;\n}\n"
  },
  {
    "path": "src/store/reducers/graduate.js",
    "content": "import { handleActions } from \"redux-actions\";\nimport {\n  SHOW_GRADUATE_MODAL,\n  HIDE_GRADUATE_MODAL,\n  JUDGE_MEMORY_MODE_STATUS,\n  SET_GRADUATE_FALSE,\n  SET_ISGRADUTE\n} from \"../types/graduate\";\n\nexport default handleActions(\n  {\n    [SHOW_GRADUATE_MODAL](state) {\n      return {\n        ...state,\n        graduateModalStatus: true\n      };\n    },\n    [HIDE_GRADUATE_MODAL](state) {\n      return {\n        ...state,\n        graduateModalStatus: false\n      };\n    },\n    [SET_GRADUATE_FALSE](state) {\n      return {\n        ...state,\n        graduateIdentity: false\n      };\n    },\n    [JUDGE_MEMORY_MODE_STATUS](state, action) {\n      return {\n        ...state,\n        chooseMemoryMode: action.payload.chooseMemoryMode\n      };\n    },\n    [SET_ISGRADUTE](state, action) {\n      return {\n        ...state,\n        graduateIdentity: action.payload.graduateIdentity\n      };\n    }\n  },\n  {\n    graduateModalStatus: false,\n    graduateIdentity: false,\n    chooseMemoryMode: false\n  }\n);\n"
  },
  {
    "path": "src/store/reducers/index.js",
    "content": "import { combineReducers } from \"redux\";\nimport graduateReducer from \"./graduate\";\nimport visitorReducer from \"./visitor-mode\";\n\nexport default combineReducers({ graduateReducer, visitorReducer });\n"
  },
  {
    "path": "src/store/reducers/visitor-mode.js",
    "content": "import { handleActions } from \"redux-actions\";\nimport { ENTER_VISITOR_MODE, EXIT_VISITOR_MODE } from \"../types/visitor-mode\";\n\nexport default handleActions(\n  {\n    [ENTER_VISITOR_MODE](state) {\n      return {\n        ...state,\n        visitorModeStatus: true\n      };\n    },\n    [EXIT_VISITOR_MODE](state) {\n      return {\n        ...state,\n        visitorModeStatus: false\n      };\n    }\n  },\n  {\n    visitorModeStatus: false\n  }\n);\n"
  },
  {
    "path": "src/store/types/graduate.js",
    "content": "export const SHOW_GRADUATE_MODAL = `SHOW_GRADUATE_MODAL`;\n\nexport const HIDE_GRADUATE_MODAL = `HIDE_GRADUATE_MODAL`;\n\nexport const JUDGE_MEMORY_MODE_STATUS = `JUDGE_MEMORY_MODE_STATUS`;\n\nexport const SET_GRADUATE_FALSE = `SET_GRADUATE_FALSE`;\n\nexport const SET_ISGRADUTE = `SET_ISGRADUTE`;\n"
  },
  {
    "path": "src/store/types/visitor-mode.js",
    "content": "export const ENTER_VISITOR_MODE = `ENTER_VISITOR_MODE`;\n\nexport const EXIT_VISITOR_MODE = `EXIT_VISITOR_MODE`;\n"
  },
  {
    "path": "src/utils/Crypto.js",
    "content": "import CryptoJS from \"crypto-js\";\n\n/**\n * base on crypto-js\n * 后端用的是 AES/CBC/PKCS5Padding\n * key 和 iv 为 utf8 编码\n */\nexport default class Crypto {\n  constructor(key, iv) {\n    this.key = key;\n    this.iv = iv;\n  }\n\n  static utf8Encode(x) {\n    return CryptoJS.enc.Utf8.parse(x);\n  }\n\n  static random() {\n    return CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Base64);\n  }\n\n  /**\n   * 加密函数\n   */\n  encrypt(data) {\n    return CryptoJS.AES.encrypt(data, this.key, {\n      iv: this.iv\n    }).ciphertext.toString(CryptoJS.enc.Base64);\n  }\n\n  jsonEncrypt(data) {\n    return CryptoJS.AES.encrypt(JSON.stringify(data), this.key, {\n      iv: this.iv\n    }).ciphertext.toString(CryptoJS.enc.Base64);\n  }\n\n  /**\n   * 解密函数\n   */\n  decrypt(data) {\n    return CryptoJS.AES.decrypt(data, this.key, {\n      iv: this.iv\n    }).toString(CryptoJS.enc.Utf8);\n  }\n\n  jsonDecrypt(data) {\n    return JSON.parse(this.decrypt(data));\n  }\n}\n"
  },
  {
    "path": "wepy.config.js",
    "content": "const path = require(\"path\");\r\nvar prod = process.env.NODE_ENV === \"production\";\r\n\r\nmodule.exports = {\r\n  wpyExt: \".wpy\",\r\n  build: {\r\n    web: {\r\n      htmlTemplate: path.join(\"src\", \"index.template.html\"),\r\n      htmlOutput: path.join(\"web\", \"index.html\"),\r\n      jsOutput: path.join(\"web\", \"index.js\")\r\n    }\r\n  },\r\n  resolve: {\r\n    alias: {\r\n      \"@\": path.join(__dirname, \"src\")\r\n    },\r\n    modules: [\"node_modules\"]\r\n  },\r\n  eslint: true,\r\n  compilers: {\r\n    pug: {},\r\n    stylus: {\r\n      compress: true\r\n    },\r\n    babel: {\r\n      sourceMap: true,\r\n      presets: [\"env\", \"stage-1\"],\r\n      plugins: [\r\n        \"transform-class-properties\",\r\n        \"transform-decorators-legacy\",\r\n        \"transform-object-rest-spread\",\r\n        \"transform-export-extensions\",\r\n        \"syntax-export-extensions\"\r\n      ]\r\n    }\r\n  },\r\n  plugins: {},\r\n  appConfig: {\r\n    noPromiseAPI: [\"createSelectorQuery\"]\r\n  }\r\n};\r\n\r\nif (prod) {\r\n  delete module.exports.compilers.babel.sourcesMap;\r\n  // 压缩 stylus\r\n  module.exports.compilers[\"stylus\"] = { compress: true };\r\n\r\n  // 压缩js\r\n  module.exports.plugins = {\r\n    uglifyjs: {\r\n      filter: /\\.js$/,\r\n      config: {}\r\n    },\r\n    imagemin: {\r\n      filter: /\\.(jpg|png|jpeg)$/,\r\n      config: {\r\n        jpg: {\r\n          quality: 80\r\n        },\r\n        png: {\r\n          quality: 80\r\n        }\r\n      }\r\n    }\r\n  };\r\n}\r\n"
  }
]