Full Code of bailicangdu/vue2-elm for AI

master b85ff0220366 cached
87 files
507.2 KB
142.2k tokens
63 symbols
1 requests
Download .txt
Showing preview only (535K chars total). Download the full file or copy to clipboard to get everything.
Repository: bailicangdu/vue2-elm
Branch: master
Commit: b85ff0220366
Files: 87
Total size: 507.2 KB

Directory structure:
gitextract_552txq2t/

├── .babelrc
├── .editorconfig
├── .github/
│   └── workflows/
│       └── close_inactive_issue.yml
├── .gitignore
├── COPYING
├── README-en.md
├── README.md
├── build/
│   ├── build.js
│   ├── dev-client.js
│   ├── dev-server.js
│   ├── utils.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config/
│   └── index.js
├── index.html
├── package.json
└── src/
    ├── App.vue
    ├── components/
    │   ├── common/
    │   │   ├── alertTip.vue
    │   │   ├── buyCart.vue
    │   │   ├── computeTime.vue
    │   │   ├── loading.vue
    │   │   ├── mixin.js
    │   │   ├── ratingStar.vue
    │   │   ├── shoplist.vue
    │   │   └── svg.vue
    │   ├── footer/
    │   │   └── footGuide.vue
    │   └── header/
    │       └── head.vue
    ├── config/
    │   ├── env.js
    │   ├── fetch.js
    │   ├── mUtils.js
    │   └── rem.js
    ├── main.js
    ├── page/
    │   ├── balance/
    │   │   ├── balance.vue
    │   │   └── children/
    │   │       └── detail.vue
    │   ├── benefit/
    │   │   ├── benefit.vue
    │   │   └── children/
    │   │       ├── commend.vue
    │   │       ├── coupon.vue
    │   │       ├── exchange.vue
    │   │       ├── hbDescription.vue
    │   │       └── hbHistory.vue
    │   ├── city/
    │   │   └── city.vue
    │   ├── confirmOrder/
    │   │   ├── children/
    │   │   │   ├── children/
    │   │   │   │   ├── addAddress.vue
    │   │   │   │   └── children/
    │   │   │   │       └── searchAddress.vue
    │   │   │   ├── chooseAddress.vue
    │   │   │   ├── invoice.vue
    │   │   │   ├── payment.vue
    │   │   │   ├── remark.vue
    │   │   │   └── userValidation.vue
    │   │   └── confirmOrder.vue
    │   ├── download/
    │   │   └── download.vue
    │   ├── find/
    │   │   └── find.vue
    │   ├── food/
    │   │   └── food.vue
    │   ├── forget/
    │   │   └── forget.vue
    │   ├── home/
    │   │   └── home.vue
    │   ├── login/
    │   │   └── login.vue
    │   ├── msite/
    │   │   └── msite.vue
    │   ├── order/
    │   │   ├── children/
    │   │   │   └── orderDetail.vue
    │   │   └── order.vue
    │   ├── points/
    │   │   ├── children/
    │   │   │   └── detail.vue
    │   │   └── points.vue
    │   ├── profile/
    │   │   ├── children/
    │   │   │   ├── children/
    │   │   │   │   ├── address.vue
    │   │   │   │   ├── children/
    │   │   │   │   │   ├── add.vue
    │   │   │   │   │   └── children/
    │   │   │   │   │       └── addDetail.vue
    │   │   │   │   └── setusername.vue
    │   │   │   └── info.vue
    │   │   └── profile.vue
    │   ├── search/
    │   │   └── search.vue
    │   ├── service/
    │   │   ├── children/
    │   │   │   └── questionDetail.vue
    │   │   └── service.vue
    │   ├── shop/
    │   │   ├── children/
    │   │   │   ├── children/
    │   │   │   │   └── shopSafe.vue
    │   │   │   ├── foodDetail.vue
    │   │   │   └── shopDetail.vue
    │   │   └── shop.vue
    │   └── vipcard/
    │       ├── children/
    │       │   ├── invoiceRecord.vue
    │       │   ├── useCart.vue
    │       │   └── vipDescription.vue
    │       └── vipcard.vue
    ├── router/
    │   └── router.js
    ├── service/
    │   └── getData.js
    ├── store/
    │   ├── action.js
    │   ├── getters.js
    │   ├── index.js
    │   ├── mutation-types.js
    │   └── mutations.js
    └── style/
        ├── common.scss
        └── mixin.scss

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
  "presets": ["es2015", "stage-2"],
  "plugins": ["transform-runtime"],
  "comments": false,
}


================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .github/workflows/close_inactive_issue.yml
================================================
name: Close Inactive Issue

on:
  schedule:
    - cron: "0 0 * * *"

jobs:
  close-issues:
    runs-on: ubuntu-latest
    steps:
      - name: close inactive issue
        uses: actions-cool/issues-helper@v2.2.1
        with:
          actions: 'close-issues'
          labels: 'inactive'
          inactive-day: 30
          body: |
            Since the issue was labeled with `inactive`, but no response in 30 days. This issue will be close. If you have any questions, you can comment and reply.
            由于该 issue 被标记为不活跃,且 30 天未收到回应。现关闭 issue,若有任何问题,可评论回复。


================================================
FILE: .gitignore
================================================
.DS_Store
node_modules/
npm-debug.log
package-lock.json
# 忽略使用WebStorm开发时,生成的缓存文件夹
.idea
# 忽略使用VSCode开发时,生成的缓存文件夹
.vscode
tree.md
*.idea

elm/


================================================
FILE: COPYING
================================================

          GNU GENERAL PUBLIC LICENSE
            Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

          Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

        GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

          NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

         END OF TERMS AND CONDITIONS

      How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.

================================================
FILE: README-en.md
================================================
# Introduction

[README in Chinese](README.md)

When I began to learn to vue, search of some practical source code about vue, but most of them are simple demo and didn't help to explore the vue. The most of demo are front-end page, such as music player interaction not as complicated as expected.But in actual work, we often meet some project involving money, such as shopping cart page. This kind of project is complex, accompany by login, register ,user information and so on. It's difficult, no one has ever written a project like this in vue and commit to github. So I write it, hope I can help you. 

This functional project is practical but often boring, with no music player so gorgeous. For a long time, I think that Elm APP is a good material. First, it is complex that the open delivery platform is more complicated than the typical project. Second, you won't get bored seeing so much beautiful food.

But why is the Elm APP, not Baidu App or Meituan App? The reason is simple, that Elm's layout is the most beautiful and the most comfortable in the three APP.

There are 45 pages of this project, involving registration, login, merchandise display, shopping cart, order and so on. It is a complete process. The average company project is not that complicated, so if you can understand this project fully, I believe that you can able to do the most of single-page applications in the other company. Even if it's more complex, and it won't be much higher than this one.

The project was done in the spare time, actually it was written years ago and over the years, so the spend time seem a bit long. The project spend more than two months from beginning to end. Now it has been completed, some performance optimizations are being performed to add detailed annotations.

In addition, the project don't related elm video of imooc website, and that project only have one page. After watching the official documentation of vue, I wrote this project directly, and without reference to any code, so please don't mix them up.

__Note: This project is purely personal. If you want to order, please choose the official elm client.__



## Technology

vue2 + vuex + vue-router + webpack + ES6/7 + fetch + sass + flex + svg


## Development

Note:This project used a lot of properties such as ES6/7, so node 6.0.0+ is required.

```
git clone https://github.com/bailicangdu/vue2-elm.git  

cd vue2-elm

npm install

npm run dev

```


## More
This project has the supporting background system. If you want to develop it, you can download the corresponding backend system.[backend system](https://github.com/bailicangdu/node-elm)。

Backend system's run command:npm run local .

If you only do the front-end development, ignore this note.


# Explain

>  If it helps you, you can click "Star" in the upper right corner to support,thank you. ^_^

>  May be you can "follow" me, I will make more interstng projects.

>  Development environment: macOS 10.12.3  Chrome 56  nodejs 6.10.0

>  Thanks for 辰妹子[@bailichen](https://github.com/bailichen), [@iceRao](https://github.com/raoenhui),to help complete the project,thank you🌹

>  If you hava some question,you can post the question in Issues, and if you find some solution or some improvement,please pull request. 👍

>  [communication group](https://gitter.im/vue2-elm/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link)

>  Recommend a open source project about react and redux。[address](https://github.com/bailicangdu/react-pxq)

>  Recommend a other demo about vue2 and vuex,it's simple and good for newbie.[address](https://github.com/bailicangdu/vue2-happyfri)


## Dscription of the data interface 🤔

### 2017-05-30

For some reason,previous interfaces could not be used, it made the project failed to run.The new backend system is built by nodejs.[backend system address](https://github.com/bailicangdu/node-elm). It can kept consisent with the offical website. And provide corresponding [background management system](https://github.com/bailicangdu/vue2-manage)


# Demo

[click it](http://cangdu.org/elm/)(Preview with chrome phone mode please)

### The mobile can scan the qr code in the below

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/ewm.png" width="250" height="250"/>



# Features
- [x] location function -- finished
- [x] choose city -- finished
- [x] search address-- finished
- [x] display a list of merchant that near by the selected address -- finished
- [x] find food or restaurant -- finished
- [x] sorting and filter according to distance,sales,rating,special course,distribution and so on -- finished
- [x] food list of restaurant -- finished
- [x] cart function -- finished
- [x] evaluation page of shop -- finished
- [x] detail page about one food-- finished
- [x] detail page about merchant -- finished
- [x] login、register -- finished
- [x] change password -- finished
- [x] user center -- finished
- [x] send message、voice verification -- finished
- [x] order function -- finished ✨✨🎉🎉
- [x] order list -- finished
- [x] order detail -- finished
- [x] download App -- finished
- [x] add、delete、change delivery address -- finished
- [x] account info -- finished
- [x] service center -- finished
- [x] red packet -- finished
- [x] upload avator -- finished
- [ ] pay -- No money~~



# Summarize

1, It is not the official of elm, so it is necessary to open the agent, and must be opened on the PC. At most, you can order but not more, after the success of the order, you can check and pay the payment on your mobile phone.

2, In general, the page involves money that is complicated, especially like elm? An open platform, It has many types of merchants and foods, need some complex interaction between page and page. When I writing the cart and order pages, without API but it has a lot of 

3, Vue is so bright, because of it's a lightweight framework good at the small and medium-sized project. Whem you want make a large single-page application, you can use vuex, the performance is still outstanding. In the treatment of the complex interaction logic page, vuex is necessary. So if you use vue and vuex, you can make large single-page projects.

4, Now, after make process of the login to register, homepage, search, businesses, shopping cart, order, order list, personal center and so on. I not only understanding the vue to a deeper level, and it's can help for me to control the large project in the future. Do a practical project has great improvement in myself.

5, Sometimes I doubt that to spend a few months make this project has meaning or not. At first I just wanted to do a small project, but I didn't think I could write more, but when I finished I believed it was worth it.

6, The project was already finished, and have 45 pages.


# Ultimate Goal

1, Build a background system to simulate the delivery platform with node.js。[address](https://github.com/bailicangdu/node-elm)

2, Use react-native to write native APP of Android and IOS。[地址在这里](https://github.com/bailicangdu/React-Native-elm)

3、May be I will make a seller's version in the future.
  
  So my goal is to build a full ecosystem across the frontend , backend, IOS and Android.
  
  ...Waiting for me



# Screenshot


### store list page

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/msite.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/msite.gif" width="365" height="619"/>


### store filter page

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/food.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/food.gif" width="365" height="619"/>



### food list and cart

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/shop_cart.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/shop_cart.gif" width="365" height="619"/>

### oder check page

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/confirm1.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/confirmOrder.gif" width="365" height="619"/>


### search page

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/search.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/search.gif" width="365" height="619"/>


### login page

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/login1.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/login.gif" width="365" height="619"/>


### user center

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/profile.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/profile.gif" width="365" height="619"/>






# Layout

```
.
├── build                                       // webpack config file
├── config                                      // package path
├── elm                                         // online project file,can access if put them one the server
├── screenshots                                 // screenshot
├── src                                         // source directory
│   ├── components                              // components
│   │   ├── common                              // common components
│   │   │   ├── alertTip.vue                    // popup components
│   │   │   ├── buyCart.vue                     // cart components
│   │   │   ├── computeTime.vue                 // countdown components
│   │   │   ├── loading.vue                     // the animation component when page is initialized
│   │   │   ├── mixin.js                        // mixinf components(inculde:directive-loading more,make picture address)
│   │   │   ├── ratingStar.vue                  // the five rating star component about comment
│   │   │   └── shoplist.vue                    // the resturant list common component of msite and shop page
│   │   ├── footer
│   │   │   └── footGuide.vue                   // footer common component
│   │   └── header
│   │       └── head.vue                        // header common component
│   ├── config                                  // basic configuration
│   │   ├── env.js                              // environment switch configuration
│   │   ├── fetch.js                            // git data
│   │   ├── mUtils.js                           // common function about js
│   │   └── rem.js                              // px transform rem
│   ├── images                                  // public picture
│   ├── page
│   │   ├── balance
│   │   │   ├── balance.vue                     // balance page
│   │   │   └── children
│   │   │       └── detail.vue                  // balance detail page
│   │   ├── benefit
│   │   │   ├── benefit.vue                     // benefit pahe
│   │   │   └── children
│   │   │       ├── commend.vue                 // recommend prize
│   │   │       ├── coupon.vue                  // coupon introduction
│   │   │       ├── exchange.vue                // exchange benefit
│   │   │       ├── hbDescription.vue           // benefit descripting
│   │   │       └── hbHistory.vue               // benefit's history
│   │   ├── city                 
│   │   │   └── city.vue                        // local city page
│   │   ├── confirmOrder
│   │   │   ├── children
│   │   │   │   ├── children
│   │   │   │   │   ├── addAddress.vue          // add address page
│   │   │   │   │   └── children
│   │   │   │   │       └── searchAddress.vue   // search address page
│   │   │   │   ├── chooseAddress.vue           // choose address page
│   │   │   │   ├── invoice.vue                 // choose invoice page
│   │   │   │   ├── payment.vue                 // pay page
│   │   │   │   ├── remark.vue                  // order remark page 
│   │   │   │   └── userValidation.vue          // user validation page
│   │   │   └── confirmOrder.vue                // confirm order page
│   │   ├── download
│   │   │   └── download.vue                    // downlad App
│   │   ├── find
│   │   │   └── find.vue                        // find page
│   │   ├── food
│   │   │   └── food.vue                        // food filter sort page
│   │   ├── forget
│   │   │   └── forget.vue                      // forget password, change password
│   │   ├── home
│   │   │   └── home.vue                        // index page
│   │   ├── login
│   │   │   └── login.vue                       // login and register page
│   │   ├── msite
│   │   │   └── msite.vue                       // merchant list page
│   │   ├── order
│   │   │   ├── children
│   │   │   │   └── orderDetail.vue             // order detail page
│   │   │   └── order.vue                       // order list page
│   │   ├── points
│   │   │   ├── children
│   │   │   │   └── detail.vue                  // points detail page
│   │   │   └── points.vue                      // points page
│   │   ├── profile
│   │   │   ├── children
│   │   │   │   ├── children
│   │   │   │   │   ├── address.vue             // address page
│   │   │   │   │   └── children
│   │   │   │   │       ├── add.vue             // add address page
│   │   │   │   │       └── children
│   │   │   │   │           └── addDetail.vue   // search address page
│   │   │   │   ├── info.vue                    // account info page
│   │   │   │   └── setusername.vue             // reset user page
│   │   │   └── profile.vue                     // user profile page
│   │   ├── search
│   │   │   └── search.vue                      // search page
│   │   ├── service
│   │   │   ├── children
│   │   │   │   └── questionDetail.vue          // question detail page
│   │   │   └── service.vue                     // service center page
│   │   ├── shop
│   │   │   ├── children
│   │   │   │   ├── children
│   │   │   │   │   └── shopSafe.vue            // shop check info page
│   │   │   │   ├── foodDetail.vue              // food detail page
│   │   │   │   └── shopDetail.vue              // shop detail page
│   │   │   └── shop.vue                        // shop filter page
│   │   └── vipcard
│   │       ├── children
│   │       │   ├── invoiceRecord.vue           // invoice record page
│   │       │   ├── useCart.vue                 // use card page
│   │       │   └── vipDescription.vue          // vip deacription page
│   │       └── vipcard.vue                     // vip handling page
│   ├── plugins                                 // plugins
│   ├── router
│   │   └── router.js                           // router configuration
│   ├── service                                 // data interaction and unified deployment
│   │   ├── getData.js                          // the unified deployment file for get data, and unified management of interfaces
│   │   └── tempdata                            // temporary data for the development
│   ├── store                                   // Vuex status management
│   │   ├── action.js                           // actions configuration
│   │   ├── getters.js                          // getters configuration
│   │   ├── index.js                            // use vuex,new store
│   │   ├── modules                             // store modules
│   │   ├── mutation-types.js                   // make const for muations
│   │   └── mutations.js                        // mutations configuration
│   └── style
│       ├── common.scss                         // common css
│       ├── mixin.scss                          // cs configuration file
│       └── swiper.min.css
│   ├── App.vue                                 // entry page js file
│   ├── main.js                                 // the main js for loading components
├── favicon.ico                                 // icon
├── index.html                                  // entry page html file
.

56 directories, 203 files
```


# License

[GPL](https://github.com/bailicangdu/vue2-elm/blob/master/COPYING)


================================================
FILE: README.md
================================================
# 前言

[README in English](README-en.md)

初学vue时曾在网上搜索vue的实战项目源码,无奈大部分都是简单的demo,对于深究vue没有太大的帮助,剩下的一些大部分都是像音乐播放器之类的展示型项目,交互没有预期那么复杂。但我们实际在工作中,经常会遇到有购物车的项目,这类项目因为涉及到money,所以对逻辑严谨度要求高,页面之间交互复杂,又会伴随着登录、注册、用户信息等等,常常会让我们很头疼。既然还没人用vue写过这样的项目,那不如我来写,开源出来对能看到的人也会有帮助。

这种功能性的项目很实用但是往往也很枯燥,没有音乐播放器那么看起来绚丽,思来想去发现饿了么是一个不错的素材,一来它足够复杂,开放的外卖平台比一般的公司独有商店更加复杂。二来 见到那么多美食,大家也不会感觉到厌烦。

为啥是饿了么,而不是美团?原因很简单,饿了么的色调和布局是最漂亮的,看起来最舒服。

此项目大大小小共 45 个页面,涉及注册、登录、商品展示、购物车、下单等等,是一个完整的流程。一般公司即便是官网的单页面项目都没这么复杂,如果这个项目能驾驭的了,相信大部分公司的其他单页面应用也就不在话下,即便更复杂,也不会比这个高到哪里去。

因为利用业余时间来做,年前就开始写,又跨个年,周期有点长,项目从零布局到完成共用了2个多月的时间。

另外,这个项目和慕课网视频的那个饿了么没有任何关系,慕课网的项目只有一个页面,我在看完vue的官方文档后直接写了这个项目,没有参照任何人的代码,请大家不要混为一谈。

__注1:此项目纯属个人瞎搞,正常下单请选择饿了么官方客户端。__

__注2:项目预览地址和接口需要使用https访问哦!__


## 技术栈

vue2 + vuex + vue-router + webpack + ES6/7 + fetch + sass + flex + svg


## 项目运行

#### 注意:由于涉及大量的 ES6/7 等新属性,node 需要 6.0 以上版本

```
git clone https://github.com/bailicangdu/vue2-elm.git  

cd vue2-elm

npm install 或 yarn(推荐)

npm run dev

```
## 关于接口数据

此项目的所有接口数据都来源于配套的后台系统,[后台项目传送地址](https://github.com/bailicangdu/node-elm)。

如果想体验前后台同时开发,可以下载后台系统。

此时启动本项目的命令为:npm run local 而不是 npm run dev。

同时我们也提供了基于`element-ui`搭建的[后台管理页面](https://github.com/bailicangdu/vue2-manage)

如果只做前端开发,请忽略上面这几句话哟~


# 说明

>  如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^

>  或者您可以 "follow" 一下,我会不断开源更多的有趣的项目

>  开发环境 macOS 10.12.3  Chrome 56  nodejs 6.10.0

>  特别感谢[@bailichen](https://github.com/bailichen), [@iceRao](https://github.com/raoenhui),在百忙之中抽出时间和我一起完成了这个项目,辛苦了🌹

>  如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR 👍

>  [项目交流群](https://gitter.im/vue2-elm/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link)

>  推荐一个 react + redux 开源项目,对react感兴趣的朋友赶紧去看看。[地址在这里](https://github.com/bailicangdu/react-pxq)

>  另外一个 vue2 + vuex 的入门项目,比当前的项目简单很多,非常适合入门练习。[地址在这里](https://github.com/bailicangdu/vue2-happyfri)


# 效果演示

[查看demo请戳这里](https://cangdu.org/elm/#/msite)(请用chrome手机模式预览)

### 移动端扫描下方二维码

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/ewm.png" width="200" height="200"/>



# 目标功能
- [x] 定位功能 -- 完成
- [x] 选择城市 -- 完成
- [x] 搜索地址 -- 完成
- [x] 展示所选地址附近商家列表 -- 完成
- [x] 搜索美食,餐馆 -- 完成
- [x] 根据距离、销量、评分、特色菜、配送方式等进行排序和筛选 -- 完成
- [x] 餐馆食品列表页 -- 完成
- [x] 购物车功能 -- 完成
- [x] 店铺评价页面 -- 完成
- [x] 单个食品详情页面 -- 完成
- [x] 商家详情页 -- 完成
- [x] 登录、注册 -- 完成
- [x] 修改密码 -- 完成
- [x] 个人中心 -- 完成
- [x] 发送短信、语音验证 -- 完成
- [x] 下单功能 -- 完成 ✨✨🎉🎉
- [x] 订单列表 -- 完成
- [x] 订单详情 -- 完成
- [x] 下载App -- 完成
- [x] 添加、删除、修改收货地址 -- 完成
- [x] 帐户信息 -- 完成
- [x] 服务中心 -- 完成
- [x] 红包 -- 完成
- [x] 上传头像 -- 完成
- [ ] 付款 -- 臣妾做不到啊~~



# 总结

1、一般涉及到money的网页逻辑都比较复杂,尤其像饿了么这样一个开放的平台,商家和食品种类繁多,页面与页面之间交互复杂,在写到 购物车 和 下单 功能时众多的数据和逻辑一度让人很头疼,又没有设计和接口api文档,只能一步步摸索。

2、vue因其轻量级的框架在中小型项目中表现亮眼,在大型单页面应用中因为vuex的存在,表现依然出色,在处理复杂交互逻辑的时候,vuex的存在是不可或缺的。所以说利用 vue + vuex 完全可以去做大型的单页面项目。

3、项目写到现在,从 登录注册到、首页、搜索、商家列表、购物车、下单、订单列表、个人中心 一个流程走完之后、不但对vue的理解更深一层,而且对以后掌控大型项目的时候也有非常多的帮助,做一个实际的项目才能对自己有很大的提升。

4、曾一度怀疑,花几个月的时间做这样一个项目到底有没有意义,本来只是想做一个小项目练练手,没想到后来越写越多,不过坚持下来后我相信一切都是值得的。

5、项目已经完成,共45个页面。


# 最终目标

1、用node.js构建一个模拟外卖平台的后台系统。[地址在这里](https://github.com/bailicangdu/node-elm)

2、写出跨 Android 和 IOS 的原生APP版本。[地址在这里](https://github.com/bailicangdu/native-xdm)

3、如果时间来的及,会出一卖家版本。

所以我的目的是构建一个横跨前后端,移动IOS、Android的完整生态圈。

。。。敬请期待




# 部分截图


### 商铺列表页

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/msite.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/msite.gif" width="365" height="619"/>


### 商铺筛选页

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/food.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/food.gif" width="365" height="619"/>



### 餐馆食品列表与购物车

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/shop_cart.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/shop_cart.gif" width="365" height="619"/>

### 确认订单页

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/confirm1.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/confirmOrder.gif" width="365" height="619"/>


### 搜索页

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/search.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/search.gif" width="365" height="619"/>


### 登录页

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/login1.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/login.gif" width="365" height="619"/>


### 个人中心

<img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/profile.png" width="365" height="619"/> <img src="https://github.com/bailicangdu/vue2-elm/blob/master/screenshots/profile.gif" width="365" height="619"/>






# 项目布局

```
.
├── build                                       // webpack配置文件
├── config                                      // 项目打包路径
├── elm                                         // 上线项目文件,放在服务器即可正常访问
├── screenshots                                 // 项目截图
├── src                                         // 源码目录
│   ├── components                              // 组件
│   │   ├── common                              // 公共组件
│   │   │   ├── alertTip.vue                    // 弹出框组件
│   │   │   ├── buyCart.vue                     // 购物车组件
│   │   │   ├── computeTime.vue                 // 倒计时组件
│   │   │   ├── loading.vue                     // 页面初始化加载数据的动画组件
│   │   │   ├── mixin.js                        // 组件混合(包括:指令-下拉加载更多,处理图片地址)
│   │   │   ├── ratingStar.vue                  // 评论的五颗星组件
│   │   │   └── shoplist.vue                    // msite和shop页面的餐馆列表公共组件
│   │   ├── footer
│   │   │   └── footGuide.vue                   // 底部公共组件
│   │   └── header
│   │       └── head.vue                        // 头部公共组件
│   ├── config                                  // 基本配置
│   │   ├── env.js                              // 环境切换配置
│   │   ├── fetch.js                            // 获取数据
│   │   ├── mUtils.js                           // 常用的js方法
│   │   └── rem.js                              // px转换rem
│   ├── images                                  // 公共图片
│   ├── page
│   │   ├── balance
│   │   │   ├── balance.vue                     // 余额页
│   │   │   └── children
│   │   │       └── detail.vue                  // 余额说明
│   │   ├── benefit
│   │   │   ├── benefit.vue                     // 红包页
│   │   │   └── children
│   │   │       ├── commend.vue                 // 推荐有奖
│   │   │       ├── coupon.vue                  // 代金券说明
│   │   │       ├── exchange.vue                // 兑换红包
│   │   │       ├── hbDescription.vue           // 红包说明
│   │   │       └── hbHistory.vue               // 历史红包
│   │   ├── city
│   │   │   └── city.vue                        // 当前城市页
│   │   ├── confirmOrder
│   │   │   ├── children
│   │   │   │   ├── children
│   │   │   │   │   ├── addAddress.vue          // 添加地址页
│   │   │   │   │   └── children
│   │   │   │   │       └── searchAddress.vue   // 搜索地址页
│   │   │   │   ├── chooseAddress.vue           // 选择地址页
│   │   │   │   ├── invoice.vue                 // 选择发票页
│   │   │   │   ├── payment.vue                 // 付款页
│   │   │   │   ├── remark.vue                  // 订单备注页
│   │   │   │   └── userValidation.vue          // 用户验证页
│   │   │   └── confirmOrder.vue                // 确认订单页
│   │   ├── download
│   │   │   └── download.vue                    // 下载App
│   │   ├── find
│   │   │   └── find.vue                        // 发现页
│   │   ├── food
│   │   │   └── food.vue                        // 食品筛选排序页
│   │   ├── forget
│   │   │   └── forget.vue                      // 忘记密码,修改密码页
│   │   ├── home
│   │   │   └── home.vue                        // 首页
│   │   ├── login
│   │   │   └── login.vue                       // 登录注册页
│   │   ├── msite
│   │   │   └── msite.vue                       // 商铺列表页
│   │   ├── order
│   │   │   ├── children
│   │   │   │   └── orderDetail.vue             // 订单详情页
│   │   │   └── order.vue                       // 订单列表页
│   │   ├── points
│   │   │   ├── children
│   │   │   │   └── detail.vue                  // 积分说明
│   │   │   └── points.vue                      // 积分页
│   │   ├── profile
│   │   │   ├── children
│   │   │   │   ├── children
│   │   │   │   │   ├── address.vue             // 地址
│   │   │   │   │   └── children
│   │   │   │   │       ├── add.vue             // 新增地址
│   │   │   │   │       └── children
│   │   │   │   │           └── addDetail.vue   // 搜索地址
│   │   │   │   ├── info.vue                    // 帐户信息
│   │   │   │   └── setusername.vue             // 重置用户名
│   │   │   └── profile.vue                     // 个人中心
│   │   ├── search
│   │   │   └── search.vue                      // 搜索页
│   │   ├── service
│   │   │   ├── children
│   │   │   │   └── questionDetail.vue          // 问题详情
│   │   │   └── service.vue                     // 服务中心
│   │   ├── shop
│   │   │   ├── children
│   │   │   │   ├── children
│   │   │   │   │   └── shopSafe.vue            // 商铺认证信息页
│   │   │   │   ├── foodDetail.vue              // 商铺信息页
│   │   │   │   └── shopDetail.vue              // 单个商铺信息页
│   │   │   └── shop.vue                        // 商铺筛选页
│   │   └── vipcard
│   │       ├── children
│   │       │   ├── invoiceRecord.vue           // 购买记录
│   │       │   ├── useCart.vue                 // 使用卡号购买
│   │       │   └── vipDescription.vue          // 会员说明
│   │       └── vipcard.vue                     // 会员卡办理页
│   ├── plugins                                 // 引用的插件
│   ├── router
│   │   └── router.js                           // 路由配置
│   ├── service                                 // 数据交互统一调配
│   │   ├── getData.js                          // 获取数据的统一调配文件,对接口进行统一管理
│   │   └── tempdata                            // 开发阶段的临时数据
│   ├── store                                   // vuex的状态管理
│   │   ├── action.js                           // 配置actions
│   │   ├── getters.js                          // 配置getters
│   │   ├── index.js                            // 引用vuex,创建store
│   │   ├── modules                             // store模块
│   │   ├── mutation-types.js                   // 定义常量muations名
│   │   └── mutations.js                        // 配置mutations
│   └── style
│       ├── common.scss                         // 公共样式文件
│       ├── mixin.scss                          // 样式配置文件
│       └── swiper.min.css
│   ├── App.vue                                 // 页面入口文件
│   ├── main.js                                 // 程序入口文件,加载各种公共组件
├── favicon.ico                                 // 图标
├── index.html                                  // 入口html文件
.

56 directories, 203 files
```

# License

[GPL](https://github.com/bailicangdu/vue2-elm/blob/master/COPYING)


================================================
FILE: build/build.js
================================================
// https://github.com/shelljs/shelljs
require('shelljs/global')
env.NODE_ENV = 'production'

var path = require('path')
var config = require('../config')
var ora = require('ora')
var webpack = require('webpack')
var webpackConfig = require('./webpack.prod.conf')

var spinner = ora('building for production...')
spinner.start()

var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
rm('-rf', assetsPath)
mkdir('-p', assetsPath)
cp('-R', 'static/*', assetsPath)

webpack(webpackConfig, function(err, stats) {
    spinner.stop()
    if (err) throw err
    process.stdout.write(stats.toString({
        colors: true,
        modules: false,
        children: false,
        chunks: false,
        chunkModules: false
    }) + '\n')
})

================================================
FILE: build/dev-client.js
================================================
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')

hotClient.subscribe(function(event) {
	if (event.action === 'reload') {
		window.location.reload()
	}
})

================================================
FILE: build/dev-server.js
================================================
var config = require('../config')
if (!process.env.NODE_ENV) process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var opn = require('opn')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')

// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
    // Define HTTP proxies to your custom API backend
    // https://github.com/chimurai/http-proxy-middleware

var server = express()
var compiler = webpack(webpackConfig)

var devMiddleware = require('webpack-dev-middleware')(compiler, {
    publicPath: webpackConfig.output.publicPath,
    stats: {
        colors: true,
        chunks: false
    }
})

var hotMiddleware = require('webpack-hot-middleware')(compiler)
    // force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function(compilation) {
    compilation.plugin('html-webpack-plugin-after-emit', function(data, cb) {
        hotMiddleware.publish({
            action: 'reload'
        })
        cb()
    })
})

var context = config.dev.context

switch(process.env.NODE_ENV){
    case 'local': var proxypath = 'http://localhost:8001'; break;
    case 'online': var proxypath = 'https://elm.cangdu.org'; break;
    default:  var proxypath = config.dev.proxypath;
}
var options = {
    target: proxypath,
    changeOrigin: true,
}
if (context.length) {
    server.use(proxyMiddleware(context, options))
}

// handle fallback for HTML5 history API
server.use(require('connect-history-api-fallback')())

// serve webpack bundle output
server.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
server.use(hotMiddleware)

// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
server.use(staticPath, express.static('./static'))

module.exports = server.listen(port, function(err) {
    if (err) {
        console.log(err)
        return
    }
    var uri = 'http://localhost:' + port
    console.log('Listening at ' + uri + '\n')

    // when env is testing, don't need open it
    if (process.env.NODE_ENV !== 'testing') {
        opn(uri)
    }
})


================================================
FILE: build/utils.js
================================================
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

exports.assetsPath = function(_path) {
    var assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory
    return path.posix.join(assetsSubDirectory, _path)
}

exports.cssLoaders = function(options) {
    options = options || {}
        // generate loader string to be used with extract text plugin
    function generateLoaders(loaders) {
        var sourceLoader = loaders.map(function(loader) {
            var extraParamChar
            if (/\?/.test(loader)) {
                loader = loader.replace(/\?/, '-loader?')
                extraParamChar = '&'
            } else {
                loader = loader + '-loader'
                extraParamChar = '?'
            }
            return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
        }).join('!')

        // (which is the case during production build)
        if (options.extract) {
            return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
        } else {
            return ['vue-style-loader', sourceLoader].join('!')
        }
    }

    // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
    return {
        css: generateLoaders(['css']),
        postcss: generateLoaders(['css']),
        less: generateLoaders(['css', 'less']),
        sass: generateLoaders(['css', 'sass?indentedSyntax']),
        scss: generateLoaders(['css', 'sass']),
        stylus: generateLoaders(['css', 'stylus']),
        styl: generateLoaders(['css', 'stylus'])
    }
}

// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function(options) {
    var output = []
    var loaders = exports.cssLoaders(options)
    for (var extension in loaders) {
        var loader = loaders[extension]
        output.push({
            test: new RegExp('\\.' + extension + '$'),
            loader: loader
        })
    }
    return output
}

================================================
FILE: build/webpack.base.conf.js
================================================
var path = require('path')
var config = require('../config')
var utils = require('./utils')
var projectRoot = path.resolve(__dirname, '../')

var env = process.env.NODE_ENV
    // check env & config/index.js to decide weither to enable CSS Sourcemaps for the
    // various preprocessor loaders added to vue-loader at the end of this file
var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
var useCssSourceMap = cssSourceMapDev || cssSourceMapProd


module.exports = {
    entry: {
        app: './src/main.js'
    },
    output: {
        path: config.build.assetsRoot,
        publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
        filename: '[name].js'
    },
    resolve: {
        extensions: ['', '.js', '.vue', '.less', '.css', '.scss'],
        fallback: [path.join(__dirname, '../node_modules')],
        alias: {
            'vue$': 'vue/dist/vue.common.js',
            'src': path.resolve(__dirname, '../src'),
            'assets': path.resolve(__dirname, '../src/assets'),
            'components': path.resolve(__dirname, '../src/components')
        }
    },
    resolveLoader: {
        fallback: [path.join(__dirname, '../node_modules')]
    },
    module: {
        loaders: [{
            test: /\.vue$/,
            loader: 'vue'
        }, {
            test: /\.js$/,
            loader: 'babel',
            include: projectRoot,
            exclude: /node_modules/
        }, {
            test: /\.json$/,
            loader: 'json'
        }, {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            loader: 'url',
            query: {
                limit: 10000,
                name: utils.assetsPath('img/[name].[ext]')
            }
        }, {
            test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'url',
            query: {
                limit: 10000,
                name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
            }
        }]
    },
    vue: {
        loaders: utils.cssLoaders({
            sourceMap: useCssSourceMap
        }),
        postcss: [
            require('autoprefixer')({
                browsers: [
                  'Android >= 4.4',
                  'iOS >= 8'
                ]
            })
        ]
    }
}


================================================
FILE: build/webpack.dev.conf.js
================================================
var config = require('../config')
var webpack = require('webpack')
var merge = require('webpack-merge')
var utils = require('./utils')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')

// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function(name) {
    baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

module.exports = merge(baseWebpackConfig, {
    module: {
        loaders: utils.styleLoaders({
            sourceMap: config.dev.cssSourceMap
        })
    },
    // eval-source-map is faster for development
    devtool: '#eval-source-map',
    plugins: [
        new webpack.DefinePlugin({
            'process.env': config.dev.env
        }),
        // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin(),
        // https://github.com/ampedandwired/html-webpack-plugin
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            favicon: 'favicon.ico',
            inject: true
        })
    ]
})

================================================
FILE: build/webpack.prod.conf.js
================================================
var path = require('path')
var config = require('../config')
var utils = require('./utils')
var webpack = require('webpack')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var env = config.build.env

var webpackConfig = merge(baseWebpackConfig, {
    module: {
        loaders: utils.styleLoaders({
            sourceMap: config.build.productionSourceMap,
            extract: true
        })
    },
    //devtool: config.build.productionSourceMap ? '#source-map' : false,
    output: {
        path: config.build.assetsRoot,
        filename: utils.assetsPath('js/[name].js'),
        chunkFilename: utils.assetsPath('js/[name].[chunkhash].min.js')
    },
    vue: {
        loaders: utils.cssLoaders({
            sourceMap: config.build.productionSourceMap,
            extract: true
        })
    },
    plugins: [
        // http://vuejs.github.io/vue-loader/en/workflow/production.html
        new webpack.DefinePlugin({
            'process.env': env
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),
        new webpack.optimize.OccurrenceOrderPlugin(),
        // extract css into its own file
        new ExtractTextPlugin(utils.assetsPath('css/[name].css')),
        // generate dist index.html with correct asset hash for caching.
        // you can customize output by editing /index.html
        // see https://github.com/ampedandwired/html-webpack-plugin
        new HtmlWebpackPlugin({
            filename: config.build.index,
            template: 'index.html',
            inject: true,
            // minify: {
            //     removeComments: true,
            //     collapseWhitespace: true,
            //     removeAttributeQuotes: true
            //         // more options:
            //         // https://github.com/kangax/html-minifier#options-quick-reference
            // },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),
        // split vendor js into its own file
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function(module, count) {
                // any required modules inside node_modules are extracted to vendor
                return (
                    module.resource &&
                    /\.js$/.test(module.resource) &&
                    module.resource.indexOf(
                        path.join(__dirname, '../node_modules')
                    ) === 0
                )
            }
        }),
        // extract webpack runtime and module manifest to its own file in order to
        // prevent vendor hash from being updated whenever app bundle is updated
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest',
            chunks: ['vendor']
        })
    ]
})

if (config.build.productionGzip) {
    var CompressionWebpackPlugin = require('compression-webpack-plugin')

    webpackConfig.plugins.push(
        new CompressionWebpackPlugin({
            asset: '[path].gz[query]',
            algorithm: 'gzip',
            test: new RegExp(
                '\\.(' +
                config.build.productionGzipExtensions.join('|') +
                ')$'
            ),
            threshold: 10240,
            minRatio: 0.8
        })
    )
}

module.exports = webpackConfig

================================================
FILE: config/index.js
================================================
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
    build: {
        env: {
            NODE_ENV: '"production"'
        },
        index: path.resolve(__dirname, '../elm/index.html'),
        assetsRoot: path.resolve(__dirname, '../elm'),
        assetsSubDirectory: 'static',
        assetsPublicPath: '/elm/',
        productionSourceMap: true,
        // Surge or Netlify already gzip all static assets for you.
        // Before setting to `true`, make sure to:
        // npm install --save-dev compression-webpack-plugin
        productionGzip: false,
        productionGzipExtensions: ['js', 'css']
    },
    dev: {
        env: {
            NODE_ENV: '"development"'
        },
        port: 8000,
        assetsSubDirectory: 'static',
        assetsPublicPath: '/',
        context: [ //代理路径
            '/shopping',
            '/ugc',
            '/v1',
            '/v2',
            '/v3',
            '/v4',
            '/bos',
            '/member',
            '/promotion',
            '/eus',
            '/payapi',
            '/img',
        ],
        proxypath: 'http://cangdu.org:8001',
        // CSS Sourcemaps off by default because relative paths are "buggy"
        // with this option, according to the CSS-Loader README
        // (https://github.com/webpack/css-loader#sourcemaps)
        // In our experience, they generally work as expected,
        // just be aware of this issue when enabling this option.
        cssSourceMap: false
    }
}

================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui">
    <meta name="screen-orientation" content="portrait"/>
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="full-screen" content="yes">
    <meta name="x5-fullscreen" content="true">
    <link rel="dns-prefetch" href="//cangdu.org">
    <link rel="dns-prefetch" href="//elm.cangdu.org">
    <title>elm</title>
  </head>
  <body>
    <div id="app">
    	<router-view></router-view>
    </div>
  </body>
</html>


================================================
FILE: package.json
================================================
{
  "name": "elm",
  "version": "2.0.1",
  "description": "vue2-elm",
  "author": "cangdu <1264889788@qq.com>",
  "private": true,
  "license": "GPL",
  "scripts": {
    "dev": "cross-env NODE_ENV=online node build/dev-server.js",
    "local": "cross-env NODE_ENV=local node build/dev-server.js",
    "build": "node build/build.js"
  },
  "dependencies": {
    "better-scroll": "1.15.2",
    "fastclick": "^1.0.6",
    "iscroll": "^5.2.0",
    "showdown": "^1.6.4",
    "vue": "^2.1.0",
    "vue-router": "^2.1.1",
    "vuex": "^2.0.0"
  },
  "devDependencies": {
    "autoprefixer": "^6.4.0",
    "autoprefixer-loader": "^3.2.0",
    "babel-core": "^6.0.0",
    "babel-loader": "^6.0.0",
    "babel-plugin-transform-runtime": "^6.0.0",
    "babel-preset-es2015": "^6.0.0",
    "babel-preset-stage-2": "^6.0.0",
    "babel-register": "^6.0.0",
    "babel-runtime": "^6.23.0",
    "chalk": "^1.1.3",
    "connect-history-api-fallback": "^1.1.0",
    "cross-env": "^5.0.0",
    "css-loader": "^0.25.0",
    "eventsource-polyfill": "^0.9.6",
    "express": "^4.13.3",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.9.0",
    "function-bind": "^1.0.2",
    "html-webpack-plugin": "^2.8.1",
    "http-proxy-middleware": "^0.17.2",
    "json-loader": "^0.5.4",
    "less": "^2.7.1",
    "less-loader": "^2.2.3",
    "node-gyp": "^3.4.0",
    "node-sass": "^4.9.2",
    "opn": "^4.0.2",
    "ora": "^0.3.0",
    "sass": "^0.5.0",
    "sass-loader": "^4.1.1",
    "scss": "^0.2.4",
    "scss-loader": "0.0.1",
    "semver": "^5.3.0",
    "shelljs": "^0.7.4",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "vue-loader": "^10.0.0",
    "vue-style-loader": "^1.0.0",
    "vue-template-compiler": "^2.1.0",
    "webpack": "^1.13.2",
    "webpack-dev-middleware": "^1.8.3",
    "webpack-dev-server": "^1.16.2",
    "webpack-hot-middleware": "^2.12.2",
    "webpack-merge": "^0.14.1"
  },
  "engines": {
    "node": ">= 4.0.0",
    "npm": ">= 3.0.0"
  }
}


================================================
FILE: src/App.vue
================================================
<template>
	<div>
		<transition name="router-fade" mode="out-in">
			<keep-alive>
			    <router-view v-if="$route.meta.keepAlive"></router-view>
			</keep-alive>
    	</transition>
    	<transition name="router-fade" mode="out-in">
			<router-view v-if="!$route.meta.keepAlive"></router-view>
		</transition>
		<svg-icon></svg-icon>	
    </div>
</template>

<script>
	import svgIcon from './components/common/svg';
  	export default {
    	components:{
            svgIcon
        },
  	}

</script>

<style lang="scss">
  	@import './style/common';
	.router-fade-enter-active, .router-fade-leave-active {
	  	transition: opacity .3s;
	}
	.router-fade-enter, .router-fade-leave-active {
	  	opacity: 0;
	}
</style>


================================================
FILE: src/components/common/alertTip.vue
================================================
 <template>
    <div class="alet_container">
	    <section class="tip_text_container">
            <div class="tip_icon">
                <span></span>
                <span></span>
            </div>
            <p class="tip_text">{{alertText}}</p>
            <div class="confrim" @click="closeTip">确认</div>
        </section>
    </div>
</template>

<script>
    export default {
    	data(){
            return{
                positionY: 0,
                timer: null,
            }
        },
        mounted(){
      
        },
        props: ['alertText'],
        methods: {
            closeTip(){
                this.$emit('closeTip')
            }
        }
    }
</script>

<style lang="scss" scoped>
    @import '../../style/mixin';
	@keyframes tipMove{
       0%   { transform: scale(1) }
       35%  { transform: scale(.8) }
       70%  { transform: scale(1.1) }
       100% { transform: scale(1) }
    }
    .alet_container{
    	position: fixed;
    	top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 200;
    }
    .tip_text_container{
        position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -6rem;
        margin-left: -6rem;
        width: 12rem;
        animation: tipMove .4s ;
        background-color: rgba(255,255,255,1);
        border: 1px;
        padding-top: .6rem;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        border: 1px;
        border-radius: 0.25rem;
        .tip_icon{
            @include wh(3rem, 3rem);
            border: 0.15rem solid #f8cb86;
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            span:nth-of-type(1){
                @include wh(.12rem, 1.5rem);
                background-color: #f8cb86;
            }
            span:nth-of-type(2){
                @include wh(.2rem, .2rem);
                border: 1px;
                border-radius: 50%;
                margin-top: .2rem;
                background-color: #f8cb86;
            }
        }
        .tip_text{
            @include sc(.7rem, #333);
            line-height: .9rem;
            text-align: center;
            margin-top: .8rem;
            padding: 0 .4rem;
        }
        .confrim{
            @include sc(.8rem, #fff);
            font-weight: bold;
            margin-top: .8rem;
            background-color: #4cd964;
            width: 100%;
            text-align: center;
            line-height: 1.8rem;
            border: 1px;
            border-bottom-left-radius: 0.25rem;
            border-bottom-right-radius: 0.25rem;
        }
    }
    
</style>


================================================
FILE: src/components/common/buyCart.vue
================================================
 <template>
    <section class="cart_module">
        <section v-if="!foods.specifications.length" class="cart_button">
            <transition name="showReduce">
                <span @click="removeOutCart(foods.category_id, foods.item_id, foods.specfoods[0].food_id, foods.specfoods[0].name, foods.specfoods[0].price, '', foods.specfoods[0].packing_fee, foods.specfoods[0].sku_id, foods.specfoods[0].stock)" v-if="foodNum">
                    <svg>
                        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#cart-minus"></use>
                    </svg>
                </span>
            </transition>
            <transition name="fade">
                <span class="cart_num" v-if="foodNum">{{foodNum}}</span>
            </transition>
            <svg class="add_icon" @click="addToCart(foods.category_id, foods.item_id, foods.specfoods[0].food_id, foods.specfoods[0].name, foods.specfoods[0].price, '', foods.specfoods[0].packing_fee, foods.specfoods[0].sku_id, foods.specfoods[0].stock, $event)">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#cart-add"></use>
            </svg>
        </section>
        <section v-else class="choose_specification">
            <section class="choose_icon_container">
                <transition name="showReduce">
                    <svg class="specs_reduce_icon" v-if="foodNum" @click="showReduceTip">
                        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#cart-minus"></use>
                    </svg>
                </transition>
                <transition name="fade">
                    <span class="cart_num" v-if="foodNum">{{foodNum}}</span>
                </transition>
                <span class="show_chooselist" @click="showChooseList(foods)">选规格</span>
            </section>
        </section>
    </section>
</template>

<script>
    import {mapState, mapMutations} from 'vuex'
    export default {
    	data(){
            return{
               showMoveDot: [], //控制下落的小圆点显示隐藏
            }
        },
        mounted(){

        },
        computed: {
            ...mapState([
                'cartList'
            ]),
            /**
             * 监听cartList变化,更新当前商铺的购物车信息shopCart,同时返回一个新的对象
             */
            shopCart: function (){
                return Object.assign({},this.cartList[this.shopId]);
            },
            //shopCart变化的时候重新计算当前商品的数量
            foodNum: function (){
                let category_id = this.foods.category_id;
                let item_id = this.foods.item_id;
                if (this.shopCart&&this.shopCart[category_id]&&this.shopCart[category_id][item_id]) {
                    let num = 0;
                    Object.values(this.shopCart[category_id][item_id]).forEach((item,index) => {
                        num += item.num;
                    })
                    return num;
                }else {
                    return 0;
                }
            },
        },
        props:['foods', 'shopId'],
        methods: {
            ...mapMutations([
                'ADD_CART','REDUCE_CART',
            ]),
            //移出购物车
            removeOutCart(category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock){
                if (this.foodNum > 0) {
                    this.REDUCE_CART({shopid: this.shopId, category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock});
                }
            },
            //加入购物车,计算按钮位置。
            addToCart(category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock, event){
                this.ADD_CART({shopid: this.shopId, category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock});
                let elLeft = event.target.getBoundingClientRect().left;
                let elBottom = event.target.getBoundingClientRect().bottom;
                this.showMoveDot.push(true);
                this.$emit('showMoveDot', this.showMoveDot, elLeft, elBottom);

            },
            //显示规格列表
            showChooseList(foodScroll){
                this.$emit('showChooseList', foodScroll)
            },
            //点击多规格商品的减按钮,弹出提示
            showReduceTip(){
                this.$emit('showReduceTip')
            },

        },
    }
</script>

<style lang="scss" scoped>
    @import '../../style/mixin';
	.cart_module{
        .add_icon{
            position: relative;
            z-index: 9;
        }
        .cart_button{
            display: flex;
            align-items: center;
        }
        svg{
            @include wh(.9rem, .9rem);
            fill: #3190e8;
        }
        .specs_reduce_icon{
            fill: #999;
        }
        .cart_num{
            @include sc(.65rem, #666);
            min-width: 1rem;
            text-align: center;
            font-family: Helvetica Neue,Tahoma;
        }
        .choose_specification{
            .choose_icon_container{
                display: flex;
                align-items: center;
                .show_chooselist{
                    display: block;
                    @include sc(.55rem, #fff);
                    padding: .1rem .2rem;
                    background-color: $blue;
                    border-radius: 0.2rem;
                    border: 1px solid $blue;
                }
            }
        }
    }
    .showReduce-enter-active, .showReduce-leave-active {
        transition: all .3s ease-out;
    }
    .showReduce-enter, .showReduce-leave-active {
        opacity: 0;
        transform: translateX(1rem);
    }
    .fade-enter-active, .fade-leave-active {
        transition: all .3s;
    }
    .fade-enter, .fade-leave-active {
        opacity: 0;
    }
    .fadeBounce-enter-active, .fadeBounce-leave-active {
        transition: all .3s;
    }
    .fadeBounce-enter, .fadeBounce-leave-active {
        opacity: 0;
        transform: scale(.7);
    }

</style>



================================================
FILE: src/components/common/computeTime.vue
================================================
 <template>
    <div class="page">
        <span class="rem_time" style="color: orange;border-width: 1px;border-style: solid;border-color: orange;" @click="gotoPay">
	       {{remaining}}
        </span>
        <alert-tip v-if="showAlert" @closeTip="showAlert = false" :alertText="alertText"></alert-tip>  
    </div>
</template>

<script>
    import alertTip from 'src/components/common/alertTip'

    export default {
    	data(){
            return{
                countNum: 900,
                showAlert: false,
                alertText: null,
            }
        },
        mounted(){
            this.countNum -= this.numTime;
            this.remainingTime();
        },
        props: ['time'],
        components: {
            alertTip,
        },
        methods: {
            closeTip(){
                this.$emit('closeTip')
            },
            //计算时间
            remainingTime(){
                clearInterval(this.timer);
                this.timer = setInterval(() => {
                    this.countNum --;
                    if (this.countNum == 0) {
                        clearInterval(this.timer);
                        this.showAlert = true;
                        this.alertText = '支付超时';
                    }
                }, 1000);
            },
            gotoPay(){
                this.showAlert = true;
                this.alertText = '暂不开放支付接口';
            }
        },
        computed: {
            //转换时间成分秒
            remaining: function (){
                let minute = parseInt(this.countNum/60);
                let second = parseInt(this.countNum%60);
                if (minute < 10) {
                    minute = '0' + minute;
                }
                if (second < 10) {
                    second = '0' + second;
                }
                return '去支付(还剩' + minute + '分' + second + '秒)';
            },
            //订单返回时间秒分分别处理
            numTime: function (){
                if (this.time.toString().indexOf('分钟') !== -1) {
                    return parseInt(this.time)*60;
                }else{
                    return parseInt(this.time);
                }
            }
        },

    }
</script>

<style lang="scss" scoped>
    @import 'src/style/mixin';
	.page{
        display: inline-block;
        .rem_time{
            @include sc(.55rem, orange);
            padding: .1rem .2rem;
            border-radius: .15rem;
        }
    }
</style>


================================================
FILE: src/components/common/loading.vue
================================================
 <template>
	<div class="loading_container">
	    <div class="load_img" :style="{backgroundPositionY: -(positionY%7)*2.5 + 'rem'}">
	    </div>
    	<svg class="load_ellipse" xmlns="http://www.w3.org/2000/svg" version="1.1">
			<ellipse cx="26" cy="10" rx="26" ry="10" style="fill:#ddd;stroke:none;"></ellipse>
		</svg>
	</div>
</template>

<script>
    export default {
    	data(){
            return{
                positionY: 0,
                timer: null,
            }
        },
        mounted(){
        	this.timer = setInterval(() => {
        		this.positionY ++;
        	}, 600)
        },
        beforeDestroy(){
        	clearInterval(this.timer);
        }
    }
</script>

<style lang="scss" scoped>
    @import '../../style/mixin';
	@keyframes load{
		0%   {transform: translateY(0px);}
		50%  {transform: translateY(-50px);}
		100% {transform: translateY(0px);}
	}
	@keyframes ellipse{
		0%   {transform: scale(1);}
		50%  {transform: scale(0.3);}
		100% {transform: scale(1);}
	}
    .loading_container{
    	position: fixed;
    	top: 50%;
    	left: 50%;
    	transform: translate(-50%, -50%);
    	@include wh(2.5rem, 2.5rem);
    }
    .load_img{
    	@include wh(100%, 100%);
    	background: url(../../images/icon_loading.png) no-repeat 0 0;
    	background-size: 2.5rem auto;
    	transform: translateY(0px);
    	animation: load .6s infinite ease-in-out;
    	position: relative;
    	z-index: 11;
    }
	.load_ellipse{
		position: absolute;
		@include wh(2.6rem, 2rem);
		top: 2.2rem;
        left: 0.2rem;
		z-index: 10;
		animation: ellipse .6s infinite ease-in-out;
	}
</style>


================================================
FILE: src/components/common/mixin.js
================================================
import { getStyle } from '../../config/mUtils'
import { imgBaseUrl, localapi, proapi } from '../../config/env'

export const loadMore = {
	directives: {
		'load-more': {
			bind: (el, binding) => {
				let windowHeight = window.screen.height;
				let height;
				let setTop;
				let paddingBottom;
				let marginBottom;
				let requestFram;
				let oldScrollTop;
				let scrollEl;
				let heightEl;
				let scrollType = el.attributes.type && el.attributes.type.value;
				let scrollReduce = 2;
				if (scrollType == 2) {
					scrollEl = el;
					heightEl = el.children[0];
				} else {
					scrollEl = document.body;
					heightEl = el;
				}

				el.addEventListener('touchstart', () => {
					height = heightEl.clientHeight;
					if (scrollType == 2) {
						height = height
					}
					setTop = el.offsetTop;
					paddingBottom = getStyle(el, 'paddingBottom');
					marginBottom = getStyle(el, 'marginBottom');
				}, false)

				el.addEventListener('touchmove', () => {
					loadMore();
				}, false)

				el.addEventListener('touchend', () => {
					oldScrollTop = scrollEl.scrollTop;
					moveEnd();
				}, false)

				const moveEnd = () => {
					requestFram = requestAnimationFrame(() => {
						if (scrollEl.scrollTop != oldScrollTop) {
							oldScrollTop = scrollEl.scrollTop;
							moveEnd()
						} else {
							cancelAnimationFrame(requestFram);
							height = heightEl.clientHeight;
							loadMore();
						}
					})
				}

				const loadMore = () => {
					if (scrollEl.scrollTop + windowHeight >= height + setTop + paddingBottom + marginBottom - scrollReduce) {
						binding.value();
					}
				}
			}
		}
	}
};

export const getImgPath = {
	methods: {
		//传递过来的图片地址需要处理后才能正常使用
		getImgPath(path) {
			let suffix;
			if (!path) {
				return '//elm.cangdu.org/img/default.jpg'
			}
			if (path.indexOf('jpeg') !== -1) {
				suffix = '.jpeg'
			} else {
				suffix = '.png'
			}
			let url = '/' + path.substr(0, 1) + '/' + path.substr(1, 2) + '/' + path.substr(3) + suffix;
			return 'https://fuss10.elemecdn.com' + url
		},
	}

}

================================================
FILE: src/components/common/ratingStar.vue
================================================
 <template>
	<div class="rating_container">
        <section class="star_container">
            <svg class="grey_fill" v-for="num in 5" :key="num">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#star"></use>
            </svg>
        </section>
        <div :style="'width:' + rating*2/5 + 'rem'" class="star_overflow">
            <section class="star_container" >
                <svg  class="orange_fill" v-for="num in 5" :key="num">
                    <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#star"></use>
                </svg>
            </section>
        </div>
    </div>
</template>

<script>
    export default {
    	data(){
            return{
               
            }
        },
        mounted(){
        	
        },
        props:['rating'],
    }
</script>

<style lang="scss" scoped>
    @import '../../style/mixin';
	.rating_container{
        position: relative;
        top: .2rem;
        @include wh(2rem, .4rem);
        .star_overflow{
            overflow: hidden;
            position: relative;
            height: 100%;
        }
        .star_container{
            position: absolute;
            display: flex;
            width: 2rem;
            height: 0.4rem;
            top: -0.02rem;
            left: -0.02rem;
            .grey_fill{
                fill: #d1d1d1;
            }
            .orange_fill{
                fill: #ff9a0d;
            }
        }
    }
</style>


================================================
FILE: src/components/common/shoplist.vue
================================================
<template>
	<div class="shoplist_container">
		<ul v-load-more="loaderMore" v-if="shopListArr.length" type="1">
			<router-link :to="{path: 'shop', query:{geohash, id: item.id}}" v-for="item in shopListArr" tag='li' :key="item.id" class="shop_li">
				<section>
					<img :src="imgBaseUrl + item.image_path" class="shop_img">
				</section>
				<hgroup class="shop_right">
					<header class="shop_detail_header">
						<h4 :class="item.is_premium? 'premium': ''" class="" class="shop_title ellipsis">{{item.name}}</h4>
						<ul class="shop_detail_ul">
							<li v-for="item in item.supports" :key="item.id" class="supports">{{item.icon_name}}</li>
						</ul>
					</header>
					<h5 class="rating_order_num">
						<section class="rating_order_num_left">
							<section class="rating_section">
								<rating-star :rating='item.rating'></rating-star>
								<span class="rating_num">{{item.rating}}</span>
							</section>
							<section class="order_section">
								月售{{item.recent_order_num}}单
							</section>
						</section>
						<section class="rating_order_num_right">
							<span class="delivery_style delivery_left" v-if="item.delivery_mode">{{item.delivery_mode.text}}</span>
							<span class="delivery_style delivery_right" v-if="zhunshi(item.supports)">准时达</span>
						</section>
					</h5>
					<h5 class="fee_distance">
						<p class="fee">
							¥{{item.float_minimum_order_amount}}起送
							<span class="segmentation">/</span>
							{{item.piecewise_agent_fee.tips}}
						</p>
						<p class="distance_time">
							<span v-if="Number(item.distance)">{{item.distance > 1000? (item.distance/1000).toFixed(2) + 'km': item.distance + 'm'}}
								<span class="segmentation">/</span>
							</span>
							<span v-else>{{item.distance}}</span>
							<span class="segmentation">/</span>
							<span class="order_time">{{item.order_lead_time}}</span>
						</p>
					</h5>
				</hgroup>
			</router-link>
		</ul>
		<ul v-else class="animation_opactiy">
			<li class="list_back_li" v-for="item in 10" :key="item">
				<img src="../../images/shopback.svg" class="list_back_svg">
			</li>
		</ul>
		<p v-if="touchend" class="empty_data">没有更多了</p>
		<aside class="return_top" @click="backTop" v-if="showBackStatus">
			<svg class="back_top_svg">
				<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#backtop"></use>
			</svg>
		</aside>
		<div ref="abc" style="background-color: red;"></div>
		<transition name="loading">
			<loading v-show="showLoading"></loading>
		</transition>
	</div>
</template>

<script>

import {mapState} from 'vuex'
import {shopList} from 'src/service/getData'
import {imgBaseUrl} from 'src/config/env'
import {showBack, animate} from 'src/config/mUtils'
import {loadMore, getImgPath} from './mixin'
import loading from './loading'
import ratingStar from './ratingStar'

export default {
	data(){
		return {
			offset: 0, // 批次加载店铺列表,每次加载20个 limit = 20
			shopListArr:[], // 店铺列表数据
			preventRepeatReuqest: false, //到达底部加载数据,防止重复加载
			showBackStatus: false, //显示返回顶部按钮
			showLoading: true, //显示加载动画
			touchend: false, //没有更多数据
			imgBaseUrl,
		}
	},
	mounted(){
		this.initData();
	},
	components: {
		loading,
		ratingStar,
	},
	props: ['restaurantCategoryId', 'restaurantCategoryIds', 'sortByType', 'deliveryMode', 'supportIds', 'confirmSelect', 'geohash'],
	mixins: [loadMore, getImgPath],
	computed: {
		...mapState([
			'latitude','longitude'
		]),
	},
	updated(){
		// console.log(this.supportIds, this.sortByType)
	},
	methods: {
		async initData(){
			//获取数据
			let res = await shopList(this.latitude, this.longitude, this.offset, this.restaurantCategoryId);
			this.shopListArr = [...res];
			if (res.length < 20) {
				this.touchend = true;
			}
			this.hideLoading();
			//开始监听scrollTop的值,达到一定程度后显示返回顶部按钮
			showBack(status => {
				this.showBackStatus = status;
			});
		},
		//到达底部加载更多数据
		async loaderMore(){
			if (this.touchend) {
				return
			}
			//防止重复请求
			if (this.preventRepeatReuqest) {
				return
			}
			this.showLoading = true;
			this.preventRepeatReuqest = true;

			//数据的定位加20位
			this.offset += 20;
			let res = await shopList(this.latitude, this.longitude, this.offset, this.restaurantCategoryId);
			this.hideLoading();
			this.shopListArr = [...this.shopListArr, ...res];
			//当获取数据小于20,说明没有更多数据,不需要再次请求数据
			if (res.length < 20) {
				this.touchend = true;
				return
			}
			this.preventRepeatReuqest = false;
		},
		//返回顶部
		backTop(){
			animate(document.body, {scrollTop: '0'}, 400,'ease-out');
		},
		//监听父级传来的数据发生变化时,触发此函数重新根据属性值获取数据
		async listenPropChange(){
			this.showLoading = true;
			this.offset = 0;
			let res = await shopList(this.latitude, this.longitude, this.offset, '', this.restaurantCategoryIds, this.sortByType, this.deliveryMode, this.supportIds);
			this.hideLoading();
			//考虑到本地模拟数据是引用类型,所以返回一个新的数组
			this.shopListArr = [...res];
		},
		//开发环境与编译环境loading隐藏方式不同
		hideLoading(){
			this.showLoading = false;
		},
		zhunshi(supports){
			let zhunStatus;
			if ((supports instanceof Array) && supports.length) {
 				supports.forEach(item => {
 					if (item.icon_name === '准') {
 						zhunStatus = true;
 					}
 				})
			}else{
				zhunStatus = false;
			}
			return zhunStatus
		},
	},
	watch: {
		//监听父级传来的restaurantCategoryIds,当值发生变化的时候重新获取餐馆数据,作用于排序和筛选
		restaurantCategoryIds: function (value){
			this.listenPropChange();
		},
		//监听父级传来的排序方式
		sortByType: function (value){
			this.listenPropChange();
		},
		//监听父级的确认按钮是否被点击,并且返回一个自定义事件通知父级,已经接收到数据,此时父级才可以清除已选状态
		confirmSelect: function (value){
			this.listenPropChange();
		}
	}
}
</script>

<style lang="scss" scoped>
	@import 'src/style/mixin';
	.shoplist_container{
		background-color: #fff;
		margin-bottom: 2rem;
	}
	.shop_li{
		display: flex;
		border-bottom: 0.025rem solid #f1f1f1;
		padding: 0.7rem 0.4rem;
	}
	.shop_img{
		@include wh(2.7rem, 2.7rem);
		display: block;
		margin-right: 0.4rem;
	}
	.list_back_li{
		height: 4.85rem;
		.list_back_svg{
			@include wh(100%, 100%)
		}
	}
	.shop_right{
		flex: auto;
		.shop_detail_header{
			@include fj;
			align-items: center;
			.shop_title{
				width: 8.5rem;
				color: #333;
				padding-top: .01rem;
				@include font(0.65rem, 0.65rem, 'PingFangSC-Regular');
				font-weight: 700;
			}
			.premium::before{
				content: '品牌';
				display: inline-block;
				font-size: 0.5rem;
				line-height: .6rem;
				color: #333;
				background-color: #ffd930;
				padding: 0 0.1rem;
				border-radius: 0.1rem;
				margin-right: 0.2rem;
			}
			.shop_detail_ul{
				display: flex;
				transform: scale(.8);
				margin-right: -0.3rem;
				.supports{
					@include sc(0.5rem, #999);
					border: 0.025rem solid #f1f1f1;
					padding: 0 0.04rem;
					border-radius: 0.08rem;
					margin-left: 0.05rem;
				}
			}
		}
		.rating_order_num{
			@include fj(space-between);
			height: 0.6rem;
			margin-top: 0.52rem;
			.rating_order_num_left{
				@include fj(flex-start);
				.rating_section{
					display: flex;
					.rating_num{
						@include sc(0.4rem, #ff6000);
						margin: 0 0.2rem;
					}
				}
				.order_section{
					transform: scale(.8);
					margin-left: -0.2rem;
					@include sc(0.4rem, #666);
				}
			}
			.rating_order_num_right{
				display: flex;
				align-items: center;
				transform: scale(.7);
				min-width: 5rem;
				justify-content: flex-end;
				margin-right: -0.8rem;
				.delivery_style{
					font-size: 0.4rem;
					padding: 0.04rem 0.08rem 0;
					border-radius: 0.08rem;
					margin-left: 0.08rem;
					border: 1px;
				}
				.delivery_left{
					color: #fff;
					background-color: $blue;
					border: 0.025rem solid $blue;
				}
				.delivery_right{
					color: $blue;
					border: 0.025rem solid $blue;
				}
			}
		}
		.fee_distance{
			margin-top: 0.52rem;
			@include fj;
			@include sc(0.5rem, #333);
			.fee{
				transform: scale(.9);
				@include sc(0.5rem, #666);
			}
			.distance_time{
				transform: scale(.9);
				span{
					color: #999;
				}
				.order_time{
					color: $blue;
				}
				.segmentation{
					color: #ccc;
				}
			}
		}
	}
	.loader_more{
		@include font(0.6rem, 3);
		text-align: center;
	    color: #999;
	}
	.empty_data{
		@include sc(0.5rem, #666);
		text-align: center;
		line-height: 2rem;
	}
	.return_top{
		position: fixed;
		bottom: 3rem;
		right: 1rem;
		.back_top_svg{
			@include wh(2rem, 2rem);
		}
	}
	.loading-enter-active, .loading-leave-active {
		transition: opacity 1s
	}
	.loading-enter, .loading-leave-active {
		opacity: 0
	}
</style>


================================================
FILE: src/components/common/svg.vue
================================================
<template>
	<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0;visibility:hidden">
		<defs>
			<symbol viewBox="0 0 60 60" id="eleme">
			<path fill="#3CABFF" fill-rule="evenodd" d="M0 9.375A9.374 9.374 0 0 1 9.375 0h41.25A9.374 9.374 0 0 1 60 9.375v41.25A9.374 9.374 0 0 1 50.625 60H9.375A9.374 9.374 0 0 1 0 50.625V9.375zm35.94 30.204c-5.601 3.147-12.645 1.256-15.834-4.217-3.206-5.501-1.303-12.537 4.25-15.713 4.7-2.689 10.51-1.749 14.127 1.941L27.526 27.89a2.81 2.81 0 0 0-1.037 3.854 2.862 2.862 0 0 0 3.887 1.035l15.988-9.166a17.238 17.238 0 0 0-1.222-2.571c-4.777-8.198-15.358-11.007-23.632-6.275-8.275 4.734-11.11 15.217-6.332 23.415 4.77 8.184 15.322 10.997 23.59 6.297.877-.5 1.654-1.037 2.376-1.623l-1.31-2.248a2.868 2.868 0 0 0-3.893-1.028zm10.824-7.39l-1.418-2.425-4.911 2.798 2.835 4.846 2.454-1.399h.002a2.779 2.779 0 0 0 1.038-3.82z">
			</path>
			</symbol>
			<symbol viewBox="0 0 28 33" id="user">
			<path fill-rule="evenodd" d="M20.798 19.289c2.636-2.002 4.215-5.091 4.215-8.437 0-5.886-4.845-10.647-10.808-10.647S3.397 4.966 3.397 10.852c0 3.345 1.578 6.433 4.212 8.435l.264-2.678C4.358 18.32 1.591 21.403.168 25.187l1.478.556v-1.579c-1.485.73-1.485.73-1.501 1.079-.054.188-.054.188-.069.278a2.58 2.58 0 0 0-.026.229 9.112 9.112 0 0 0-.019.4c-.008.265-.014.617-.018 1.039-.005.511-.006 1.037-.006 1.451v.027c-.004 1.732 1.41 3.129 3.154 3.129h22.082a3.18 3.18 0 0 0 3.172-3.153l.011-1.305.008-.897.003-.296.001-.083v-.022-.006-.001l.002-.278-.093-.262c-1.385-3.918-4.203-7.122-7.812-8.88l.263 2.678zm-1.911-2.516l-2.045 1.553 2.309 1.125c2.856 1.392 5.106 3.949 6.218 7.093l-.09-.54V26.033l-.001.083-.003.296-.008.897-.011 1.305c0 .01-.011.021-.013.021H3.161c-.007 0 .005.011.005.032v-.031c0-.404.001-.92.006-1.418.004-.4.01-.732.017-.969.004-.121.008-.212.012-.262l-.006.043c-.009.06-.009.06-.058.229-.01.336-.01.336-1.49 1.063H2.74l.385-1.024c1.141-3.035 3.35-5.495 6.131-6.849l2.309-1.124-2.045-1.554c-1.859-1.412-2.964-3.576-2.964-5.92 0-4.129 3.418-7.488 7.649-7.488s7.649 3.359 7.649 7.488c0 2.344-1.106 4.509-2.966 5.921z" class="path1">
			</path>
			</symbol>
			<symbol viewBox="0 0 32 31" id="shop">
			<g fill-rule="evenodd">
			  <path d="M28.232 1.822C27.905.728 26.97.152 25.759.152H5.588c-1.252 0-1.867.411-2.397 1.415l-.101.243-.443 1.434-.975 3.154-.002.007C.837 9.101.294 10.854.26 10.956l-.059.259c-.231 1.787.337 3.349 1.59 4.448 1.159 1.017 2.545 1.384 3.865 1.384.07 0 .07 0 .132-.002-.01.001-.01.001.061.002 1.32 0 2.706-.367 3.865-1.384a4.96 4.96 0 0 0 .413-.407l-1.043-.946-1.056.931c1.033 1.171 2.51 1.792 4.21 1.801.04.002.088.004.173.004 1.32 0 2.706-.367 3.865-1.384.148-.13.287-.267.418-.411l-1.044-.944-1.057.93c1.033 1.174 2.511 1.796 4.213 1.806.04.002.088.004.173.004 1.32 0 2.706-.367 3.865-1.384.15-.131.29-.27.422-.416l-1.046-.943-1.058.929c1.033 1.177 2.513 1.801 4.218 1.811.04.002.088.004.173.004 1.32 0 2.706-.367 3.865-1.384 1.206-1.058 1.858-2.812 1.676-4.426-.069-.61-.535-2.207-1.354-4.785l-.109-.342a327.554 327.554 0 0 0-1.295-3.966l-.122-.366.014.043h.004zm-2.684.85l.12.361.318.962c.329.999.658 2.011.965 2.973l.108.338c.719 2.262 1.203 3.92 1.24 4.249.08.711-.233 1.553-.735 1.993-.553.485-1.308.685-2.008.685l-.098-.002c-.987-.007-1.695-.306-2.177-.854l-1.044-1.189-1.06 1.175a2.192 2.192 0 0 1-.188.185c-.553.485-1.308.685-2.008.685l-.098-.002c-.985-.007-1.693-.305-2.174-.852l-1.043-1.185-1.059 1.171c-.058.064-.12.125-.186.183-.553.485-1.308.685-2.008.685l-.098-.002c-.984-.007-1.692-.304-2.173-.85L9.101 12.2l-1.058 1.166a2.248 2.248 0 0 1-.184.181c-.553.485-1.307.685-2.008.685l-.061-.001-.131.001c-.701 0-1.455-.2-2.008-.685-.538-.472-.767-1.102-.654-1.971l-1.396-.18 1.338.44c.043-.13.552-1.775 1.425-4.599l.002-.007.975-3.155.443-1.434-1.345-.415 1.245.658c.054-.102.042-.085-.083-.001-.122.082-.143.086-.009.086H25.763c.053 0-.164-.133-.225-.339l.014.043-.004-.001zM5.528 19.48c.778 0 1.408.63 1.408 1.408v7.424a1.408 1.408 0 1 1-2.816 0v-7.424c0-.778.63-1.408 1.408-1.408z">
			  </path>
			  <path d="M.28 29.72c0-.707.58-1.28 1.277-1.28h28.155a1.28 1.28 0 0 1 .007 2.56H1.561A1.278 1.278 0 0 1 .28 29.72z">
			  </path>
			  <path d="M26.008 19.48c.778 0 1.408.63 1.408 1.408v7.424a1.408 1.408 0 1 1-2.816 0v-7.424c0-.778.63-1.408 1.408-1.408z">
			  </path>
			</g>
			</symbol>
			<symbol viewBox="0 0 28 33" id="location">
			<g fill-rule="evenodd">
			  <path d="M20.809 21.6L12.9 29.509h1.616l-7.992-7.992a13.003 13.003 0 0 1-.506-.478c-4.25-4.25-4.25-11.14 0-15.389s11.14-4.25 15.389 0c4.25 4.25 4.25 11.14 0 15.389a10.81 10.81 0 0 1-.543.508l-.056.052zm1.56 1.669c.225-.196.443-.401.656-.613 5.142-5.142 5.142-13.48 0-18.622s-13.48-5.142-18.622 0c-5.142 5.142-5.142 13.48 0 18.622.18.18.364.354.553.522l8.753 8.755 8.661-8.664z" class="path1">
			  </path>
			  <path d="M9.428 16.739a6.063 6.063 0 1 0 8.573-8.575 6.063 6.063 0 0 0-8.573 8.575zm1.616-1.616a3.776 3.776 0 1 1 5.34-5.341 3.776 3.776 0 0 1-5.34 5.341z" class="path2">
			  </path>
			</g>
			</symbol>
			<symbol id="star" viewBox="0 0 32 32">
			<path class="path1" d="M16 26.382l-8.16 4.992c-1.5 0.918-2.382 0.264-1.975-1.435l2.226-9.303-7.269-6.218c-1.337-1.143-0.987-2.184 0.755-2.322l9.536-0.758 3.667-8.835c0.674-1.624 1.772-1.613 2.442 0l3.667 8.835 9.536 0.758c1.753 0.139 2.082 1.187 0.755 2.322l-7.269 6.218 2.226 9.303c0.409 1.71-0.485 2.347-1.975 1.435l-8.16-4.992z">
			</path>
			</symbol>
			<symbol viewBox="0 0 32 32" id="backtop">
			<g fill-rule="evenodd">
			  <circle cx="16" cy="16" r="15" stroke="#999" stroke-width="0.6" fill="none"/>
			  <line x1="16" y1="10" x2="16" y2="21" style="stroke:#999;stroke-width:0.8"/>
			  <line x1="10" y1="10" x2="22" y2="10" style="stroke:#999;stroke-width:0.8"/>
			  <path d="M9.5 18 L16 10 L22.5 18" style="stroke:#999;stroke-width:0.8;fill:none"/>
			  <text x="10" y="27"  style="font-size:6px;fill:#999;font-weight:700;">顶部</text>
			</g>
			</symbol>
			<symbol viewBox="0 0 33 32" id="default">
			<path fill="#3b87c8" d="M13.374 29.064a.94.94 0 0 1-.941-.941V6.476l-7.285 6.899a.942.942 0 0 1-1.299-1.364l8.876-8.424a.94.94 0 0 1 1.59.681v23.855a.94.94 0 0 1-.941.941zM20.904 29.355h-.008a.94.94 0 0 1-.375-.078.943.943 0 0 1-.559-.86V3.944a.94.94 0 1 1 1.882 0v22.287l7.238-6.842a.94.94 0 0 1 1.289 1.366l-8.818 8.338a.943.943 0 0 1-.649.264z">
			</path>
			</symbol>
			<symbol viewBox="0 0 32 32" id="distance">
			<path fill="#2a9bd3" d="M15.884 31.236l-.042.001a.888.888 0 0 1-.59-.224l-7.91-7.91a7.548 7.548 0 0 1-.498-.471 12.752 12.752 0 0 1-3.747-9.045C3.097 6.523 8.824.796 15.888.796s12.791 5.727 12.791 12.791c0 3.532-1.432 6.73-3.747 9.045-.196.196-.409.391-.613.578l-7.813 7.804a.886.886 0 0 1-.589.223l-.035-.001zm0-28.667C9.818 2.59 4.908 7.513 4.908 13.582c0 3.023 1.218 5.762 3.19 7.752l.461.435 7.316 7.316 7.2-7.2q.284-.249.551-.516a10.977 10.977 0 0 0 3.225-7.787c0-6.066-4.905-10.987-10.965-11.013z">
			</path>
			<path fill="#2a9bd3" d="M15.884 18.524a5.707 5.707 0 0 1-4.07-1.732l-.001-.001a5.76 5.76 0 1 1 4.119 1.734h-.05zm-2.817-2.942a3.982 3.982 0 1 0 0-5.626c-.726.717-1.175 1.713-1.175 2.813s.449 2.096 1.175 2.813z"></path>
			</symbol>
			<symbol viewBox="0 0 32 32" id="fengniao">
			<path fill="#27a9e1" d="M5.953 2.793s-.117 1.801.857 3.56c.361.255 10.458 6.218 10.458 6.218L5.953 2.794z"></path>
			<path fill="#b8e5fa" d="M9.604.889s-.333 1.404.069 3.147c.254.307 7.801 8.116 7.801 8.116L9.604.889z"></path>
			<path fill="#0089cf" d="M29.282 14.601l-4.861-.361s-.133-.001-.147-.226h-.002a2.652 2.652 0 0 0-2.978-2.357h-.003l-.011.001-.12.019-.004.001c-.432.075-1.812.374-3.038 1.285 0 0-.167.121-.421.33L2.665 6.043s3.254 8.665 12.207 11.98c-1.6 2.849-7.407 13.48-7.407 13.48l2.446-1.306s.775-2.853 1.884-4.957c.609-.936 1.211-.992 1.498-1.141.291-.151 3.707-.765 6.431-4.339.897-1.166 1.244-2.666 1.723-4.261.28-.061 3.008-.651 3.789-.718 1.068-.092 4.045-.181 4.045-.181z"></path>
			<path fill="#0089cf" d="M7.392 17.849c-1.567-1.368-2.199-3.219-2.035-5.217-.232-.288-.45-.572-.654-.851-.484 2.903.555 4.854 2.176 6.269 1.538 1.342 3.635 1.85 5.466 1.577-1.674.109-3.563-.565-4.953-1.778z"></path>
			<path fill="#0089cf" d="M12.345 19.628h.002zm-7.642-7.846c.204.279.421.563.654.851-.164 1.998.468 3.849 2.035 5.217 1.292 1.128 3.016 1.79 4.597 1.79.12 0 .238-.004.356-.011a6.554 6.554 0 0 1-.975.071c-1.568 0-3.22-.54-4.49-1.648-1.621-1.415-2.66-3.366-2.176-6.269z"></path>
			</symbol>
			<symbol viewBox="0 0 23 32" id="hot">
			<path fill="#f07373" d="M9.859 29.375c-3.489-.771-6.362-3.097-7.187-5.551-.882-2.623-1.029-6.873-.238-9.318l-1.727.037.001.002.001.004.004.01.011.029.038.091c.039.09.086.191.142.3.155.304.349.627.586.955a7.477 7.477 0 0 0 2.711 2.318c.583.153.583.153 1.087-.188.187-.263.187-.263.224-.39.028-.094.041-.176.05-.28.01-.109.016-.238.022-.47.063-2.219.162-3.38.562-4.943a10.05 10.05 0 0 1 .814-2.185c1.433-2.723 4.843-6.053 6.699-7.021l-1.325-.962c-.064.382-.127.992-.131 1.722-.008 1.252.169 2.393.616 3.329.261.547.525.968 1.132 1.862l.23.339c.86 1.281 1.161 1.986 1.069 2.653l-.009.125c.069.517.069.517.781.906.451-.026.451-.026.578-.104.144-.093.144-.093.19-.136.041-.037.079-.077.123-.125.068-.076.153-.178.245-.295.22-.279.458-.615.677-.963.648-1.028 1.045-1.988 1.037-2.845l-.914.009-.706.581c.295.358.809 1.075 1.33 1.936.826 1.363 1.492 2.791 1.898 4.209 1.1 3.845.3 9.288-2.245 11.75a9.652 9.652 0 0 1-1.659 1.29 10.232 10.232 0 0 1-3.471 1.332c-.794.151-1.385.191-2.064.191h-.009a2.75 2.75 0 0 1-.373-.03 6.007 6.007 0 0 1-.585-.115 7.765 7.765 0 0 1-.536-.15l-.578 1.735a9.182 9.182 0 0 0 1.445.341c.221.031.43.048.627.048h.009a12.546 12.546 0 0 0 2.407-.224 12.011 12.011 0 0 0 4.088-1.572c.699-.431 1.358-.94 1.971-1.533 3.098-2.998 4-9.132 2.731-13.567-.455-1.591-1.188-3.161-2.092-4.653-.569-.939-1.134-1.727-1.482-2.15l-1.645-1.998.024 2.588c.004.412-.281 1.1-.756 1.853a9.64 9.64 0 0 1-.569.809 4.528 4.528 0 0 1-.158.195c.028-.027.028-.027.16-.113.122-.075.122-.075.57-.101.71.388.71.388.778.902h-.914l.906.125c.174-1.262-.261-2.281-1.362-3.922l-.235-.347c-.554-.817-.787-1.189-.995-1.624-.306-.642-.444-1.53-.438-2.53a10.566 10.566 0 0 1 .107-1.431L14.44.304l-1.628.85c-2.18 1.138-5.862 4.733-7.471 7.791a11.873 11.873 0 0 0-.967 2.583 19.2 19.2 0 0 0-.511 3.147c-.036.423-.061.839-.079 1.273-.011.281-.019.531-.029.924-.005.191-.01.298-.015.354a.403.403 0 0 1 .019-.077c.027-.099.027-.099.203-.346.492-.332.492-.332 1.112-.157a5.745 5.745 0 0 1-2.54-2.496 3.456 3.456 0 0 1-.093-.197l-.018-.044-.002-.006v.001l.001.002v.002l-.915-2.473-.812 2.51c-.917 2.836-.757 7.485.245 10.463 1.042 3.099 4.442 5.852 8.526 6.754l.395-1.785z"></path>
			</symbol>
			<symbol viewBox="0 0 32 32" id="price">
			<path fill="#e6b61a" d="M16 32c8.837 0 16-7.163 16-16S24.837 0 16 0 0 7.163 0 16s7.163 16 16 16zm0-2C8.268 30 2 23.732 2 16S8.268 2 16 2s14 6.268 14 14-6.268 14-14 14z"></path><path fill="#e6b61a" d="M23.14 6.06l-5.12 8.65h4.48v1.54h-5.49v2.43h5.49v1.54h-5.49v5.1h-2.02v-5.1H9.53v-1.54h5.46v-2.43H9.53v-1.54h4.45L8.8 6.06h2.24l4.99 8.48 4.93-8.48h2.18z"></path>
			</symbol>
			<symbol viewBox="0 0 33 32" id="rating">
			<path fill="#eba53b" d="M27.087 31.84L16.8 25.553 6.504 31.84l2.824-11.727-9.186-7.878 12.019-.941L16.801.16l4.631 11.134 12.019.941-9.158 7.849zM16.8 23.369l7.407 4.527-2.014-8.471 6.588-5.647-8.659-.696L16.8 5.063l-3.341 8.019-8.659.696 6.588 5.647-2.014 8.471z"></path>
			</symbol>
			<symbol viewBox="0 0 38 32" id="selected">
			<path fill="#3190e8" d="M32.291 2.327c.582-.582 1.455-.582 2.036 0l2.036 2.036c.582.582.582 1.455 0 2.036L13.818 29.09c-.582.582-1.455.582-2.036 0L1.455 18.908c-.582-.582-.582-1.455 0-2.036l2.036-2.036c.582-.582 1.455-.582 2.036 0l7.273 7.273L32.291 2.327z"></path>
			</symbol>
			<symbol viewBox="0 0 32 32" id="speed">
			<path fill="#37c7b7" d="M16 32c8.837 0 16-7.163 16-16S24.837 0 16 0 0 7.163 0 16s7.163 16 16 16zm0-2C8.268 30 2 23.732 2 16S8.268 2 16 2s14 6.268 14 14-6.268 14-14 14z"></path><path fill="#37c7b7" d="M15 7v11.002l5.678 4.882 1.304-1.517-5.33-4.583.348.758V6.999h-2z"></path>
			</symbol>
			<symbol viewBox="0 0 50 50" id="cart-minus">
			<path fill-rule="evenodd" stroke-width="4" d="M22 0C9.8 0 0 9.8 0 22s9.8 22 22 22 22-9.8 22-22S34.2 0 22 0zm0 42C11 42 2 33 2 22S11 2 22 2s20 9 20 20-9 20-20 20z" clip-rule="evenodd"></path>
			<path fill-rule="evenodd" d="M32 20c1.1 0 2 .9 2 2s-.9 2-2 2H12c-1.1 0-2-.9-2-2s.9-2 2-2h20z" clip-rule="evenodd"></path>
			</symbol>
			<symbol viewBox="0 0 50 50" id="cart-add">
			<path fill="none" d="M0 0h44v44H0z"></path>
			<path fill-rule="evenodd" d="M22 0C9.8 0 0 9.8 0 22s9.8 22 22 22 22-9.8 22-22S34.2 0 22 0zm10 24h-8v8c0 1.1-.9 2-2 2s-2-.9-2-2v-8h-8c-1.1 0-2-.9-2-2s.9-2 2-2h8v-8c0-1.1.9-2 2-2s2 .9 2 2v8h8c1.1 0 2 .9 2 2s-.9 2-2 2z" clip-rule="evenodd"></path>
			</symbol>
			<symbol viewBox="0 0 24 32" id="cart-remove">
			<path fill="#bbb" fill-rule="evenodd" d="M21.5 10h-19c-1.1 0-1.918.896-1.819 1.992l1.638 18.016C2.419 31.104 3.4 32 4.5 32h15c1.1 0 2.081-.896 2.182-1.992l1.637-18.016A1.798 1.798 0 0 0 21.5 10zM8 28H5L4 14h4v14zm6 0h-4V14h4v14zm5 0h-3V14h4l-1 14zm2-24h-2.941l-.353-2.514C17.592.669 16.823 0 15.998 0H8c-.825 0-1.593.668-1.708 1.486L5.94 4H3a3 3 0 0 0-3 3v1h24V7a3 3 0 0 0-3-3zM8.24 2h7.52l.279 2H7.96l.28-2z"></path>
			</symbol>
			<symbol viewBox="0 0 14 16" id="cart">
			<path fill="#FFF" fill-rule="evenodd" d="M12.364 2.998H2.088L1.816.687a.455.455 0 0 0-.478-.431L.431.303A.454.454 0 0 0 0 .78l1.256 10.893c.006.293.011 1.325.933 1.325h9.546a.455.455 0 0 0 .455-.454v-.881a.454.454 0 0 0-.455-.455H3.05l-.11-.937h8.606c.998 0 1.889-.724 1.989-1.616l.455-4.04c.1-.893-.628-1.617-1.626-1.617zm-.45 4.245c-.075.669-.317 1.212-1.066 1.212H2.727L2.3 4.812h8.821c.749 0 1.065.543.99 1.212l-.197 1.219zM2.416 15.79a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm9.092 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path>
			</symbol>
			<symbol viewBox="0 0 58 58" id="cart-icon">
			<defs>
			  <filter id="a" width="200%" height="200%" x="-50%" y="-50%" filterUnits="objectBoundingBox"><feOffset in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0" in="shadowBlurOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter><path id="b" d="M7.614 4.051c-1.066.086-1.452-.398-1.752-1.584C5.562 1.28.33 5.88.33 5.88l3.71 19.476c0 .148-1.56 7.515-1.56 7.515-.489 2.19.292 4.27 3.56 4.32 0 0 36.917.017 36.92.047 1.979-.012 2.981-.995 3.013-3.039.03-2.043-1.045-2.978-2.987-2.993L8.83 31.192s.86-3.865 1.077-3.865c0 0-5.788.122 32.065-1.956.606-.033 2.018-.764 2.298-1.848 1.113-4.317 4.008-13.26 4.458-15.64.932-4.925 2.061-8.558-4.28-7.405 0 0-35.768 3.487-36.833 3.573z"/>
			</defs>
			<g fill="none" fill-rule="evenodd" filter="url(#a)" transform="translate(3 2)">
			  <g transform="translate(5.038 7.808)"><mask id="c" fill="#fff"><use xlink:href="#b"/></mask><use fill="#FFF" xlink:href="#b"/><path fill="#2073C1" d="M53.962 7.774l-5.701 19.305-40.78 1.574z" opacity=".1" mask="url(#c)"/></g><path stroke="#FFF" stroke-width="6" d="M9.374 18.722S7.868 11.283 7.323 8.71C6.778 6.136 5.86 5.33 3.978 4.52 2.096 3.713.367 2.286.367 2.286" stroke-linecap="round"/><circle cx="46" cy="51" r="4" fill="#FFF"/><circle cx="12" cy="51" r="4" fill="#FFF"/>
			</g>
			</symbol>
			<symbol viewBox="0 0 14 14" id="arrow-left">
			<path d="M0 0 L8 7 L0 14"  stroke="#fff" stroke-width="1" fill="none"/>
			</symbol>
			<symbol viewBox="0 0 1024 1024" id="res-well"><path fill="#7ED321" fill-rule="evenodd" d="M512 0C229.376 0 0 229.376 0 512s229.376 512 512 512 512-229.376 512-512S794.624 0 512 0zM247.808 402.432c0-36.864 39.936-93.184 93.184-93.184s93.184 56.32 93.184 93.184c0 11.264-9.216 20.48-20.48 20.48-11.264 0-20.48-9.216-20.48-20.48 0-16.384-24.576-52.224-52.224-52.224-27.648 0-52.224 35.84-52.224 52.224 0 11.264-9.216 20.48-20.48 20.48-11.264 0-20.48-9.216-20.48-20.48zM512 800.768c-132.096 0-239.616-96.256-239.616-215.04 0-11.264 9.216-20.48 20.48-20.48 11.264 0 20.48 9.216 20.48 20.48 0 96.256 89.088 174.08 198.656 174.08 109.568 0 198.656-77.824 198.656-174.08 0-11.264 9.216-20.48 20.48-20.48 11.264 0 20.48 9.216 20.48 20.48 0 117.76-107.52 215.04-239.616 215.04zm243.712-377.856c-11.264 0-20.48-9.216-20.48-20.48 0-17.408-24.576-52.224-52.224-52.224-28.672 0-52.224 34.816-52.224 52.224 0 11.264-9.216 20.48-20.48 20.48-11.264 0-20.48-9.216-20.48-20.48 0-36.864 39.936-93.184 93.184-93.184s93.184 56.32 93.184 93.184c0 11.264-9.216 20.48-20.48 20.48z"></path></symbol>
			<symbol viewBox="0 0 1024 1024" id="res-bad"><path fill="#D0021B" fill-rule="evenodd" d="M512 0C230.326 0 0 230.326 0 512s230.573 512 512 512 512-230.326 512-512S793.674 0 512 0zM240.694 373.755l158.735-56.285 15.306 46.164L256 419.919l-15.306-46.164zm440.409 384.123c-10.122 0-20.49-10.122-25.674-20.49-10.122-10.122-61.47-25.674-148.366-25.674-86.896 0-138.245 15.306-148.366 25.674 0 10.122-10.122 20.49-25.674 20.49s-25.674-10.122-25.674-25.674c0-71.591 174.041-71.591 194.53-71.591 20.489 0 194.53 0 194.53 71.591 10.122 10.368 0 25.674-15.306 25.674zM768 419.919l-163.672-61.47 15.306-46.164 158.735 56.285-10.368 51.348-.001.001z"></path></symbol>
			<symbol viewBox="0 0 122 122" id="avatar-default"><path fill="#DCDCDC" fill-rule="evenodd" d="M61 121.5c33.413 0 60.5-27.087 60.5-60.5S94.413.5 61 .5.5 27.587.5 61s27.087 60.5 60.5 60.5zm12.526-45.806c-.019 3.316-.108 6.052.237 9.825 3.286 8.749 18.816 9.407 28.468 17.891-1.833 1.998-6.768 6.788-15 10.848-7.02 3.463-16.838 6.416-24.831 6.416-17.366 0-32.764-7.149-42.919-17.264 9.713-8.407 25.49-9.173 28.769-17.891.345-3.773.258-6.509.24-9.825l-.004-.002c-1.903-.985-5.438-7.268-6.01-12.571-1.492-.12-3.843-1.561-4.534-7.247-.37-3.053 1.107-4.77 2.004-5.31-5.046-19.212 1.507-33.16 20.749-34.406 5.753 0 10.18 1.52 11.909 4.523 15.35 2.702 11.756 22.658 9.328 29.882.899.54 2.376 2.258 2.004 5.31-.689 5.687-3.042 7.127-4.534 7.248-.575 5.305-3.25 10.82-5.873 12.57l-.003.003zM61 120.5C28.14 120.5 1.5 93.86 1.5 61S28.14 1.5 61 1.5s59.5 26.64 59.5 59.5-26.64 59.5-59.5 59.5z"></path></symbol>
			<symbol viewBox="0 0 655 1024" id="mobile"><path d="M0 122.501v778.998C0 968.946 55.189 1024 123.268 1024h408.824c68.52 0 123.268-54.846 123.268-122.501V122.501C655.36 55.054 600.171 0 532.092 0H123.268C54.748 0 0 54.846 0 122.501zM327.68 942.08c-22.622 0-40.96-18.338-40.96-40.96s18.338-40.96 40.96-40.96 40.96 18.338 40.96 40.96-18.338 40.96-40.96 40.96zM81.92 163.84h491.52V819.2H81.92V163.84z"></path></symbol>
			<symbol viewBox="0 0 1024 1024" id="arrow-right" class="icon"><path d="M716.298 417.341l-.01.01L307.702 7.23l-94.295 94.649 408.591 410.117-408.591 410.137 94.295 94.639 502.891-504.76z" class="selected"></path></symbol>
			<symbol viewBox="0 0 40 40" id="order"><path d="M31.5 3h-23C6 3 4 5.1 4 7.7v24.7C4 34.9 6 37 8.5 37h23c2.5 0 4.5-2.1 4.5-4.7V7.7C36 5.1 34 3 31.5 3zM11.8 28.2c-1.1 0-2-.9-2-2.1 0-1.1.9-2.1 2-2.1s2 .9 2 2.1c0 1.2-.9 2.1-2 2.1zm0-6.1c-1.1 0-2-.9-2-2.1 0-1.1.9-2.1 2-2.1s2 .9 2 2.1c0 1.1-.9 2.1-2 2.1zm0-6.2c-1.1 0-2-.9-2-2.1 0-1.1.9-2.1 2-2.1s2 .9 2 2.1c0 1.2-.9 2.1-2 2.1zm5.1 11.9h13.5v-2.6H16.9v2.6zm0-6.5h13.5v-2.6H16.9v2.6zm0-6.6h13.5v-2.6H16.9v2.6z"></path></symbol>
			<symbol viewBox="0 0 40 40" id="point"><path d="M34.6 7.1c0-1.1-1-2.1-2.1-2.1h-24c-1.1 0-2 1-2.1 2.1l-1.6 25C4.6 34.3 6.3 36 8.5 36h24c2.2 0 3.9-1.7 3.7-3.9l-1.6-25zm-5.9 6.1c-.2 4.6-3.7 8.2-8.3 8.2-4.6 0-8.2-3.7-8.4-8.3-.3-.2-.5-.6-.5-1 0-.7.6-1.2 1.3-1.2s1.3.6 1.3 1.2c0 .5-.3.9-.7 1.1.2 3.8 3.2 6.8 7.1 6.8 3.9 0 6.8-3.1 7-6.9-.4-.2-.6-.6-.6-1.1 0-.7.6-1.2 1.3-1.2s1.3.6 1.3 1.2c-.2.6-.4 1-.8 1.2z"></path></symbol>
			<symbol viewBox="0 0 40 40" id="vip"><path d="M7 33.4c0 1.1.9 1.6 2 1.6h22c1.1 0 2-.5 2-1.6V31H7v2.4z"></path><path d="M32.1 14.3c-.6 2.3-2.6 4-5.1 4-2.9 0-5.3-2.3-5.3-5.2v-.2c-.5.2-1 .3-1.6.3-.6 0-1.1-.1-1.7-.3v.2c0 2.9-2.4 5.2-5.3 5.2-2.5 0-4.6-1.7-5.1-4.1-.5.4-1.2.6-1.8.6-.3 0-.5.1-.8 0L7.2 29h26l1.7-14.2c-.3.1-.5.1-.8.1-.8 0-1.5-.2-2-.6z" class="st0"></path><ellipse cx="20.1" cy="8.2" rx="3.2" ry="3.2"></ellipse><ellipse cx="6.4" cy="10.5" rx="2.4" ry="2.4"></ellipse><ellipse cx="33.8" cy="10.5" rx="2.4" ry="2.4"></ellipse></symbol>
			<symbol viewBox="0 0 40 40" id="download"><path d="M30 5H10c-2.8 0-5 2.2-5 5v20c0 2.8 2.2 5 5 5h20c2.8 0 5-2.2 5-5V10c0-2.8-2.2-5-5-5zm-3.9 22.7c-.1.2-.3.4-.6.5-4.3 2.8-10.1 1.6-13-2.8-2.8-4.3-1.6-10.2 2.8-13 4.3-2.8 10.2-1.6 13 2.8.2.2.3.5.4.8.1.2 0 .5-.2.7l-8.8 5.7c-.2.2-.6.1-.7-.2l-.5-.7c-.4-.6-.2-1.5.4-1.9l5.6-3.6c.2-.2.3-.5.2-.7l-.1-.1c-2.2-1.8-5.4-2.1-7.9-.4-3.1 2-4 6.1-2 9.2 2 3.1 6.1 4 9.2 2 .6-.4 1.3-.2 1.7.4l.3.7c.1.2.4.5.2.6zm3.1-4.4l-.9.6c-.2.2-.6.1-.7-.2L26.5 22c-.2-.2-.1-.6.2-.7l1.8-1.1c.2-.2.6-.1.7.2l.6.9c.3.6.1 1.5-.6 2z"></path></symbol>
			<symbol viewBox="0 0 40 40" id="service"><g id="service_XMLID_1_"><path id="service_XMLID_6_" d="M32.2 9.5c-.2-.7-.1-.7-.4-.9-1.7-1.2-5.3.2-6.7 1.9-.8-3.8-3.8-6.1-4.7-5.9-.9-.2-4 2.1-4.8 5.9-1.3-1.7-5-3.1-6.7-1.9-.1.1-.5.6-.5.7C5.4 20.7 15 24.6 19 25.7v8.7c0 .7.3 1.2 1 1.2s1-.5 1-1.2v-8.6c4-1 14.2-4.8 11.2-16.3z"></path><path id="service_XMLID_7_" d="M6 25c-.9 0-1.6.7-1.6 1.5.1.8.7 1.5 1.6 1.5 3.1 0 6.5 1.5 8.5 3.7.3.3.7.6 1.1.6.4 0 .7-.1 1-.4.6-.6.6-1.6.1-2.3C14.1 26.8 10 25 6 25z"></path><path id="service_XMLID_8_" d="M34.6 25c-4 0-8.1 1.9-10.7 4.6-.6.6-.5 1.6.1 2.2.3.3.7.4 1 .4.4 0 .8-.3 1.1-.6 2-2.1 5.3-3.7 8.4-3.7h.1c.8 0 1.5-.7 1.5-1.5 0-.7-.7-1.4-1.5-1.4z"></path></g><path d="M0 0h40v40H0z" class="st1"></path></symbol>
			<symbol viewBox="0 0 120 120" id="select"><circle cx="60" cy="60" r="60"></circle><path fill="#FFF" d="M63.84 84.678a1.976 1.976 0 0 1-.387.545l-7.975 7.976a1.996 1.996 0 0 1-2.829-.005L24.172 64.716a2.005 2.005 0 0 1-.005-2.828l7.976-7.976a1.996 1.996 0 0 1 2.828.005l19.015 19.015L91.498 35.42a1.991 1.991 0 0 1 2.823 0l7.976 7.977c.784.784.78 2.043 0 2.823L63.84 84.678z"></path></symbol>
			<symbol xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 72 72" id="sdk_icon_zhifubao@2x"><defs><path d="M36 72c19.882 0 36-16.118 36-36S55.882 0 36 0 0 16.118 0 36s16.118 36 36 36z" id="sdk_icon_zhifubao@2x_a"></path></defs><g fill="none" fill-rule="evenodd"><mask id="sdk_icon_zhifubao@2x_b" fill="#fff"><use xlink:href="#sdk_icon_zhifubao@2x_a"></use></mask><use fill="#00A1E9" xlink:href="#sdk_icon_zhifubao@2x_a"></use><path d="M33 21v-5h7v5h14v3H40v4h12c-.202.048-.408 3.223-2 7-1.32 4.134-2.683 6.15-2 6l23.6 8c-.2-.285-.848 2.3-2 4-.775 2.013-2 5-2 5L44 46c.237.162-3.79 4.674-8 7-4.002 1.645-8.717 2.88-14 1-4.93-.56-8.554-3.867-8-10 .693-6.083 7.138-8.19 13-8 4.739-.19 14.796 3.29 15 3-.204.29.642-1.628 2-4 .283-2.015.518-3.777 0-4H22v-3h11v-4H20v-3h13zm-7 30c-7.407 0-9-3.593-9-6 0-2.761 1.576-5.57 8-6 6.484-.383 15.2 4.436 15 4 .2.436-6.238 8-14 8z" fill="#FFF" mask="url(#sdk_icon_zhifubao@2x_b)"></path></g></symbol>
			<symbol viewBox="0 0 72 72" id="weixin"><g fill="none" fill-rule="evenodd"><path d="M36 72c19.882 0 36-16.118 36-36S55.882 0 36 0 0 16.118 0 36s16.118 36 36 36z" fill="#45C144"></path><path d="M29 40l-4-8c-.262-.292-.288-.398 0-1 .594-.228.743-.174 1 0l4 4c1.5 1.098 1.5 1.098 3 0l21-10c-3.668-4.964-10.11-8-17-8-12.33 0-22 8.12-22 18 0 5.6 2.91 10.518 7 14 1 .8 1.068.537 1 1 .068.185-.954 4.042-1 4-.027.316-.097.495 0 1-.097.075.225.4 1 0-.22.4 5-3 5-3 1.4.6 5.8 1 9 1 11.533 0 21.2-7.85 21-18 .2-2.899-.692-5.756-2-8L31 41c-1.5.5-2-1-2-1z" fill="#FFF"></path></g></symbol>
			<symbol viewBox="0 0 46 46" id="human"><path fill="#ff7b52" d="M33.291 37.774c-.25.097-.504.175-.765.233-6.427 1.444-5.954-3.968-6-3.953 10.457-5.053 10.348-13.466 10-16.216-16.15-.041-22.943-7.063-22.943-7.063s-.176 1.733-2.933 4.996c-2.756 3.262-5.236 4.09-5.132 4.113.54 13.9 12.246 14.242 12.246 14.242-.762 4.662-4.357 4.33-4.357 4.33s-6.38.213-11.173-7.446c-.85-1.359-1.02-2.864-1.166-4.579-.217-2.542.14-4.643.312-7.2.271-4.064.96-6.269.96-6.269S7.13 0 21.4 0s17.828 12.508 17.828 12.508l-.035.074c.533.763.984 1.997 1.356 3.36A3.483 3.483 0 0 1 45 19.281v7.257a3.484 3.484 0 0 1-3.325 3.472c-2.009 4.537-6.657 12.185-15.241 12.457C26.023 44.485 24.269 46 22.168 46c-2.407 0-4.357-1.988-4.357-4.44 0-2.453 1.95-4.44 4.357-4.44 1.955 0 3.609 1.311 4.16 3.118 1.447.13 4.044-.094 6.963-2.464zM18.216 27.018s.99 3.08 3.705 3.08 3.807-1.875 3.807-2.906c.467-1.135 1.348-.541 1.482-.071.134.47-.763 4.67-5.24 4.67s-5.205-4.358-5.205-4.358.033-.97.702-.97c.669 0 .749.555.749.555zm10.052-2.332c.963 0 1.743-1.192 1.743-2.664 0-1.471-.78-2.664-1.743-2.664-.963 0-1.743 1.193-1.743 2.664 0 1.472.78 2.664 1.743 2.664zm-12.723 0c.962 0 1.743-1.192 1.743-2.664 0-1.471-.78-2.664-1.743-2.664-.963 0-1.743 1.193-1.743 2.664 0 1.472.78 2.664 1.743 2.664z"></path></symbol>
			<symbol viewBox="0 0 46 46" id="phone"><path fill="#6ac20b" d="M15.433 30.568c9.342 9.342 17.708 12.15 18.871 12.316 1.163.167 3.07.542 5.837-2.225 3.24-3.24 3.566-4.94 1.783-6.724-1.783-1.783-6.212-4.48-7.416-5.176-1.206-.696-2.228-.472-3.097.133-.868.605-1.87 1.375-2.798 2.047-.927.671-2.087.955-3.332.167-1.245-.79-3.35-2.27-5.735-4.652-2.384-2.384-3.863-4.49-4.651-5.735-.789-1.245-.505-2.405.167-3.332.671-.928 1.441-1.93 2.046-2.798.605-.869.828-1.89.134-3.097-.696-1.204-3.394-5.633-5.177-7.416-1.783-1.783-3.484-1.457-6.724 1.783-2.766 2.766-2.391 4.674-2.226 5.837.167 1.164 2.976 9.53 12.318 18.872"></path></symbol>
			<symbol viewBox="0 0 126 126" id="expired"><path fill="#9B9B9B" fill-rule="evenodd" d="M63 125.5c34.518 0 62.5-27.982 62.5-62.5S97.518.5 63 .5.5 28.482.5 63s27.982 62.5 62.5 62.5zM15.156 66.678l-3.073-1.258 2.868-1.674.248-3.31 2.478 2.21 3.225-.79-1.335 3.04 1.746 2.825-3.302-.33-2.147 2.533-.704-3.245zm4.07-24.55l-2.03-2.625 3.32-.015 1.87-2.744 1.04 3.153 3.187.93-2.677 1.964.1 3.32-2.695-1.94-3.124 1.122 1.01-3.163zm15.8-19.223l-.446-3.29 2.883 1.646 2.99-1.44-.674 3.25 2.294 2.4-3.3.363-1.573 2.924-1.363-3.027-3.267-.592 2.457-2.233zm23.296-8.75l1.258-3.072 1.674 2.868 3.31.248-2.21 2.478.79 3.225-3.04-1.335-2.825 1.746.33-3.302-2.533-2.147 3.245-.704zm24.55 4.072l2.625-2.032.015 3.32 2.744 1.87-3.153 1.04-.93 3.188-1.964-2.677-3.32.1 1.94-2.695-1.122-3.124 3.163 1.01zm27.972 39.095l3.073 1.258-2.868 1.674-.248 3.31-2.478-2.21-3.225.79 1.335-3.04-1.746-2.825 3.302.33 2.147-2.533.704 3.245zm-4.07 24.55l2.03 2.625-3.32.015-1.87 2.744-1.04-3.153-3.187-.93 2.677-1.964-.1-3.32 2.695 1.94 3.124-1.122-1.01 3.163zm-15.8 19.223l.446 3.29-2.883-1.646-2.99 1.44.674-3.25-2.294-2.4 3.3-.363 1.573-2.924 1.363 3.027 3.267.592-2.457 2.233zm-23.296 8.75l-1.258 3.072-1.674-2.868-3.31-.248 2.21-2.478-.79-3.225 3.04 1.335 2.825-1.746-.33 3.302 2.533 2.147-3.245.704zm-24.55-4.072l-2.625 2.032-.015-3.32-2.744-1.87 3.153-1.04.93-3.188 1.964 2.677 3.32-.1-1.94 2.695 1.122 3.124-3.163-1.01zM74.257 41.7a23.764 23.764 0 0 0-22.17.092 23.767 23.767 0 0 0-12.508 18.646l.995.1a22.767 22.767 0 0 1 11.983-17.863 22.764 22.764 0 0 1 21.238-.088l.462-.887zm11.387 22.436A22.764 22.764 0 0 1 74.313 82.1a22.767 22.767 0 0 1-21.5.696l-.44.897a23.767 23.767 0 0 0 22.44-.727A23.764 23.764 0 0 0 86.64 64.214l-.997-.078zM63 122.5C30.14 122.5 3.5 95.86 3.5 63S30.14 3.5 63 3.5s59.5 26.64 59.5 59.5-26.64 59.5-59.5 59.5zm14.127-71.148l1.14 1.975 3.388-1.956-1.14-1.974-3.388 1.956zm2.704-3.14l-1.055-1.83-3.388 1.956 1.056 1.83 3.388-1.957zm.237 8.232l3.388-1.956-1.14-1.974-3.388 1.956 1.14 1.974zm-6.89-8.715a24.73 24.73 0 0 0-.892-1.453 7.288 7.288 0 0 0-.79-.985c.31-.104.617-.227.924-.367a6.52 6.52 0 0 0 .842-.46c.13-.093.226-.12.285-.08.06.04.066.128.017.267a.653.653 0 0 0-.032.378c.03.113.09.253.187.42l.85 1.475 3.39-1.956a39.962 39.962 0 0 0-1.01-1.677c-.25-.383-.472-.665-.67-.847a13.33 13.33 0 0 0 1.857-.767c.19-.09.313-.107.374-.05.062.057.064.148.007.273-.09.2-.128.356-.117.47.01.114.06.247.147.4l.792 1.37c.24-.157.48-.318.718-.483a9.91 9.91 0 0 0 .673-.513l1.02 1.766c-.26.095-.52.204-.78.327-.262.123-.525.243-.79.36l4.655 8.063c.234-.17.46-.333.675-.486.217-.153.43-.318.643-.496l.912 1.58c-.21.085-.434.177-.672.278-.238.1-.534.243-.888.43-.354.185-.79.423-1.307.712a205.733 205.733 0 0 0-3.876 2.238c-.516.307-.943.567-1.28.78-.34.215-.615.402-.828.562-.212.16-.408.31-.586.45l-.912-1.58c.638-.24 1.29-.533 1.958-.882l-4.668-8.085a20.893 20.893 0 0 0-1.67 1.186l-1.02-1.767a21.623 21.623 0 0 0 1.862-.854zm14.762 2.285l3.387-1.956-2.124-3.68-3.388 1.956 2.124 3.68zm-1.45-10.332l-3.387 1.956 1.956 3.387 3.387-1.956-1.956-3.387zm2.11 11.67c.274.634.514 1.305.717 2.01.204.704.36 1.408.47 2.11.11.704.167 1.4.17 2.093a10.19 10.19 0 0 1-.17 1.94c-.51-.15-1.18-.14-2.008.024.213-.974.312-1.88.298-2.723a10.595 10.595 0 0 0-.37-2.558c-.23-.865-.573-1.77-1.028-2.72a48.398 48.398 0 0 0-1.714-3.208l-2.7-4.676a25.767 25.767 0 0 0-.875-1.42 21.753 21.753 0 0 0-.85-1.186c.525-.21 1.043-.45 1.554-.717.51-.267 1.112-.6 1.805-1a60.923 60.923 0 0 0 1.893-1.136 17.45 17.45 0 0 0 1.502-1.047c.137.364.325.787.565 1.267.24.48.517.99.83 1.53l7.535 13.054a6.1 6.1 0 0 1 .46.94.97.97 0 0 1-.036.756c-.115.25-.347.527-.698.832-.35.304-.864.688-1.54 1.15a3.186 3.186 0 0 0-.647-.858 4.97 4.97 0 0 0-1.038-.717 13.81 13.81 0 0 0 1.096-.55c.264-.152.45-.295.555-.43a.502.502 0 0 0 .108-.437 2.097 2.097 0 0 0-.243-.566l-2.172-3.762-3.47 2.004zm-1.954 7.223a6.16 6.16 0 0 0-1.466-.69 6.537 6.537 0 0 0-1.563-.332l.69-1.59a14.604 14.604 0 0 1 3.05.817l-.71 1.794zm-4.033-.027a2.137 2.137 0 0 0-.287.51 6.12 6.12 0 0 0-.26.872 23.78 23.78 0 0 0-.283 1.452c-.1.594-.225 1.34-.37 2.237a3.37 3.37 0 0 0-.92-.078 5.34 5.34 0 0 0-1.096.19 8.492 8.492 0 0 0 .812-2.41c.15-.843.175-1.782.077-2.816.39.034.75.034 1.08 0a8.61 8.61 0 0 0 1.06-.182c.14-.044.227-.04.26.017.03.056.007.126-.074.21zm-17.506-5.745c.68-.392 1.22-.72 1.624-.98.405-.26.798-.538 1.182-.834l1.044 1.81c-.426.19-.86.4-1.3.626a40.64 40.64 0 0 0-1.66.917l5.015 8.688c.21.36.354.684.435.97.082.285.043.584-.118.9-.16.313-.468.676-.924 1.086-.455.41-1.11.918-1.962 1.52a10.17 10.17 0 0 0-.84-.83 7.863 7.863 0 0 0-1.12-.836 20.7 20.7 0 0 0 1.457-.813c.36-.226.625-.43.797-.612.172-.183.262-.346.27-.49a.783.783 0 0 0-.117-.444l-4.68-8.105-4.448 2.568c-.846.488-1.512.886-2 1.195-.485.31-.936.6-1.35.877l-1.03-1.788c.236-.1.472-.204.706-.31.234-.108.484-.234.75-.38a93.69 93.69 0 0 0 2.035-1.132l4.45-2.568a106.39 106.39 0 0 0-1.3-2.202c-.33-.54-.576-.92-.74-1.138.35-.13.72-.29 1.105-.486.387-.194.696-.378.93-.55.192-.147.346-.176.462-.086.117.09.133.205.048.346a.79.79 0 0 0-.08.56c.044.186.098.335.162.446l1.2 2.08zm-1.79 11.537a25.633 25.633 0 0 0-1.934-1.475 35.97 35.97 0 0 0-2.03-1.31l1.267-1.644a38.25 38.25 0 0 1 2.034 1.195c.68.428 1.346.9 1.993 1.412l-1.33 1.822zm-12.53-7.01c.706.293 1.41.608 2.11.942.702.334 1.376.693 2.022 1.078l-1.13 2.12a56.81 56.81 0 0 0-2.01-1.152 41.097 41.097 0 0 0-2.06-1.044l1.067-1.945zM63 118.25c30.514 0 55.25-24.736 55.25-55.25S93.514 7.75 63 7.75 7.75 32.486 7.75 63 32.486 118.25 63 118.25zm-2.237-47.53c.262-.058.562-.097.9-.118.34-.02.753-.04 1.24-.063.52-.025 1.176-.163 1.964-.415.788-.25 1.72-.646 2.794-1.184 1.077-.536 2.303-1.235 3.682-2.096a87.9 87.9 0 0 0 4.634-3.133 10.2 10.2 0 0 0 .24 1.4c.098.378.23.74.394 1.09a321.96 321.96 0 0 1-4.068 2.362 69.403 69.403 0 0 1-3.052 1.65c-.88.445-1.643.802-2.29 1.074s-1.236.483-1.768.633c-.533.15-1.03.256-1.492.32-.462.063-.954.107-1.476.13-.62.046-1.087.126-1.4.24-.31.117-.536.344-.674.682-.123.33-.22.74-.286 1.232a18.89 18.89 0 0 0-.144 1.62 7.14 7.14 0 0 0-1.164-.31 9.118 9.118 0 0 0-1.23-.136c.132-.575.256-1.07.374-1.49.118-.42.23-.785.338-1.096.106-.31.212-.575.318-.793.105-.22.214-.407.326-.564l-3.66-6.34c-.582.337-1.08.634-1.495.892-.415.257-.75.498-1.01.722l-.972-1.684c.293-.132.648-.3 1.066-.505.42-.203.83-.42 1.23-.653a31.8 31.8 0 0 0 1.27-.775c.433-.277.775-.516 1.028-.718.14.4.292.778.46 1.134.17.355.413.81.733 1.364l3.193 5.53zm-15.907-.43l-2.712-4.7-5.425 3.133c-1.456.84-2.783 1.63-3.983 2.368-1.2.74-2.125 1.344-2.778 1.813l-1.237-2.14c.307-.14.708-.335 1.202-.583.494-.25 1.055-.54 1.684-.876a143.593 143.593 0 0 0 4.375-2.429 153.71 153.71 0 0 0 4.442-2.648c1.175-.734 2.054-1.315 2.638-1.745.15.357.367.813.652 1.37a42.88 42.88 0 0 0 1.05 1.915l1.848 3.2a32.46 32.46 0 0 0 1.93 2.96l-2.057 1.188-.72-1.247-9.395 5.424 3.072 5.32c.224.39.415.68.574.875.158.195.345.304.562.327.216.023.5-.045.853-.202.353-.157.838-.405 1.455-.743.876-.47 1.734-.942 2.577-1.42a68.054 68.054 0 0 0 2.465-1.465c.754-.453 1.335-.84 1.743-1.158.407-.318.686-.66.836-1.023.15-.364.185-.81.104-1.334a26.6 26.6 0 0 0-.45-2.124c.843.437 1.734.523 2.67.26.206 1.026.324 1.854.354 2.483.03.628-.083 1.184-.34 1.665-.258.48-.698.943-1.32 1.386-.623.443-1.495.988-2.617 1.636l-2.545 1.47c-.908.524-1.758.996-2.55 1.417-1.063.558-1.902.97-2.517 1.23-.615.264-1.123.368-1.524.313-.402-.055-.75-.274-1.045-.657-.297-.385-.652-.937-1.068-1.658l-3.444-5.965a27.726 27.726 0 0 0-1.155-1.855c-.337-.49-.602-.835-.793-1.04.37-.157.762-.342 1.176-.553.414-.212.79-.425 1.13-.64.185-.125.32-.144.41-.056.087.088.085.214-.005.377a.624.624 0 0 0-.105.394c.015.12.082.286.202.494l.384.665 9.396-5.424zM10.402 63c0-29.05 23.55-52.598 52.598-52.598 29.05 0 52.598 23.55 52.598 52.598 0 29.05-23.55 52.598-52.598 52.598-29.05 0-52.598-23.55-52.598-52.598z"></path></symbol>
		</defs>
	</svg>
</template>

<script>

  	export default {

  	}

</script>

<style lang="scss">
  	
</style>


================================================
FILE: src/components/footer/footGuide.vue
================================================
<template>
    <section id='foot_guide'>
    	<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
	    	<defs>
	    		<symbol viewBox="0 0 40 40" id="msite"><g fill="none" fill-rule="evenodd" stroke="#666" stroke-width="2"><path d="M31.426 23.095l2.678 5.742 2.943-1.372a3.173 3.173 0 0 0 1.537-4.212l-1.339-2.871-5.819 2.713z"></path><path d="M29.074 31.161c-1.224-.49-2.404-.32-3.49.185-6.383 2.977-13.938.286-16.875-6.01-2.936-6.297-.14-13.815 6.243-16.792 5.211-2.43 11.203-1.083 14.825 2.919l-12.263 5.718c-1.596.745-2.295 2.624-1.561 4.198.734 1.574 2.625 2.246 4.22 1.503l8.422-3.928 9.953-4.641a18.78 18.78 0 0 0-.941-2.453C33.202 2.416 21.869-1.62 12.294 2.844 2.718 7.309-1.474 18.586 2.93 28.03c4.404 9.445 15.737 13.482 25.313 9.017 1.069-.499 2.067-.879 3.438-1.744 0 0-1.382-3.651-2.607-4.142z"></path></g></symbol>
				
				<symbol xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 40 40" id="msiteActive"><defs><linearGradient id="index.18edf5a_c" x1="50%" x2="50%" y1="100%" y2="0%"><stop offset="0%" stop-color="#2BAEFF"></stop><stop offset="100%" stop-color="#0095FF"></stop></linearGradient><linearGradient id="index.18edf5a_d" x1="50%" x2="50%" y1="100%" y2="0%"><stop offset="0%" stop-color="#29ADFF"></stop><stop offset="100%" stop-color="#0095FF"></stop></linearGradient><path id="index.18edf5a_a" d="M30.426 22.095l2.678 5.742 2.943-1.372a3.173 3.173 0 0 0 1.537-4.212l-1.339-2.871-5.819 2.713z"></path><mask id="index.18edf5a_e" width="9.455" height="10.456" x="-1" y="-1"><path fill="#fff" d="M29.426 18.382h9.455v10.456h-9.455z"></path><use xlink:href="#index.18edf5a_a"></use></mask><path id="index.18edf5a_b" d="M28.074 30.161c-1.224-.49-2.404-.32-3.49.185-6.383 2.977-13.938.286-16.875-6.01-2.936-6.297-.14-13.815 6.243-16.792 5.211-2.43 11.203-1.083 14.825 2.919l-12.263 5.718c-1.596.745-2.295 2.624-1.561 4.198.734 1.574 2.625 2.246 4.22 1.503l8.422-3.928 9.953-4.641a18.78 18.78 0 0 0-.941-2.453C32.202 1.416 20.869-2.62 11.294 1.844 1.718 6.309-2.474 17.586 1.93 27.03c4.404 9.445 15.737 13.482 25.313 9.017 1.069-.499 2.067-.879 3.438-1.744 0 0-1.382-3.651-2.607-4.142z"></path><mask id="index.18edf5a_f" width="38.769" height="39.241" x="-.7" y="-.7"><path fill="#fff" d="M-.521-.675h38.769v39.241H-.521z"></path><use xlink:href="#index.18edf5a_b"></use></mask></defs><g fill="none" fill-rule="evenodd"><g transform="translate(1 1)"><use fill="url(#index.18edf5a_c)" xlink:href="#index.18edf5a_a"></use><use stroke="url(#index.18edf5a_d)" stroke-width="2" mask="url(#index.18edf5a_e)" xlink:href="#index.18edf5a_a"></use></g><g transform="translate(1 1)"><use fill="url(#index.18edf5a_c)" xlink:href="#index.18edf5a_b"></use><use stroke="url(#index.18edf5a_d)" stroke-width="1.4" mask="url(#index.18edf5a_f)" xlink:href="#index.18edf5a_b"></use></g></g></symbol>

				<symbol xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 40 40" id="find"><defs><path id="discover-regular.8ef537f_a" d="M20 40c11.046 0 20-8.954 20-20S31.046 0 20 0 0 8.954 0 20s8.954 20 20 20z"></path><mask id="discover-regular.8ef537f_b" width="40" height="40" x="0" y="0" fill="#fff"><use xlink:href="#discover-regular.8ef537f_a"></use></mask></defs><g fill="none" fill-rule="evenodd"><use stroke="#666" stroke-width="4" mask="url(#discover-regular.8ef537f_b)" xlink:href="#discover-regular.8ef537f_a"></use><path stroke="#666" stroke-width="2" d="M12.79 28.126c-1.515.68-2.169.016-1.462-1.484l3.905-8.284c.47-.999 1.665-2.198 2.66-2.675l8.484-4.064c1.497-.717 2.153-.08 1.46 1.435l-3.953 8.64c-.46 1.006-1.647 2.186-2.655 2.64l-8.44 3.792z"></path><path fill="#666" d="M15.693 24.636c-.692.276-1.02-.06-.747-.746l2.21-4.946c.225-.505.721-.602 1.122-.202l2.563 2.563c.394.394.31.893-.203 1.122l-4.945 2.209z"></path></g></symbol>
				
                <symbol xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 40 40" id="findActive"><defs><path id="discover-regular.8ef537f_a" d="M20 40c11.046 0 20-8.954 20-20S31.046 0 20 0 0 8.954 0 20s8.954 20 20 20z"></path><mask id="discover-regular.8ef537f_b" width="40" height="40" x="0" y="0" fill="#fff"><use xlink:href="#discover-regular.8ef537f_a"></use></mask></defs><g fill="none" fill-rule="evenodd"><use stroke="#3190e8" stroke-width="4" mask="url(#discover-regular.8ef537f_b)" xlink:href="#discover-regular.8ef537f_a"></use><path stroke="#3190e8" stroke-width="2" d="M12.79 28.126c-1.515.68-2.169.016-1.462-1.484l3.905-8.284c.47-.999 1.665-2.198 2.66-2.675l8.484-4.064c1.497-.717 2.153-.08 1.46 1.435l-3.953 8.64c-.46 1.006-1.647 2.186-2.655 2.64l-8.44 3.792z"></path><path fill="#3190e8" d="M15.693 24.636c-.692.276-1.02-.06-.747-.746l2.21-4.946c.225-.505.721-.602 1.122-.202l2.563 2.563c.394.394.31.893-.203 1.122l-4.945 2.209z"></path></g></symbol>

				<symbol xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 38 38" id="order"><defs><rect id="order-regular.41c17f8_a" width="38" height="38" rx="2"></rect><mask id="order-regular.41c17f8_b" width="38" height="38" x="0" y="0" fill="#fff"><use xlink:href="#order-regular.41c17f8_a"></use></mask></defs><g fill="none" fill-rule="evenodd"><use stroke="#666" stroke-width="4" mask="url(#order-regular.41c17f8_b)" xlink:href="#order-regular.41c17f8_a"></use><rect width="24" height="2" x="7" y="8" fill="#666" rx="1"></rect><rect width="20" height="2" x="7" y="17" fill="#666" rx="1"></rect><rect width="8" height="2" x="7" y="26" fill="#666" rx="1"></rect></g></symbol>

				<symbol viewBox="0 0 38 38" id="orderActive"><defs><linearGradient id="order.070ae2a_a" x1="50%" x2="50%" y1="100%" y2="0%"><stop offset="0%" stop-color="#2BAEFF"></stop><stop offset="100%" stop-color="#0095FF"></stop></linearGradient></defs><g fill="none" fill-rule="evenodd"><rect width="38" height="38" fill="url(#order.070ae2a_a)" rx="2"></rect><rect width="24" height="2" x="7" y="8" fill="#FFF" rx="1"></rect><rect width="20" height="2" x="7" y="17" fill="#FFF" rx="1"></rect><rect width="8" height="2" x="7" y="26" fill="#FFF" rx="1"></rect></g></symbol>

				<symbol xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 38 38" id="profile"><defs><path id="profile-regular.c151d62_a" d="M10 11.833V8.999A8.999 8.999 0 0 1 19 0c4.97 0 9 4.04 9 8.999v2.834l-.013.191C27.657 16.981 23.367 21 19 21c-4.616 0-8.64-4.02-8.987-8.976L10 11.833z"></path><mask id="profile-regular.c151d62_c" width="18" height="21" x="0" y="0" fill="#fff"><use xlink:href="#profile-regular.c151d62_a"></use></mask><path id="profile-regular.c151d62_b" d="M0 32.675C0 26.763 10.139 22 19.027 22 27.916 22 38 26.763 38 32.757v3.312C38 37.136 37.098 38 35.997 38H2.003C.897 38 0 37.137 0 36.037v-3.362z"></path><mask id="profile-regular.c151d62_d" width="38" height="16" x="0" y="0" fill="#fff"><use xlink:href="#profile-regular.c151d62_b"></use></mask></defs><g fill="none" fill-rule="evenodd" stroke="#666" stroke-width="4"><use mask="url(#profile-regular.c151d62_c)" xlink:href="#profile-regular.c151d62_a"></use><use mask="url(#profile-regular.c151d62_d)" xlink:href="#profile-regular.c151d62_b"></use></g></symbol>

				<symbol viewBox="0 0 38 38" id="profileActive"><defs><linearGradient id="profile.dbc5ebf_a" x1="50%" x2="50%" y1="100%" y2="0%"><stop offset="0%" stop-color="#2BAEFF"></stop><stop offset="100%" stop-color="#0095FF"></stop></linearGradient></defs><path fill="url(#profile.dbc5ebf_a)" fill-rule="evenodd" d="M10 11.833V8.999A8.999 8.999 0 0 1 19 0c4.97 0 9 4.04 9 8.999v2.834l-.013.191C27.657 16.981 23.367 21 19 21c-4.616 0-8.64-4.02-8.987-8.976L10 11.833zM0 32.675C0 26.763 10.139 22 19.027 22 27.916 22 38 26.763 38 32.757v3.312C38 37.136 37.098 38 35.997 38H2.003C.897 38 0 37.137 0 36.037v-3.362z"></path></symbol>

	    	</defs>
    	</svg>
        <section @click = "gotoAddress({path: '/msite', query: {geohash}})" class="guide_item">
        	<svg class="icon_style">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" :xlink:href="$route.path.indexOf('msite') !== -1? '#msiteActive' : '#msite'"></use>
            </svg>
            <span>外卖</span>
        </section>
        <section @click = "gotoAddress({path: `/search/${geohash}`})" class="guide_item">
        	<svg class="icon_style">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" :xlink:href="$route.path.indexOf('search') !== -1? '#findActive' : '#find'"></use>
            </svg>
            <span>搜索</span>
        </section>
        <section @click = "gotoAddress('/order')" class="guide_item">
        	<svg class="icon_style">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" :xlink:href="$route.path.indexOf('order') !== -1? '#orderActive' : '#order'"></use>
            </svg>
            <span>订单</span>
        </section>
        <section @click = "gotoAddress('/profile')" class="guide_item">
        	<svg class="icon_style">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" :xlink:href="$route.path.indexOf('profile') !== -1? '#profileActive' : '#profile'"></use>
            </svg>
            <span>我的</span>
        </section>
    </section>
</template>

<script>
    import {mapState} from 'vuex'
    export default {
    	data(){
            return{
                
            }
        },
        created(){
           
        },
        mounted(){
            
        },
        computed: {
            ...mapState([
                'geohash'
            ]),
        },
        methods: {
        	gotoAddress(path){
        		this.$router.push(path)
        	}
        },

    }

</script>

<style lang="scss" scoped>
    @import '../../style/mixin';

    #foot_guide{
        background-color: #fff;
        position: fixed;
        z-index: 100;
        left: 0;
        right: 0;
        bottom: 0;
        @include wh(100%, 1.95rem);
        display: flex;
        box-shadow: 0 -0.026667rem 0.053333rem rgba(0,0,0,.1);
    }
    .guide_item{
    	flex: 1;
    	display: flex;
    	text-align: center;
    	flex-direction: column;
    	align-items: center;
		.icon_style{
			@include wh(.8rem, .8rem);
			margin-top: .3rem;
			fill: #ccc;
		}
		span{
			@include sc(.45rem, #666);
		}
    }
   
</style>


================================================
FILE: src/components/header/head.vue
================================================
<template>
    <header id='head_top'>
        <slot name='logo'></slot>
        <slot name='search'></slot>
        <section class="head_goback" v-if="goBack" @click="$router.go(-1)">
            <svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" version="1.1">
                <polyline points="12,18 4,9 12,0" style="fill:none;stroke:rgb(255,255,255);stroke-width:2"/>
            </svg>
        </section>
        <router-link :to="userInfo? '/profile':'/login'" v-if='signinUp' class="head_login">
            <svg class="user_avatar" v-if="userInfo">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#user"></use>
            </svg>
            <span class="login_span" v-else>登录|注册</span>
        </router-link>
        <section class="title_head ellipsis" v-if="headTitle">
            <span class="title_text">{{headTitle}}</span>
        </section>
        <slot name="edit"></slot>
        <slot name="msite-title"></slot>
        <slot name="changecity"></slot>
        <slot name="changeLogin"></slot>
    </header>
</template>

<script>
    import {mapState, mapActions} from 'vuex'
    export default {
    	data(){
            return{

            }
        },
        mounted(){
            //获取用户信息
            this.getUserInfo();

        },
        props: ['signinUp', 'headTitle', 'goBack'],
        computed: {
            ...mapState([
                'userInfo'
            ]),
        },
        methods: {
            ...mapActions([
                'getUserInfo'
            ]),
        },

    }

</script>

<style lang="scss" scoped>
    @import '../../style/mixin';

    #head_top{
        background-color: $blue;
        position: fixed;
        z-index: 100;
        left: 0;
        top: 0;
        @include wh(100%, 1.95rem);
    }
    .head_goback{
        left: 0.4rem;
        @include wh(0.6rem, 1rem);
        line-height: 2.2rem;
        margin-left: .4rem;
    }
    .head_login{
        right: 0.55rem;
        @include sc(0.65rem, #fff);
        @include ct;
        .login_span{
            color: #fff;
        }
        .user_avatar{
            fill: #fff;
            @include wh(.8rem, .8rem);
        }
    }
    .title_head{
        @include center;
        width: 50%;
        color: #fff;
        text-align: center;
        .title_text{
            @include sc(0.8rem, #fff);
            text-align: center;
            font-weight: bold;
        }
    }
</style>


================================================
FILE: src/config/env.js
================================================
/**
 * 配置编译环境和线上环境之间的切换
 * 
 * baseUrl: 域名地址
 * routerMode: 路由模式
 * imgBaseUrl: 图片所在域名地址
 * 
 */

let baseUrl = ''; 
let routerMode = 'hash';
let imgBaseUrl = '';


if (process.env.NODE_ENV == 'development') {
    imgBaseUrl = '/img/';

}else if(process.env.NODE_ENV == 'production'){
	baseUrl = '//elm.cangdu.org';
    imgBaseUrl = '//elm.cangdu.org/img/';
}

export {
	baseUrl,
	routerMode,
	imgBaseUrl,
}

================================================
FILE: src/config/fetch.js
================================================
import {
	baseUrl
} from './env'

export default async(url = '', data = {}, type = 'GET', method = 'fetch') => {
	type = type.toUpperCase();
	url = baseUrl + url;

	if (type == 'GET') {
		let dataStr = ''; //数据拼接字符串
		Object.keys(data).forEach(key => {
			dataStr += key + '=' + data[key] + '&';
		})

		if (dataStr !== '') {
			dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
			url = url + '?' + dataStr;
		}
	}

	if (window.fetch && method == 'fetch') {
		let requestConfig = {
			credentials: 'include',
			method: type,
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},
			mode: "cors",
			cache: "force-cache"
		}

		if (type == 'POST') {
			Object.defineProperty(requestConfig, 'body', {
				value: JSON.stringify(data)
			})
		}
		
		try {
			const response = await fetch(url, requestConfig);
			const responseJson = await response.json();
			return responseJson
		} catch (error) {
			throw new Error(error)
		}
	} else {
		return new Promise((resolve, reject) => {
			let requestObj;
			if (window.XMLHttpRequest) {
				requestObj = new XMLHttpRequest();
			} else {
				requestObj = new ActiveXObject;
			}

			let sendData = '';
			if (type == 'POST') {
				sendData = JSON.stringify(data);
			}

			requestObj.open(type, url, true);
			requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			requestObj.send(sendData);

			requestObj.onreadystatechange = () => {
				if (requestObj.readyState == 4) {
					if (requestObj.status == 200) {
						let obj = requestObj.response
						if (typeof obj !== 'object') {
							obj = JSON.parse(obj);
						}
						resolve(obj)
					} else {
						reject(requestObj)
					}
				}
			}
		})
	}
}

================================================
FILE: src/config/mUtils.js
================================================
/**
 * 存储localStorage
 */
export const setStore = (name, content) => {
	if (!name) return;
	if (typeof content !== 'string') {
		content = JSON.stringify(content);
	}
	window.localStorage.setItem(name, content);
}

/**
 * 获取localStorage
 */
export const getStore = name => {
	if (!name) return;
	return window.localStorage.getItem(name);
}

/**
 * 删除localStorage
 */
export const removeStore = name => {
	if (!name) return;
	window.localStorage.removeItem(name);
}

/**
 * 获取style样式
 */
export const getStyle = (element, attr, NumberMode = 'int') => {
    let target;
    // scrollTop 获取方式不同,没有它不属于style,而且只有document.body才能用
    if (attr === 'scrollTop') { 
        target = element.scrollTop;
    }else if(element.currentStyle){
        target = element.currentStyle[attr]; 
    }else{ 
        target = document.defaultView.getComputedStyle(element,null)[attr]; 
    }
    //在获取 opactiy 时需要获取小数 parseFloat
    return  NumberMode == 'float'? parseFloat(target) : parseInt(target);
} 

/**
 * 页面到达底部,加载更多
 */
export const loadMore = (element, callback) => {
	let windowHeight = window.screen.height;
	let height;
	let setTop;
	let paddingBottom;
	let marginBottom;
    let requestFram;
    let oldScrollTop;

    document.body.addEventListener('scroll',() => {
       loadMore();
    }, false)
    //运动开始时获取元素 高度 和 offseTop, pading, margin
	element.addEventListener('touchstart',() => {
        height = element.offsetHeight;
        setTop = element.offsetTop;
        paddingBottom = getStyle(element,'paddingBottom');
        marginBottom = getStyle(element,'marginBottom');
    },{passive: true})

    //运动过程中保持监听 scrollTop 的值判断是否到达底部
    element.addEventListener('touchmove',() => {
       loadMore();
    },{passive: true})

    //运动结束时判断是否有惯性运动,惯性运动结束判断是非到达底部
    element.addEventListener('touchend',() => {
       	oldScrollTop = document.body.scrollTop;
       	moveEnd();
    },{passive: true})
    
    const moveEnd = () => {
        requestFram = requestAnimationFrame(() => {
            if (document.body.scrollTop != oldScrollTop) {
                oldScrollTop = document.body.scrollTop;
                loadMore();
                moveEnd();
            }else{
            	cancelAnimationFrame(requestFram);
            	//为了防止鼠标抬起时已经渲染好数据从而导致重获取数据,应该重新获取dom高度
            	height = element.offsetHeight;
                loadMore();
            }
        })
    }

    const loadMore = () => {
        if (document.body.scrollTop + windowHeight >= height + setTop + paddingBottom + marginBottom) {
            callback();
        }
    }
}

/**
 * 显示返回顶部按钮,开始、结束、运动 三个过程中调用函数判断是否达到目标点
 */
export const showBack = callback => {
    let requestFram;
    let oldScrollTop;

    document.addEventListener('scroll',() => {
       showBackFun();
    }, false)
    document.addEventListener('touchstart',() => {
       showBackFun();
    },{passive: true})

    document.addEventListener('touchmove',() => {
       showBackFun();
    },{passive: true})

    document.addEventListener('touchend',() => {
        oldScrollTop = document.body.scrollTop;
        moveEnd();
    },{passive: true})
    
    const moveEnd = () => {
        requestFram = requestAnimationFrame(() => {
            if (document.body.scrollTop != oldScrollTop) {
                oldScrollTop = document.body.scrollTop;
                moveEnd();
            }else{
                cancelAnimationFrame(requestFram);
            }
            showBackFun();
        })
    }

    //判断是否达到目标点
    const showBackFun = () => {
        if (document.body.scrollTop > 500) {
            callback(true);
        }else{
            callback(false);
        }
    }
}


/**
 * 运动效果
 * @param {HTMLElement} element   运动对象,必选
 * @param {JSON}        target    属性:目标值,必选
 * @param {number}      duration  运动时间,可选
 * @param {string}      mode      运动模式,可选
 * @param {function}    callback  可选,回调函数,链式动画
 */
export const animate = (element, target, duration = 400, mode = 'ease-out', callback) => {
    clearInterval(element.timer);

    //判断不同参数的情况
    if (duration instanceof Function) {
        callback = duration;
        duration = 400;
    }else if(duration instanceof String){
        mode = duration;
        duration = 400;
    }

    //判断不同参数的情况
    if (mode instanceof Function) {
        callback = mode;
        mode = 'ease-out';
    }

    //获取dom样式
    const attrStyle = attr => {
        if (attr === "opacity") { 
            return Math.round(getStyle(element, attr, 'float') * 100);
        } else {
            return getStyle(element, attr);
        }
    }
    //根字体大小,需要从此将 rem 改成 px 进行运算
    const rootSize = parseFloat(document.documentElement.style.fontSize);

    const unit = {};
    const initState = {};

    //获取目标属性单位和初始样式值
    Object.keys(target).forEach(attr => {
        if (/[^\d^\.]+/gi.test(target[attr])) {
            unit[attr] = target[attr].match(/[^\d^\.]+/gi)[0] || 'px';
        }else{
            unit[attr] = 'px';
        }
        initState[attr] = attrStyle(attr);
    });

    //去掉传入的后缀单位
    Object.keys(target).forEach(attr => {
        if (unit[attr] == 'rem') {
            target[attr] = Math.ceil(parseInt(target[attr])*rootSize);
        }else{
            target[attr] = parseInt(target[attr]);
        }
    });


    let flag = true; //假设所有运动到达终点
    const remberSpeed = {};//记录上一个速度值,在ease-in模式下需要用到
    element.timer = setInterval(() => {
        Object.keys(target).forEach(attr => {
            let iSpeed = 0;  //步长
            let status = false; //是否仍需运动
            let iCurrent = attrStyle(attr) || 0; //当前元素属性址
            let speedBase = 0; //目标点需要减去的基础值,三种运动状态的值都不同
            let intervalTime; //将目标值分为多少步执行,数值越大,步长越小,运动时间越长
            switch(mode){
                case 'ease-out': 
                    speedBase = iCurrent;
                    intervalTime = duration*5/400;
                    break;
                case 'linear':
                    speedBase = initState[attr];
                    intervalTime = duration*20/400;
                    break;
                case 'ease-in':
                    let oldspeed = remberSpeed[attr] || 0;
                    iSpeed = oldspeed + (target[attr] - initState[attr])/duration;
                    remberSpeed[attr] = iSpeed
                    break;
                default:
                    speedBase = iCurrent;
                    intervalTime = duration*5/400; 
            }
            if (mode !== 'ease-in') {
                iSpeed = (target[attr] - speedBase) / intervalTime;
                iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
            }
            //判断是否达步长之内的误差距离,如果到达说明到达目标点
            switch(mode){
                case 'ease-out': 
                    status = iCurrent != target[attr]; 
                    break;
                case 'linear':
                    status = Math.abs(Math.abs(iCurrent) - Math.abs(target[attr])) > Math.abs(iSpeed);
                    break;
                case 'ease-in':
                    status = Math.abs(Math.abs(iCurrent) - Math.abs(target[attr])) > Math.abs(iSpeed);
                    break;
                default:
                    status = iCurrent != target[attr]; 
            }

            if (status) {
                flag = false; 
                //opacity 和 scrollTop 需要特殊处理
                if (attr === "opacity") {
                    element.style.filter = "alpha(opacity:" + (iCurrent + iSpeed) + ")";
                    element.style.opacity = (iCurrent + iSpeed) / 100;
                } else if (attr === 'scrollTop') {
                    element.scrollTop = iCurrent + iSpeed;
                }else{
                    element.style[attr] = iCurrent + iSpeed + 'px';
                }
            } else {
                flag = true;
            }

            if (flag) {
                clearInterval(element.timer);
                if (callback) {
                    callback();
                }
            }
        })
    }, 20);
}


================================================
FILE: src/config/rem.js
================================================
(function(doc, win) {
    var docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function() {
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';
        };
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

================================================
FILE: src/main.js
================================================
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './router/router'
import store from './store/'
import {routerMode} from './config/env'
import './config/rem'

Vue.use(VueRouter)
const router = new VueRouter({
	routes,
	mode: routerMode,
	strict: process.env.NODE_ENV !== 'production',
	scrollBehavior (to, from, savedPosition) {
	    if (savedPosition) {
		    return savedPosition
		} else {
			if (from.meta.keepAlive) {
				from.meta.savedPosition = document.body.scrollTop;
			}
		    return { x: 0, y: to.meta.savedPosition || 0 }
		}
	}
})

new Vue({
	router,
	store,
}).$mount('#app')



================================================
FILE: src/page/balance/balance.vue
================================================
 <template>
  <div class="page">
        <head-top head-title="我的余额" go-back='true'></head-top>
        <section class="content_container">
            <section class="content">
                <header class="content_header">
                    <span class="content_title_style">当前余额</span>
                    <section class="contetn_description">
                        <img src="../../images/description.png" height="24" width="24">
                        <router-link to="/balance/detail" class="content_title_style">余额说明</router-link>
                    </section>
                </header>
                <p class="content_num">
                    <span>0.00</span>
                    <span>元</span>
                </p>
                <div class="promit_button">提现</div>
            </section>
        </section>
        <p class="deal_detail">交易明细</p>
        <div class="no_log">
            <img src="../../images/no-log.png">
            <p>暂无明细记录</p>
        </div>
        <alert-tip v-if="showAlert" @closeTip="showAlert = false" :alertText="alertText"></alert-tip>
        <transition name="router-slid" mode="out-in">
            <router-view></router-view>
        </transition>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import alertTip from 'src/components/common/alertTip'
    
    export default {
      data(){
            return{
                showAlert: false,
                alertText: null,
            }
        },
        mounted(){
          
        },
        components: {
            headTop,
            alertTip,
        },
        computed: {
           
        },
        methods: {
            
        }
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .page{
        padding-top: 1.95rem;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .content_container{
        padding: .3rem;
        background-color: $blue;
        .content{
            padding: .4rem;
            background-color: #fff;
            border-radius: .15rem;
            .content_header{
                @include fj;
                font-size: .55rem;
                .contetn_description{
                    display: flex;
                    align-items: center;
                    img{
                        @include wh(.6rem, .6rem);
                        margin-right: .2rem;
                    }
                    .content_title_style{
                        color: $blue;
                    }
                }
                .content_title_style{
                    color: #666;
                }
            }
            .content_num{
                span:nth-of-type(1){
                    @include sc(1.8rem, #333);
                }
                span:nth-of-type(2){
                    @include sc(.7rem, #333);
                }
            }
            .promit_button{
                @include wh(100%, 2rem);
                @include sc(.8rem, #fff);
                border-radius: 0.15rem;
                line-height: 2rem;
                margin-top: 1rem;
                text-align: center;
                background-color: #ccc;
            }
        }
    }
    .deal_detail{
        @include sc(.6rem, #999);
        line-height: 2rem;
        padding-left: .5rem;
    }
    .no_log{
        text-align: center;
        margin-top: 1rem;
        img{
            @include wh(8rem, 5rem);
        }
        p{
            margin-top: .5rem;
            @include sc(.7rem, #666);
        }
    }
    .router-slid-enter-active, .router-slid-leave-active {
        transition: all .4s;
    }
    .router-slid-enter, .router-slid-leave-active {
        transform: translate3d(2rem, 0, 0);
        opacity: 0;
    }
</style>


================================================
FILE: src/page/balance/children/detail.vue
================================================
 <template>
    <div class="page">
        <head-top head-title="余额问题" go-back='true'></head-top>
        <div class="markdown"><h3 id="q1-">Q1: 使用余额的条件</h3>
        <p>为了保护账户安全,使用余额前必须先绑定手机号。</p>
        <h3 id="q2-">Q2: 余额可以怎么用?</h3>
        <p>余额可以在饿了么平台上提现,当余额大于等于待支付金额时可以在支持在线支付的商家中进行消费。提现功能将于2016年12月25日00:00全面开放。</p>
        <h3 id="q3-">Q3:我要如何提现?</h3>
        <p>为了保护账户和资金安全,您在提现前需要输入真实姓名和用该姓名开通的银行卡号、选择开户行,并验证已绑定饿了么账号的手机号。每日只能提现1次,每次限额50元。若提现金额超过50元,点击【提现】时系统会提示您已超额,请您修改提现金额。</p>
        <h3 id="q4-">Q4:为什么会提现失败?</h3>
        <p>可能原因有:您的姓名、开户行、银行卡号等信息不匹配;您当日的提现次数和金额超过限制;您的账户存在异常,被风控拦截。</p>
        </div>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState, mapMutations} from 'vuex'
    import {payRequest} from 'src/service/getData'
    import alertTip from 'src/components/common/alertTip'
    import loading from 'src/components/common/loading'

    export default {
      data(){
            return{
               
            }
        },
        components: {
            headTop,
        },
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .page{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        padding-top: 1.95rem;
        z-index: 203;
        background-color: #fff;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .markdown{
        @include sc(.6rem, #666);
        padding: 0 0.5rem 0.5rem;
        h3{
            line-height: 2rem;
        }
        p,li{
            @include sc(.6rem, #666);
            line-height: 1rem;
        }
    }
</style>


================================================
FILE: src/page/benefit/benefit.vue
================================================
 <template>
  <div class="rating_page">
        <head-top head-title="我的优惠" go-back='true'></head-top>
        <section v-if="!showLoading">
            <section class="category_title"> 
                <span :class="{choosed: categoryType === 1}" @click="categoryType = 1">红包</span>
                <span :class="{choosed: categoryType === 2}" @click="categoryType = 2">商家代金券</span>
            </section>
            <transition name="router-fade">
                <section v-if="categoryType === 1">
                    <section class="hongbao_container">
                        <header class="hongbao_title">
                            <section class="total_number">
                                有 <span>{{hongbaoList.length}}</span> 个红包即将到期
                            </section>
                            <section class="hongbao_description">
                                <img src="../../images/description.png" height="24" width="24">
                                <router-link to="/benefit/hbDescription" class="hongbao_detail">红包说明</router-link>
                            </section>
                        </header>
                        <ul class="hongbao_list_ul">
                            <li class="hongbao_list_li" v-for="item in hongbaoList" :key="item.id">
                                <section class="list_item">
                                    <div class="list_item_left">
                                        <span>¥</span>
                                        <span>{{String(item.amount).split('.')[0]}}</span>
                                        <span>.</span>
                                        <span>{{String(item.amount).split('.')[1]||0}}</span>
                                        <p>{{item.description_map.sum_condition}}</p>
                                    </div>
                                    <div class="list_item_right">
                                        <h4>{{item.name}}</h4>
                                        <p>{{item.description_map.validity_periods}}</p>
                                        <p>{{item.description_map.phone}}</p>
                                    </div>
                                    <div class="time_left">{{item.description_map.validity_delta}}</div>
                                </section>
                                <footer class="list_item_footer" v-if="item.limit_map">
                                    <p>{{item.limit_map.restaurant_flavor_ids}}</p>
                                </footer>
                            </li>
                        </ul>
                    </section>
                    <router-link to="/benefit/hbHistory" class="history_hongbao">
                        <span class="check_history">查看历史红包</span>
                        <svg class="history_right">
                            <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#arrow-right"></use>
                        </svg>
                    </router-link>
                    <footer class="hongbao_footer">
                        <router-link to="/benefit/exchange" class="hongbao_style" style="border-right: 1px solid #f5f5f5">
                            兑换红包
                        </router-link>
                        <router-link to="/benefit/commend" class="hongbao_style">
                            推荐有奖
                        </router-link>
                    </footer>
                </section>
            </transition>
            <transition name="router-fade">
                <section v-if="categoryType === 2" class="voucher_container">
                    <section class="hongbao_description voucher_header">
                        <img src="../../images/description.png" height="24" width="24">
                        <router-link to="/benefit/coupon" class="hongbao_detail">商家代金券说明</router-link>
                    </section>
                    <section class="unable_use">
                        <img src="../../images/voucher.png" height="170" width="300">
                        <p>无法使用代金券</p>
                        <p>非客户端或客户端版本过低</p>
                        <router-link to="/download" class="download_app">
                        下载或升级客户端
                        </router-link>
                    </section>
                </section>
            </transition>
        </section>
        <alert-tip v-if="showAlert" @closeTip="showAlert = false" :alertText="alertText"></alert-tip>
        <loading v-show="showLoading"></loading>
        <transition name="router-slid" mode="out-in">
            <router-view></router-view>
        </transition>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState, mapMutations} from 'vuex'
    import {getHongbaoNum} from 'src/service/getData'
    import alertTip from 'src/components/common/alertTip'
    import loading from 'src/components/common/loading'

    export default {
      data(){
            return{
                showAlert: false, //弹出框
                alertText: null, //弹出框文字
                showLoading: true, //加载动画
                hongbaoList: null, //红包列表
                categoryType: 1, //红包与商家代金券切换

            }
        },
        mounted(){
            this.initData();
        },
        components: {
            headTop,
            alertTip,
            loading,
        },
        computed: {
            ...mapState([
                'userInfo',
            ]),
        },
        methods: {
            ...mapMutations([
                'CLEAR_CART'
            ]),
            async initData(){
                if (this.userInfo) {
                    this.hongbaoList = await getHongbaoNum(this.userInfo.user_id);
                    this.showLoading = false;
                }
            }
        },
        watch: {
            userInfo: function (value){
                this.initData();
            }
        }
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .rating_page{
        padding-top: 1.95rem;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .category_title{
        display: flex;
        justify-content: space-around;
        align-items: center;
        height: 2rem;
        background-color: #fff;
        span{
            text-align: center;
            @include sc(.65rem, #333);
            padding-bottom: .2rem;
            border-bottom: 0.1rem solid #fff;
        }
        .choosed{
            border-bottom-color: $blue;
            color: $blue;
        }
    }
    .hongbao_description{
        display: flex;
        align-items: center;
        img{
            @include wh(.6rem, .6rem);
            margin-right: .2rem;
        }
        .hongbao_detail{
            color: $blue;
        }
    }
    .hongbao_container{
        padding: 0 .7rem;
        .hongbao_title{
            @include fj;
            font-size: .5rem;
            line-height: 2rem;
            .total_number{
                color: #666;
                span{
                    color: #ff5340;
                }
            }
        }
        .hongbao_list_ul{
            .hongbao_list_li{
                background: #fff url(../../images/hongbao.png) repeat-x ;
                background-size: .5rem .2rem;
                margin-bottom: 0.5rem;
                border-radius: 0.25rem;
                .list_item{
                    @include fj;
                    padding: 1rem 0.5rem .8rem;
                    .list_item_left{
                        font-size: 0;
                        border-right: 0.025rem dotted #ccc;
                        flex: 1;
                        span:nth-of-type(1){
                            @include sc(.75rem, #ff5340);
                            font-weight: bold;
                        }
                        span:nth-of-type(2){
                            @include sc(1.5rem, #ff5340);
                        }
                        span:nth-of-type(3), span:nth-of-type(4){
                            @include sc(0.8rem, #ff5340);
                            font-weight: bold;
                        }
                        p{
                            @include sc(0.4rem, #999);
                        }
                    }
                    .list_item_right{
                        flex: 2;
                        margin-left: 1.5rem;
                        h4{
                            @include sc(.7rem, #666);
                            margin-left: -.7rem;
                        }
                        p{
                            list-style-type: disc;
                            margin-left: -.7rem;
                            @include sc(.4rem, #999);   
                        }
                    }
                    .time_left{
                        @include sc(.75rem, #ff5340);
                    }
                }
                .list_item_footer{
                    background-color: #f9f9f9;
                    padding: .4rem .4rem;
                    border-bottom-left-radius: 0.25rem;
                    border-bottom-right-radius: 0.25rem;
                    p{
                        list-style-type: disc;
                        @include sc(.4rem, #999);
                        margin-left: .4rem;
                    }
                }
            }
        }
    }
    .history_hongbao{
        padding: .5rem 0 2.8rem;
        display: flex;
        align-items: center;
        justify-content: center;
        .check_history{
            @include sc(.5rem, #999);
            margin-right: .2rem;
        }
        .history_right{
            @include wh(.4rem, .4rem);
            fill: #aaa;
        }
    }
    .hongbao_footer{
        position: fixed;
        bottom: 0;
        width: 100%;
        background-color: #fff;
        display: flex;
        .hongbao_style{
            flex: 1;
            line-height: 2rem;
            text-align: center;
            @include sc(.7rem, #555);
        }
    }
    .voucher_container{
        .voucher_header{
            font-size: .5rem;
            justify-content: flex-end;
            line-height: 2rem;
            margin-right: .5rem;
        }
        .unable_use{
            text-align: center;
            margin-top: 4rem;
            img{
                @include wh(6rem, 3.4rem);
            }
            p:nth-of-type(1){
                @include sc(.7rem, #666);
                margin-top: .4rem;
            }
            p:nth-of-type(2){
                @include sc(.5rem, #999);
                margin-top: .3rem;
                margin-bottom: .3rem;
            }
            .download_app{
                background-color: #56d176;
                @include sc(.65rem, #fff);
                padding: .3rem;
                border-radius: .15rem;
            }
        }
    }
    .router-fade-enter-active, .router-fade-leave-active {
        transition: opacity .3s;
    }
    .router-fade-enter, .router-fade-leave-active {
        opacity: 0;
    }
    .router-slid-enter-active, .router-slid-leave-active {
        transition: all .4s;
    }
    .router-slid-enter, .router-slid-leave-active {
        transform: translate3d(2rem, 0, 0);
        opacity: 0;
    }
</style>


================================================
FILE: src/page/benefit/children/commend.vue
================================================
 <template>
  <div class="page">
        <head-top head-title="推荐有奖" go-back='true'></head-top>
        <section class="activity_banner">
            <img src="../../../images/activity.png">
        </section>
        <section class="invite_firend">
            <div class="invite_firend_style">
                <img src="../../../images/weixin.png" @click="fenxiang">
                <p>邀请微信好友</p>
            </div>
            <div class="invite_firend_style">
                <img src="../../../images/qq.png" @click="fenxiang">
                <p>邀请QQ好友</p>
            </div>
            <div class="invite_firend_style">
                <img src="../../../images/fenxiang.png" @click="fenxiang">
                <p>面对面邀请</p>
            </div>
        </section>
        <section class="invite_num">
            <div class="invite_num_style">
                <p>累计收益</p>
                <p><span>0</span>元</p>
            </div>
            <div class="invite_num_style invite_people">
                <p>成功邀请</p>
                <p><span>0</span>人</p>
            </div>
        </section>
        <p class="income_detail">-收益明细-</p>
        <section class="incom_tips">
            <img src="../../../images/qianbao.png">
            <p>还不赶紧去邀请好友</p>
        </section>
        <alert-tip v-if="showAlert" @closeTip="showAlert = false" :alertText="alertText"></alert-tip>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState} from 'vuex'
    import {payRequest} from 'src/service/getData'
    import alertTip from 'src/components/common/alertTip'

    export default {
      data(){
            return{
                showAlert: false,
                alertText: null,
            }
        },
        mounted(){
            
        },
        components: {
            headTop,
            alertTip,
        },
        computed: {
            ...mapState([
                'userInfo',
            ]),
        },
        methods: {
            fenxiang(){
                this.showAlert = true;
                this.alertText = '请在饿了么APP中打开';
            }
        }
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .page{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        overflow-y: auto;
        padding-top: 1.95rem;
        z-index: 203;
        background-color: #f5f5f5;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .activity_banner{
        img{
            @include wh(100%, 10rem);
        }
    }
    .invite_firend{
        display: flex;
        padding: 1rem 0;
        background-color: #fff;
        .invite_firend_style{
            flex: 1;
            text-align: center;
            img{
                @include wh(2.5rem, 2.5rem);
            }
            p{
                @include sc(.5rem, #333);
            }
        }
    }
    .invite_num{
        display: flex;
        margin-top: 1rem;
        @include sc(.5rem, #666);
        .invite_num_style{
            flex: 1;
            text-align: center;
            p{
                color: #666;
            }
            span{
                @include sc(.8rem, #ff5633);
                font-weight: bold;
            }
        }
        .invite_people{
            border-left: 0.025rem solid #ddd;
            span{
                @include sc(.8rem, #666);
                font-weight: bold;
            }
        }
    }
    .income_detail{
        text-align: center;
        margin-top: 1rem;
        @include sc(.5rem, #666);
    }
    .incom_tips{
        text-align: center;
        margin-top: 1rem;
        img{
            @include wh(1.3rem, 1.6rem);
        }
        p{
            @include sc(.5rem, #999);
        }
    }
</style>


================================================
FILE: src/page/benefit/children/coupon.vue
================================================
 <template>
  <div class="page">
        <head-top head-title="代金券说明" go-back='true'></head-top>
        <div class="markdown">
            <h3 id="q1-">Q1: 什么是商家代金券?</h3>
            <p>商家代金券是指由商家自己发放代金券,只限在指定的商家使用,可根据条件抵扣相应金额。</p>
            <h3 id="q2-">Q2: 怎么获得商家代金券?</h3>
            <ul>
                <li>进入有「进店领券」或「下单返券」标示的商家即有机会获得代金券。</li>
                <li>「下单返券」需要在指定商家完成满足返券金额要求的订单后才会返还,代金券可在下次下单时使用。</li>
            </ul>
            <h3 id="q3-">Q3: 商家代金券使用条件</h3>
            <ul>
                <li>商家代金券仅限在指定商家使用</li>
                <li>商家代金券仅限在线支付使用</li>
                <li>每个订单只能使用一张商家代金券,不可与其他代金券叠加使用</li>
            </ul>
        </div>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState, mapMutations} from 'vuex'
    import {payRequest} from 'src/service/getData'
    import alertTip from 'src/components/common/alertTip'
    import loading from 'src/components/common/loading'

    export default {
      data(){
            return{
               
            }
        },
        components: {
            headTop,
        },
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .page{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        padding-top: 1.95rem;
        z-index: 203;
        background-color: #fff;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .markdown{
        @include sc(.6rem, #666);
        padding: 0 0.5rem 0.5rem;
        h3{
            line-height: 2rem;
        }
        p,li{
            @include sc(.6rem, #666);
            line-height: 1rem;
        }
    }
</style>


================================================
FILE: src/page/benefit/children/exchange.vue
================================================
 <template>
  <div class="page">
        <head-top head-title="兑换红包" go-back='true'></head-top>
        <form class="exchange_code">
            <input type="text" placeholder="请输入兑换码" v-model="exchangeCode" class="exchange_input">
            <section class="input_container captcha_code_container">
                <input type="text" placeholder="验证码" maxlength="4" v-model="codeNumber">
                <div class="img_change_img">
                    <img v-show="captchaCodeImg" :src="captchaCodeImg">
                    <div class="change_img" @click="getCaptchaCode">
                        <p>看不清</p>
                        <p>换一张</p>
                    </div>
                </div>
            </section>
        </form>
        <div class="determine" @click="exchange" :class="{active: status}">兑换</div>
        <alert-tip v-if="showAlert" @closeTip="showAlert = false" :alertText="alertText"></alert-tip>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState} from 'vuex'
    import {getcaptchas, exChangeHongbao} from 'src/service/getData'
    import alertTip from 'src/components/common/alertTip'

    export default {
      data(){
            return{
                showAlert: false,
                alertText: null,
                exchangeCode: null,
                codeNumber: '',
                captchaCodeImg: null,
            }
        },
        mounted(){
            this.getCaptchaCode();
        },
        components: {
            headTop,
            alertTip,
        },
        computed: {
            ...mapState([
                'userInfo',
            ]),
            status: function (){
                let status = (/^\d+$/gi.test(this.exchangeCode)) && (/^\w{4}$/gi.test(this.codeNumber))
                return status;
            }
        },
        methods: {
            //线上环境采用固定的图片,编译环境获取真实的验证码
            async getCaptchaCode(){
                let res = await getcaptchas();
                this.captchaCodeImg = res.code;
            },
            //兑换红包
            async exchange(){
                if (this.status) {
                    let res = await exChangeHongbao(this.userInfo.user_id, this.exchangeCode, this.codeNumber);
                    //不成功则弹出提示框
                    if (res.message) {
                        this.getCaptchaCode();
                        this.showAlert = true;
                        this.alertText = res.message;
                    }
                }
            }
        }
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .page{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        overflow-y: auto;
        padding-top: 1.95rem;
        z-index: 203;
        background-color: #f1f1f1;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .determine{
        background-color: #ccc;
        @include sc(.7rem, #fff);
        text-align: center;
        margin: 0 .7rem;
        line-height: 1.8rem;
        border-radius: 0.2rem;
        margin-top: 0.7rem;
    }
    .active{
        background-color: #4cd964;
    }
    .exchange_code{
        margin-top: 0.7rem;
        padding: 0 .5rem;
        .exchange_input{
            width: 100%;
            @include sc(.7rem, #666);
            padding: .6rem .4rem;
            border-radius: .15rem;
        }
    }
    .captcha_code_container{
        height: 2.2rem;
        display: flex;
        margin-top: .7rem;
        input{
            @include sc(.7rem, #666);
            padding: .4rem;
            border-radius: .15rem;
            flex: 3;
        }
        .img_change_img{
            display: flex;
            align-items: center;
            flex: 2;
            margin-left: .3rem;
            background-color: #fff;
            padding-left: .2rem;
            border-radius: .15rem;
            img{
                @include wh(3.5rem, 1.5rem);
                margin-right: .2rem;
            }
            .change_img{
                display: flex;
                flex-direction: 'column';
                flex-wrap: wrap;
                width: 2rem;
                justify-content: center;
                p{
                    @include sc(.55rem, #666);
                }
                p:nth-of-type(2){
                    color: #3b95e9;
                    margin-top: .2rem;
                }
            }
        }
    }
</style>


================================================
FILE: src/page/benefit/children/hbDescription.vue
================================================
 <template>
    <div class="page">
        <head-top head-title="红包说明" go-back='true'></head-top>
        <section id="scroll_section" class="scroll_container">
            <div class="markdown">
            <h3 id="q1-">Q1: 怎么获得红包?</h3>
            <ul>
                <li>通过邀请好友获得</li>
                <li>在下单返红包的商家下单获得</li>
                <li>抢微信朋友分享的红包获得</li>
            </ul>
            <h3 id="q2-">Q2: 红包可以做什么?</h3>
            <p>可以抵扣在线支付时的实际支付金额。</p>
            <h3 id="q3-">Q3: 红包的门槛金额按照什么金额计算?</h3>
            <p>红包的的门槛金额按照(选购菜品折后价+餐盒费)的金额作为计算门槛,即购物车显示的金额(7.3以上版本)。假设红包满30可用,只要选购的菜品现价(折后价)+餐盒费超过30,就可以使用红包。</p>
            <h3 id="q4-">Q4: 一个红包能拆开多次使用吗?</h3>
            <p>不能,一个红包只能一次性使用,不能分开使用。</p>
            <h3 id="q5-">Q5: 下单的时候使用了红包,但是后来订单取消了,红包还会返还吗?</h3>
            <p>会的,订单无效后红包会自动返还到您的账户里。</p>
            <h3 id="q6-">Q6: 红包兑换码怎样兑换成红包,怎样查看红包?</h3>
            <p>在个人中心 &gt; 我的红包 &gt; 兑换红包,输入兑换码进行兑换。</p>
            <h3 id="q7-">Q7: 邀请好友了,为什么没获得红包?</h3>
            <p>先检查下您是否在同一设备上进行的邀请?或者被邀请人是否通过您发给对方的链接进行注册?而非自己复制链接注册的。同一设备上邀请或没有按照点击发送的链接邀请都是无效邀请。如果您是正常邀请没获得红包,可以致电客服进行查实。</p>
            <h3 id="q8-">Q8: 预订早餐、预订午餐的红包怎么使用?在哪里查询?</h3>
            <ul>
                <li>预订早餐、预订午餐的红包暂时不支持直接点外卖使用,并且当前点外卖的红包也暂时不支持在预订早餐、预订午餐时使用。</li>
                <li>预订早餐、预订午餐的红包从APP首页点击“预订早餐”按钮进入后在右上角的个人中心中查找预订早餐、预订午餐的红包。</li>
            </ul>
            <h3 id="q9-">Q9: 互斥红包怎么使用?</h3>
            <ul>
                <li>互斥红包不与其他优惠活动(包含但不限于:新用户专享、满X元减X元、满X元赠XX)同时使用。</li>
            </ul>
            <h3 id="q10-">Q10: 返红包活动, 红包领取规则是什么?</h3>
            <ul>
                <li>同一个手机号一天限领取三个。</li>
                <li>同一注册用户一天限领取三个。</li>
                <li>注册用户红包直接发送至用户账户里。</li>
                <li>非注册用户红包以兑换码短信的形式发送至用户手机,注册后凭兑换码兑换即可。</li>
                <li>红包的使用周期为1周,自红包发放的第2天开始计算。</li>
                <li>同一个手机号一天最多使用两个红包。</li>
                <li>未收到红包短信的用户注意查看手机里的拦截短信。</li>
                <li>有任何问题请拨打客服电话:10105757。</li>
            </ul>
            </div>
        </section>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState, mapMutations} from 'vuex'
    import {payRequest} from 'src/service/getData'
    import alertTip from 'src/components/common/alertTip'
    import loading from 'src/components/common/loading'
    import BScroll from 'better-scroll'

    export default {
      data(){
            return{
               
            }
        },
        mounted(){
            this.$nextTick(() => {
                new BScroll('#scroll_section', {  
                    deceleration: 0.001,
                    bounce: true,
                    swipeTime: 1800,
                    click: true,
                }); 
            })
        },
        components: {
            headTop,
        },
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .page{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        padding-top: 1.95rem;
        z-index: 203;
        background-color: #fff;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .scroll_container{
        @include wh(100%, 100%);
    }
    .markdown{
        padding-bottom: 2rem;
        @include sc(.6rem, #666);
        padding: 0 0.5rem 0.5rem;
        h3{
            line-height: 2rem;
        }
        p,li{
            @include sc(.6rem, #666);
            line-height: 1rem;
        }
    }
</style>


================================================
FILE: src/page/benefit/children/hbHistory.vue
================================================
 <template>
  <div class="rating_page">
        <head-top head-title="历史红包" go-back='true'></head-top>
        <section v-if="!showLoading" id="scroll_section" class="scroll_container">
            <ul class="hongbao_list_ul">
                <li class="hongbao_list_li" v-for="item in expiredList" :key="item.id">
                    <section class="list_item">
                        <div class="list_item_left">
                            <span>¥</span>
                            <span>{{String(item.amount).split('.')[0]}}</span>
                            <span>.</span>
                            <span>{{String(item.amount).split('.')[1]||0}}</span>
                            <p>{{item.description_map.sum_condition}}</p>
                        </div>
                        <div class="list_item_right">
                            <h4>{{item.name}}</h4>
                            <p>{{item.description_map.validity_periods}}</p>
                            <p>{{item.description_map.phone}}</p>
                        </div>
                    </section>
                    <footer class="list_item_footer" v-if="item.limit_map">
                        <p>{{item.limit_map.restaurant_flavor_ids}}</p>
                    </footer>
                    <svg class="expired">
                        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#expired"></use>
                    </svg>
                </li>
            </ul>
        </section>
        <loading v-if="showLoading"></loading>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState, mapMutations} from 'vuex'
    import {getExpired} from 'src/service/getData'
    import loading from 'src/components/common/loading'
    import BScroll from 'better-scroll'
    
    export default {
      data(){
            return{
                showAlert: false,
                alertText: null,
                showLoading: true,
                expiredList: null, //历史红包列表
            }
        },
        mounted(){
            this.initData();
        },
        components: {
            headTop,
            loading,
        },
        computed: {
            ...mapState([
                'userInfo',
            ]),
        },
        methods: {
            ...mapMutations([
                'CLEAR_CART'
            ]),
            async initData(){
                //获取历史红包
                if (this.userInfo) {
                    this.expiredList = await getExpired(this.userInfo.user_id);
                    this.showLoading = false;
                    this.$nextTick(() => {
                        new BScroll('#scroll_section', {  
                            deceleration: 0.001,
                            bounce: true,
                            swipeTime: 1800,
                            click: true,
                        }); 
                    })
                }
            }
        },
        watch: {
            userInfo: function (value){
                this.initData();
            }
        }
    }
</script>
  
<style lang="scss" scoped>
    @import 'src/style/mixin';
  
    .rating_page{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        padding-top: 1.95rem;
        z-index: 203;
        background-color: #f1f1f1;
        p, span{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .scroll_container{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        padding-top: 1.95rem;
    }
    .hongbao_list_ul{
        padding: 1rem .5rem;
        .hongbao_list_li{
            background: #fff url(../../../images/expired.png) repeat-x ;
            background-size: .5rem .2rem;
            margin-bottom: 0.5rem;
            border-radius: 0.25rem;
            position: relative;
            .list_item{
                @include fj;
                padding: 1rem 0.5rem .8rem;
                .list_item_left{
                    font-size: 0;
                    border-right: 0.025rem dotted #ccc;
                    flex: 1;
                    span:nth-of-type(1){
                        @include sc(.75rem, #ccc);
                        font-weight: bold;
                    }
                    span:nth-of-type(2){
                        @include sc(2rem, #ccc);
                    }
                    span:nth-of-type(3), span:nth-of-type(4){
                        @include sc(1rem, #ccc);
                        font-weight: bold;
                    }
                    p{
                        @include sc(0.4rem, #999);
                    }
                }
                .list_item_right{
                    flex: 2;
                    margin-left: 1.5rem;
                    h4{
                        @include sc(.7rem, #666);
                        margin-left: -.7rem;
                    }
                    p{
                        list-style-type: disc;
                        margin-left: -.7rem;
                        @include sc(.4rem, #999);   
                    }
                }
            }
            .list_item_footer{
                background-color: #f9f9f9;
                padding: .4rem .4rem;
                border-bottom-left-radius: 0.25rem;
                border-bottom-right-radius: 0.25rem;
                p{
                    list-style-type: disc;
                    @include sc(.4rem, #999);
                    margin-left: .4rem;
                }
            }
            .expired{
                fill: #ddd;
                @include wh(3rem, 3rem);
                top: .6rem;
                right: .2rem;
                position: absolute;
            }
        }
    }
</style>


================================================
FILE: src/page/city/city.vue
================================================
<template>
  	<div class="city_container">
        <head-top :head-title="cityname" go-back='true'>
            <router-link to="/home" slot="changecity" class="change_city">切换城市</router-link>
        </head-top>
        <form class="city_form" v-on:submit.prevent>
            <div>
                <input type="search" name="city" placeholder="输入学校、商务楼、地址" class="city_input input_style" required v-model='inputVaule'>
            </div>
            <div>
                <input type="submit" name="submit" class="city_submit input_style" @click='postpois' value="提交">
            </div>
        </form>
        <header v-if="historytitle" class="pois_search_history">搜索历史</header>
        <ul class="getpois_ul">
            <li v-for="(item, index) in placelist" @click='nextpage(index, item.geohash)' :key="index">
                <h4 class="pois_name ellipsis">{{item.name}}</h4>
                <p class="pois_address ellipsis">{{item.address}}</p>
            </li>
        </ul>
        <footer v-if="historytitle&&placelist.length" class="clear_all_history" @click="clearAll">清空所有</footer>
        <div class="search_none_place" v-if="placeNone">很抱歉!无搜索结果</div>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {currentcity, searchplace} from 'src/service/getData'
    import {getStore, setStore, removeStore} from 'src/config/mUtils'

    export default {
    	data(){
            return{
                inputVaule:'', // 搜索地址
                cityid:'', // 当前城市id
                cityname:'', // 当前城市名字
                placelist:[], // 搜索城市列表
                placeHistory:[], // 历史搜索记录
                historytitle: true, // 默认显示搜索历史头部,点击搜索后隐藏
                placeNone: false, // 搜索无结果,显示提示信息
            }
        },

        mounted(){
            this.cityid = this.$route.params.cityid;
            //获取当前城市名字
            currentcity(this.cityid).then(res => {
                this.cityname = res.name;
            })
            this.initData();
        },

        components:{
            headTop
        },

        computed:{

        },

        methods:{
            initData(){
                //获取搜索历史记录
                if (getStore('placeHistory')) {
                    this.placelist = JSON.parse(getStore('placeHistory'));
                }else{
                    this.placelist = [];
                }
            },
            //发送搜索信息inputVaule
            postpois(){
                //输入值不为空时才发送信息
                if (this.inputVaule) {
                    searchplace(this.cityid, this.inputVaule).then(res => {
                        this.historytitle = false;
                        this.placelist = res;
                        this.placeNone = res.length? false : true;
                    })
                }
            },
            /**
             * 点击搜索结果进入下一页面时进行判断是否已经有一样的历史记录
             * 如果没有则新增,如果有则不做重复储存,判断完成后进入下一页
             */
            nextpage(index, geohash){
                let history = getStore('placeHistory');
                let choosePlace = this.placelist[index];
                if (history) {
                    let checkrepeat = false;
                    this.placeHistory = JSON.parse(history);
                    this.placeHistory.forEach(item => {
                        if (item.geohash == geohash) {
                            checkrepeat = true;
                        }
                    })
                    if (!checkrepeat) {
                        this.placeHistory.push(choosePlace)
                    }
                }else {
                    this.placeHistory.push(choosePlace)
                }
                setStore('placeHistory',this.placeHistory)
                this.$router.push({path:'/msite', query:{geohash}})
            },
            clearAll(){
                removeStore('placeHistory');
                this.initData();
            }
        }
    }

</script>

<style lang="scss" scoped>
    @import 'src/style/mixin';
    .city_container{
        padding-top: 2.35rem;
    }
    .change_city{
        right: 0.4rem;
        @include sc(0.6rem, #fff);
        @include ct;
    }
    .city_form{
        background-color: #fff;
        border-top: 1px solid $bc;
        border-bottom: 1px solid $bc;
        padding-top: 0.4rem;
        div{
            width: 90%;
            margin: 0 auto;
            text-align: center;
            .input_style{
                border-radius: 0.1rem;
                margin-bottom: 0.4rem;
                @include wh(100%, 1.4rem);
            }
            .city_input{
                border: 1px solid $bc;
                padding: 0 0.3rem;
                @include sc(0.65rem, #333);
            }
            .city_submit{
                background-color: $blue;
                @include sc(0.65rem, #fff);
            }
        }
    }
    .pois_search_history{
        border-top: 1px solid $bc;
        border-bottom: 1px solid $bc;
        padding-left: 0.5rem;
        @include font(0.475rem, 0.8rem);
    }
    .getpois_ul{
        background-color: #fff;
        border-top: 1px solid $bc;
        li{
            margin: 0 auto;
            padding-top: 0.65rem;
            border-bottom: 1px solid $bc;
            .pois_name{
                margin: 0 auto 0.35rem;
                width: 90%;
               @include sc(0.65rem, #333);
            }
            .pois_address{
                width: 90%;
                margin: 0 auto 0.55rem;
                @include sc(0.45rem, #999);
            }
        }
    }
    .search_none_place{
        margin: 0 auto;
        @include font(0.65rem, 1.75rem);
        color: #333;
        background-color: #fff;
        text-indent: 0.5rem;
    }
    .clear_all_history{
        @include sc(0.7rem, #666);
        text-align: center;
        line-height: 2rem;
        background-color: #fff;
    }
</style>


================================================
FILE: src/page/confirmOrder/children/children/addAddress.vue
================================================
 <template>
    <div class="address_page">
        <head-top head-title="添加地址" go-back='true'></head-top>
        <section class="page_text_container">
            <section class="section_list">
                <span class="section_left">联系人</span>
                <section class="section_right">
                    <input type="text" name="name" placeholder="你的名字" v-model="name" class="input_style">
                    <div class="choose_sex">
                        <span class="choose_option">
                            <svg class="address_empty_right" @click="chooseSex(1)" :class="{choosed: sex == 1}">
                                <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#select"></use>
                            </svg>
                            <span>先生</span>
                        </span>
                        <span class="choose_option">
                            <svg class="address_empty_right" @click="chooseSex(2)" :class="{choosed: sex == 2}">
                                <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#select"></use>
                            </svg>
                            <span>女士</span>
                        </span>
                    </div>
                </section>
            </section>
            <section class="section_list">
                <span class="section_left">联系电话</span>
                <section class="section_right">
                    <div class="phone_add">
                        <input type="text" name="phone" placeholder="你的手机号" v-model="phone" class="input_style">
                        <img src="../../../../images/add_phone.png" height="20" width="20" @click="phone_bk = true">
                    </div>
                    <input v-if="phone_bk" type="text" name="anntherPhoneNumber" placeholder="备选电话" v-model="anntherPhoneNumber" class="input_style phone_bk">
                </section>
            </section>
            <section class="section_list">
                <span class="section_left">送餐地址</span>
                <section class="section_right">
                    <router-link to="/confirmOrder/chooseAddress/addAddress/searchAddress" tag="div" class="choose_address">{{searchAddress? searchAddress.name : '小区/写字楼/学校等'}}</router-link>
                    <input type="text" name="address_detail" placeholder="详细地址(如门牌号等)" v-model="address_detail" class="input_style">

                </section>
            </section>
            <section class="section_list">
                <span class="section_left">标签</span>
                <section class="section_right">
                    <input type="text" name="tag" placeholder="无/家/学校/公司" v-model="tag" class="input_style">
                </section>
            </section>
        </section>
        <div class="determine" @click="addAddress">确定</div>
        <alert-tip v-if="showAlert" @closeTip="showAlert = false" :alertText="alertText"></alert-tip>
        <transition name="router-slid" mode="out-in">
            <router-view></router-view>
        </transition>
    </div>
</template>

<script>
    import headTop from 'src/components/header/head'
    import {mapState, mapMutations} from 'vuex'
    import {getAddress, getUser, postAddAddress} from 'src/service/getData'
    import alertTip from 'src/components/common/alertTip'

    export default {
      data(){
            return{
                name: null, //姓名
                sex: 1, //性别
                phone: null, //电话
                address_detail: null, //详细地址
                tag: '', //备注
                tag_type: 1, //备注类型
                phone_bk: false, //是否选择备注电话
                anntherPhoneNumber: '', //备注电话
                showAlert: false, //弹出框
                alertText: null, //弹出框信息
                poi_type: 0, //地址类型
            }
        },
        created(){

        },
        components: {
            headTop,
            alertTip,
        },
        computed: {
            ...mapState([
                'searchAddress', 'geohash', 'userInfo',
            ]),
        },
        methods: {
            ...mapMutations([
                'CONFIRM_ADDRESS'
            ]),
            //选择性别
            chooseSex(sex){
                this.sex = sex;
            },
            //保存地址信息
            async addAddress(){
                if (!(this.userInfo && this.userInfo.user_id)) {
                    this.showAlert = true;
                    this.alertText = '请登录'
                }else if(!this.name){
                    this.showAlert = true;
                    this.alertText = '请输入姓名'
                }else if(!this.phone){
                    this.showAlert = true;
                    this.alertText = '请输入电话号码'
                }else if(!this.searchAddress){
                    this.showAlert = true;
                    this.alertText = '请选择地址'
                }else if(!this.address_detail){
                    this.showAlert = true;
                    this.alertText = '请输入详细地址'
                }
                if (this.tag == '家') {
                    this.tag_type = 2;
                }else if(this.tag == '学校'){
                    this.tag_type = 3;
                }else if(this.tag == '公司'){
                    this.tag_type = 4;
                }
                let res = await postAddAddress(this.userInfo.user_id, this.searchAddress.name, this.address_detail, this.geohash, this.name, this.phone, this.anntherPhoneNumber, 0, this.sex, this.tag, this.tag_type);
                //保存成功返沪上一页,否则弹出提示框
                if (res.message) {
                    this.showAlert = true;
                    this.alertText = res.message;
                }else {
                    this.CONFIRM_ADDRESS(1);
                    this.$router.go(-1);
                }
            },
        }
    }
</script>

<style lang="scss" scoped>
    @import 'src/style/mixin';

    .address_page{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #f5f5f5;
        z-index: 204;
        padding-top: 1.95rem;
        p, span, input{
            font-family: Helvetica Neue,Tahoma,Arial;
        }
    }
    .page_text_container{
        background-color: #fff;
        padding: 0 .7rem;
    }
    .section_list{
        display: flex;
        border-bottom: 0.025rem solid #f5f5f5;
    
Download .txt
gitextract_552txq2t/

├── .babelrc
├── .editorconfig
├── .github/
│   └── workflows/
│       └── close_inactive_issue.yml
├── .gitignore
├── COPYING
├── README-en.md
├── README.md
├── build/
│   ├── build.js
│   ├── dev-client.js
│   ├── dev-server.js
│   ├── utils.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config/
│   └── index.js
├── index.html
├── package.json
└── src/
    ├── App.vue
    ├── components/
    │   ├── common/
    │   │   ├── alertTip.vue
    │   │   ├── buyCart.vue
    │   │   ├── computeTime.vue
    │   │   ├── loading.vue
    │   │   ├── mixin.js
    │   │   ├── ratingStar.vue
    │   │   ├── shoplist.vue
    │   │   └── svg.vue
    │   ├── footer/
    │   │   └── footGuide.vue
    │   └── header/
    │       └── head.vue
    ├── config/
    │   ├── env.js
    │   ├── fetch.js
    │   ├── mUtils.js
    │   └── rem.js
    ├── main.js
    ├── page/
    │   ├── balance/
    │   │   ├── balance.vue
    │   │   └── children/
    │   │       └── detail.vue
    │   ├── benefit/
    │   │   ├── benefit.vue
    │   │   └── children/
    │   │       ├── commend.vue
    │   │       ├── coupon.vue
    │   │       ├── exchange.vue
    │   │       ├── hbDescription.vue
    │   │       └── hbHistory.vue
    │   ├── city/
    │   │   └── city.vue
    │   ├── confirmOrder/
    │   │   ├── children/
    │   │   │   ├── children/
    │   │   │   │   ├── addAddress.vue
    │   │   │   │   └── children/
    │   │   │   │       └── searchAddress.vue
    │   │   │   ├── chooseAddress.vue
    │   │   │   ├── invoice.vue
    │   │   │   ├── payment.vue
    │   │   │   ├── remark.vue
    │   │   │   └── userValidation.vue
    │   │   └── confirmOrder.vue
    │   ├── download/
    │   │   └── download.vue
    │   ├── find/
    │   │   └── find.vue
    │   ├── food/
    │   │   └── food.vue
    │   ├── forget/
    │   │   └── forget.vue
    │   ├── home/
    │   │   └── home.vue
    │   ├── login/
    │   │   └── login.vue
    │   ├── msite/
    │   │   └── msite.vue
    │   ├── order/
    │   │   ├── children/
    │   │   │   └── orderDetail.vue
    │   │   └── order.vue
    │   ├── points/
    │   │   ├── children/
    │   │   │   └── detail.vue
    │   │   └── points.vue
    │   ├── profile/
    │   │   ├── children/
    │   │   │   ├── children/
    │   │   │   │   ├── address.vue
    │   │   │   │   ├── children/
    │   │   │   │   │   ├── add.vue
    │   │   │   │   │   └── children/
    │   │   │   │   │       └── addDetail.vue
    │   │   │   │   └── setusername.vue
    │   │   │   └── info.vue
    │   │   └── profile.vue
    │   ├── search/
    │   │   └── search.vue
    │   ├── service/
    │   │   ├── children/
    │   │   │   └── questionDetail.vue
    │   │   └── service.vue
    │   ├── shop/
    │   │   ├── children/
    │   │   │   ├── children/
    │   │   │   │   └── shopSafe.vue
    │   │   │   ├── foodDetail.vue
    │   │   │   └── shopDetail.vue
    │   │   └── shop.vue
    │   └── vipcard/
    │       ├── children/
    │       │   ├── invoiceRecord.vue
    │       │   ├── useCart.vue
    │       │   └── vipDescription.vue
    │       └── vipcard.vue
    ├── router/
    │   └── router.js
    ├── service/
    │   └── getData.js
    ├── store/
    │   ├── action.js
    │   ├── getters.js
    │   ├── index.js
    │   ├── mutation-types.js
    │   └── mutations.js
    └── style/
        ├── common.scss
        └── mixin.scss
Download .txt
SYMBOL INDEX (63 symbols across 6 files)

FILE: build/utils.js
  function generateLoaders (line 13) | function generateLoaders(loaders) {

FILE: src/components/common/mixin.js
  method getImgPath (line 72) | getImgPath(path) {

FILE: src/main.js
  method scrollBehavior (line 13) | scrollBehavior (to, from, savedPosition) {

FILE: src/store/action.js
  method getUserInfo (line 12) | async getUserInfo({
  method saveAddress (line 19) | async saveAddress({

FILE: src/store/mutation-types.js
  constant RECORD_ADDRESS (line 1) | const RECORD_ADDRESS = 'RECORD_ADDRESS'
  constant ADD_CART (line 2) | const ADD_CART = 'ADD_CART'
  constant REDUCE_CART (line 3) | const REDUCE_CART = 'REDUCE_CART'
  constant INIT_BUYCART (line 4) | const INIT_BUYCART = 'INIT_BUYCART'
  constant CLEAR_CART (line 5) | const CLEAR_CART = 'CLEAR_CART'
  constant RECORD_SHOPDETAIL (line 6) | const RECORD_SHOPDETAIL = 'RECORD_SHOPDETAIL'
  constant RECORD_USERINFO (line 7) | const RECORD_USERINFO = 'RECORD_USERINFO'
  constant GET_USERINFO (line 8) | const GET_USERINFO = 'GET_USERINFO'
  constant CONFIRM_REMARK (line 9) | const CONFIRM_REMARK = 'CONFIRM_REMARK'
  constant CONFIRM_INVOICE (line 10) | const CONFIRM_INVOICE = 'CONFIRM_INVOICE'
  constant CHOOSE_SEARCH_ADDRESS (line 11) | const CHOOSE_SEARCH_ADDRESS = 'CHOOSE_SEARCH_ADDRESS'
  constant SAVE_GEOHASH (line 12) | const SAVE_GEOHASH = 'SAVE_GEOHASH'
  constant CONFIRM_ADDRESS (line 13) | const CONFIRM_ADDRESS = 'CONFIRM_ADDRESS'
  constant CHOOSE_ADDRESS (line 14) | const CHOOSE_ADDRESS = 'CHOOSE_ADDRESS'
  constant NEED_VALIDATION (line 15) | const NEED_VALIDATION = 'NEED_VALIDATION'
  constant SAVE_CART_ID_SIG (line 16) | const SAVE_CART_ID_SIG = 'SAVE_CART_ID_SIG'
  constant SAVE_ORDER_PARAM (line 17) | const SAVE_ORDER_PARAM = 'SAVE_ORDER_PARAM'
  constant CHANGE_ORDER_PARAM (line 18) | const CHANGE_ORDER_PARAM = 'CHANGE_ORDER_PARAM'
  constant ORDER_SUCCESS (line 19) | const ORDER_SUCCESS = 'ORDER_SUCCESS'
  constant SAVE_SHOPID (line 20) | const SAVE_SHOPID = 'SAVE_SHOPID'
  constant SAVE_ORDER (line 21) | const SAVE_ORDER = 'SAVE_ORDER'
  constant OUT_LOGIN (line 22) | const OUT_LOGIN = 'OUT_LOGIN'
  constant RETSET_NAME (line 23) | const RETSET_NAME = 'RETSET_NAME'
  constant SAVE_AVANDER (line 24) | const SAVE_AVANDER = 'SAVE_AVANDER'
  constant SAVE_ADDDETAIL (line 25) | const SAVE_ADDDETAIL = 'SAVE_ADDDETAIL'
  constant SAVE_ADDRESS (line 26) | const SAVE_ADDRESS = 'SAVE_ADDRESS'
  constant SAVE_QUESTION (line 27) | const SAVE_QUESTION = 'SAVE_QUESTION'
  constant ADD_ADDRESS (line 28) | const ADD_ADDRESS = 'ADD_ADDRESS'
  constant BUY_CART (line 29) | const BUY_CART = 'BUY_CART'

FILE: src/store/mutations.js
  method [RECORD_ADDRESS] (line 39) | [RECORD_ADDRESS](state, {
  method [RECORD_SHOPDETAIL] (line 47) | [RECORD_SHOPDETAIL](state, detail) {
  method [ADD_CART] (line 51) | [ADD_CART](state, {
  method [REDUCE_CART] (line 86) | [REDUCE_CART](state, {
  method [INIT_BUYCART] (line 112) | [INIT_BUYCART](state) {
  method [CLEAR_CART] (line 119) | [CLEAR_CART](state, shopid) {
  method [RECORD_USERINFO] (line 125) | [RECORD_USERINFO](state, info) {
  method [GET_USERINFO] (line 131) | [GET_USERINFO](state, info) {
  method [RETSET_NAME] (line 145) | [RETSET_NAME](state,username) {
  method [SAVE_SHOPID] (line 149) | [SAVE_SHOPID](state, shopid) {
  method [CONFIRM_REMARK] (line 153) | [CONFIRM_REMARK](state, {
  method [CONFIRM_INVOICE] (line 161) | [CONFIRM_INVOICE](state, invoice) {
  method [CHOOSE_SEARCH_ADDRESS] (line 165) | [CHOOSE_SEARCH_ADDRESS](state, place) {
  method [SAVE_GEOHASH] (line 169) | [SAVE_GEOHASH](state, geohash) {
  method [CONFIRM_ADDRESS] (line 174) | [CONFIRM_ADDRESS](state, newAddress) {
  method [CHOOSE_ADDRESS] (line 178) | [CHOOSE_ADDRESS](state, {
  method [NEED_VALIDATION] (line 186) | [NEED_VALIDATION](state, needValidation) {
  method [SAVE_CART_ID_SIG] (line 190) | [SAVE_CART_ID_SIG](state, {
  method [SAVE_ORDER_PARAM] (line 198) | [SAVE_ORDER_PARAM](state, orderParam) {
  method [CHANGE_ORDER_PARAM] (line 202) | [CHANGE_ORDER_PARAM](state, newParam) {
  method [ORDER_SUCCESS] (line 206) | [ORDER_SUCCESS](state, order) {
  method [SAVE_ORDER] (line 211) | [SAVE_ORDER](state, orderDetail) {
  method [OUT_LOGIN] (line 215) | [OUT_LOGIN](state) {
  method [SAVE_AVANDER] (line 220) | [SAVE_AVANDER](state, imgPath) {
  method [SAVE_ADDRESS] (line 224) | [SAVE_ADDRESS](state, newAdress) {
  method [SAVE_ADDDETAIL] (line 228) | [SAVE_ADDDETAIL](state, addAddress){
  method [SAVE_QUESTION] (line 232) | [SAVE_QUESTION](state, question) {
  method [ADD_ADDRESS] (line 236) | [ADD_ADDRESS](state, obj) {
  method [BUY_CART] (line 240) | [BUY_CART](state, price) {
Condensed preview — 87 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (551K chars).
[
  {
    "path": ".babelrc",
    "chars": 97,
    "preview": "{\n  \"presets\": [\"es2015\", \"stage-2\"],\n  \"plugins\": [\"transform-runtime\"],\n  \"comments\": false,\n}\n"
  },
  {
    "path": ".editorconfig",
    "chars": 146,
    "preview": "root = true\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_t"
  },
  {
    "path": ".github/workflows/close_inactive_issue.yml",
    "chars": 565,
    "preview": "name: Close Inactive Issue\n\non:\n  schedule:\n    - cron: \"0 0 * * *\"\n\njobs:\n  close-issues:\n    runs-on: ubuntu-latest\n  "
  },
  {
    "path": ".gitignore",
    "chars": 143,
    "preview": ".DS_Store\nnode_modules/\nnpm-debug.log\npackage-lock.json\n# 忽略使用WebStorm开发时,生成的缓存文件夹\n.idea\n# 忽略使用VSCode开发时,生成的缓存文件夹\n.vscod"
  },
  {
    "path": "COPYING",
    "chars": 18029,
    "preview": "\n          GNU GENERAL PUBLIC LICENSE\n            Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundati"
  },
  {
    "path": "README-en.md",
    "chars": 16148,
    "preview": "# Introduction\n\n[README in Chinese](README.md)\n\nWhen I began to learn to vue, search of some practical source code about"
  },
  {
    "path": "README.md",
    "chars": 10873,
    "preview": "# 前言\n\n[README in English](README-en.md)\n\n初学vue时曾在网上搜索vue的实战项目源码,无奈大部分都是简单的demo,对于深究vue没有太大的帮助,剩下的一些大部分都是像音乐播放器之类的展示型项目,交"
  },
  {
    "path": "build/build.js",
    "chars": 763,
    "preview": "// https://github.com/shelljs/shelljs\nrequire('shelljs/global')\nenv.NODE_ENV = 'production'\n\nvar path = require('path')\n"
  },
  {
    "path": "build/dev-client.js",
    "chars": 239,
    "preview": "/* eslint-disable */\nrequire('eventsource-polyfill')\nvar hotClient = require('webpack-hot-middleware/client?noInfo=true&"
  },
  {
    "path": "build/dev-server.js",
    "chars": 2307,
    "preview": "var config = require('../config')\nif (!process.env.NODE_ENV) process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)\n"
  },
  {
    "path": "build/utils.js",
    "chars": 2070,
    "preview": "var path = require('path')\nvar config = require('../config')\nvar ExtractTextPlugin = require('extract-text-webpack-plugi"
  },
  {
    "path": "build/webpack.base.conf.js",
    "chars": 2388,
    "preview": "var path = require('path')\nvar config = require('../config')\nvar utils = require('./utils')\nvar projectRoot = path.resol"
  },
  {
    "path": "build/webpack.dev.conf.js",
    "chars": 1275,
    "preview": "var config = require('../config')\nvar webpack = require('webpack')\nvar merge = require('webpack-merge')\nvar utils = requ"
  },
  {
    "path": "build/webpack.prod.conf.js",
    "chars": 3572,
    "preview": "var path = require('path')\nvar config = require('../config')\nvar utils = require('./utils')\nvar webpack = require('webpa"
  },
  {
    "path": "config/index.js",
    "chars": 1545,
    "preview": "// see http://vuejs-templates.github.io/webpack for documentation.\nvar path = require('path')\n\nmodule.exports = {\n    bu"
  },
  {
    "path": "index.html",
    "chars": 696,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initia"
  },
  {
    "path": "package.json",
    "chars": 1980,
    "preview": "{\n  \"name\": \"elm\",\n  \"version\": \"2.0.1\",\n  \"description\": \"vue2-elm\",\n  \"author\": \"cangdu <1264889788@qq.com>\",\n  \"priva"
  },
  {
    "path": "src/App.vue",
    "chars": 716,
    "preview": "<template>\n\t<div>\n\t\t<transition name=\"router-fade\" mode=\"out-in\">\n\t\t\t<keep-alive>\n\t\t\t    <router-view v-if=\"$route.meta."
  },
  {
    "path": "src/components/common/alertTip.vue",
    "chars": 2762,
    "preview": " <template>\n    <div class=\"alet_container\">\n\t    <section class=\"tip_text_container\">\n            <div class=\"tip_icon\""
  },
  {
    "path": "src/components/common/buyCart.vue",
    "chars": 5938,
    "preview": " <template>\n    <section class=\"cart_module\">\n        <section v-if=\"!foods.specifications.length\" class=\"cart_button\">\n"
  },
  {
    "path": "src/components/common/computeTime.vue",
    "chars": 2450,
    "preview": " <template>\n    <div class=\"page\">\n        <span class=\"rem_time\" style=\"color: orange;border-width: 1px;border-style: s"
  },
  {
    "path": "src/components/common/loading.vue",
    "chars": 1614,
    "preview": " <template>\n\t<div class=\"loading_container\">\n\t    <div class=\"load_img\" :style=\"{backgroundPositionY: -(positionY%7)*2.5"
  },
  {
    "path": "src/components/common/mixin.js",
    "chars": 2051,
    "preview": "import { getStyle } from '../../config/mUtils'\nimport { imgBaseUrl, localapi, proapi } from '../../config/env'\n\nexport c"
  },
  {
    "path": "src/components/common/ratingStar.vue",
    "chars": 1476,
    "preview": " <template>\n\t<div class=\"rating_container\">\n        <section class=\"star_container\">\n            <svg class=\"grey_fill\" "
  },
  {
    "path": "src/components/common/shoplist.vue",
    "chars": 8463,
    "preview": "<template>\n\t<div class=\"shoplist_container\">\n\t\t<ul v-load-more=\"loaderMore\" v-if=\"shopListArr.length\" type=\"1\">\n\t\t\t<rout"
  },
  {
    "path": "src/components/common/svg.vue",
    "chars": 33310,
    "preview": "<template>\n\t<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"position:absolute;"
  },
  {
    "path": "src/components/footer/footGuide.vue",
    "chars": 10148,
    "preview": "<template>\n    <section id='foot_guide'>\n    \t<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/199"
  },
  {
    "path": "src/components/header/head.vue",
    "chars": 2461,
    "preview": "<template>\n    <header id='head_top'>\n        <slot name='logo'></slot>\n        <slot name='search'></slot>\n        <sec"
  },
  {
    "path": "src/config/env.js",
    "chars": 407,
    "preview": "/**\n * 配置编译环境和线上环境之间的切换\n * \n * baseUrl: 域名地址\n * routerMode: 路由模式\n * imgBaseUrl: 图片所在域名地址\n * \n */\n\nlet baseUrl = ''; \nlet"
  },
  {
    "path": "src/config/fetch.js",
    "chars": 1726,
    "preview": "import {\n\tbaseUrl\n} from './env'\n\nexport default async(url = '', data = {}, type = 'GET', method = 'fetch') => {\n\ttype ="
  },
  {
    "path": "src/config/mUtils.js",
    "chars": 7974,
    "preview": "/**\n * 存储localStorage\n */\nexport const setStore = (name, content) => {\n\tif (!name) return;\n\tif (typeof content !== 'stri"
  },
  {
    "path": "src/config/rem.js",
    "chars": 523,
    "preview": "(function(doc, win) {\r\n    var docEl = doc.documentElement,\r\n        resizeEvt = 'orientationchange' in window ? 'orient"
  },
  {
    "path": "src/main.js",
    "chars": 620,
    "preview": "import Vue from 'vue'\nimport VueRouter from 'vue-router'\nimport routes from './router/router'\nimport store from './store"
  },
  {
    "path": "src/page/balance/balance.vue",
    "chars": 3947,
    "preview": " <template>\r\n  <div class=\"page\">\r\n        <head-top head-title=\"我的余额\" go-back='true'></head-top>\r\n        <section clas"
  },
  {
    "path": "src/page/balance/children/detail.vue",
    "chars": 1669,
    "preview": " <template>\n    <div class=\"page\">\n        <head-top head-title=\"余额问题\" go-back='true'></head-top>\n        <div class=\"ma"
  },
  {
    "path": "src/page/benefit/benefit.vue",
    "chars": 11635,
    "preview": " <template>\r\n  <div class=\"rating_page\">\r\n        <head-top head-title=\"我的优惠\" go-back='true'></head-top>\r\n        <secti"
  },
  {
    "path": "src/page/benefit/children/commend.vue",
    "chars": 3831,
    "preview": " <template>\n  <div class=\"page\">\n        <head-top head-title=\"推荐有奖\" go-back='true'></head-top>\n        <section class=\""
  },
  {
    "path": "src/page/benefit/children/coupon.vue",
    "chars": 1719,
    "preview": " <template>\n  <div class=\"page\">\n        <head-top head-title=\"代金券说明\" go-back='true'></head-top>\n        <div class=\"mar"
  },
  {
    "path": "src/page/benefit/children/exchange.vue",
    "chars": 4501,
    "preview": " <template>\n  <div class=\"page\">\n        <head-top head-title=\"兑换红包\" go-back='true'></head-top>\n        <form class=\"exc"
  },
  {
    "path": "src/page/benefit/children/hbDescription.vue",
    "chars": 3501,
    "preview": " <template>\n    <div class=\"page\">\n        <head-top head-title=\"红包说明\" go-back='true'></head-top>\n        <section id=\"s"
  },
  {
    "path": "src/page/benefit/children/hbHistory.vue",
    "chars": 5791,
    "preview": " <template>\n  <div class=\"rating_page\">\n        <head-top head-title=\"历史红包\" go-back='true'></head-top>\n        <section "
  },
  {
    "path": "src/page/city/city.vue",
    "chars": 5899,
    "preview": "<template>\n  \t<div class=\"city_container\">\n        <head-top :head-title=\"cityname\" go-back='true'>\n            <router-"
  },
  {
    "path": "src/page/confirmOrder/children/children/addAddress.vue",
    "chars": 8158,
    "preview": " <template>\n    <div class=\"address_page\">\n        <head-top head-title=\"添加地址\" go-back='true'></head-top>\n        <secti"
  },
  {
    "path": "src/page/confirmOrder/children/children/children/searchAddress.vue",
    "chars": 3133,
    "preview": " <template>\n    <div class=\"search_address_page\">\n        <section>\n            <head-top head-title=\"搜索\" go-back='true'"
  },
  {
    "path": "src/page/confirmOrder/children/chooseAddress.vue",
    "chars": 8640,
    "preview": " <template>\n    <div class=\"rating_page\">\n        <head-top head-title=\"选择地址\" go-back='true'></head-top>\n        <router"
  },
  {
    "path": "src/page/confirmOrder/children/invoice.vue",
    "chars": 2028,
    "preview": " <template>\n    <div class=\"rating_page\">\n        <head-top head-title=\"选择发票抬头\" go-back='true'></head-top>\n        <sect"
  },
  {
    "path": "src/page/confirmOrder/children/payment.vue",
    "chars": 7129,
    "preview": " <template>\n    <div class=\"rating_page\">\n        <head-top head-title=\"在线支付\" go-back='true'></head-top>\n        <sectio"
  },
  {
    "path": "src/page/confirmOrder/children/remark.vue",
    "chars": 4714,
    "preview": " <template>\n    <div class=\"rating_page\">\n        <section v-if=\"!showLoading\">\n            <head-top head-title=\"订单备注\" "
  },
  {
    "path": "src/page/confirmOrder/children/userValidation.vue",
    "chars": 5685,
    "preview": " <template>\n    <div class=\"validation_page\">\n        <head-top head-title=\"用户手机验证\" go-back='true'></head-top>\n        <"
  },
  {
    "path": "src/page/confirmOrder/confirmOrder.vue",
    "chars": 20696,
    "preview": "<template>\n    <div class=\"confirmOrderContainer\">\n        <section v-if=\"!showLoading\">\n            <head-top head-titl"
  },
  {
    "path": "src/page/download/download.vue",
    "chars": 2876,
    "preview": " <template>\n  <div class=\"download_page\">\n        <head-top head-title=\"下载\" go-back='true'></head-top>\n        <section "
  },
  {
    "path": "src/page/find/find.vue",
    "chars": 1037,
    "preview": " <template>\n    <div class=\"rating_page\">\n        <head-top head-title=\"发现\" go-back='true'></head-top>\n        <section>"
  },
  {
    "path": "src/page/food/food.vue",
    "chars": 18629,
    "preview": "<template>\n    <div class=\"food_container\">\n    \t<head-top :head-title=\"headTitle\" goBack=\"true\"></head-top>\n    \t<secti"
  },
  {
    "path": "src/page/forget/forget.vue",
    "chars": 8842,
    "preview": "<template>\n    <div class=\"restContainer\">\n        <head-top head-title=\"重置密码\" goBack=\"true\"></head-top>\n        <form c"
  },
  {
    "path": "src/page/home/home.vue",
    "chars": 5108,
    "preview": "<template>\n  \t<div>\n        <head-top signin-up='home'>\n            <span slot='logo' class=\"head_logo\"  @click=\"reload\""
  },
  {
    "path": "src/page/login/login.vue",
    "chars": 10962,
    "preview": "<template>\n    <div class=\"loginContainer\">\n        <head-top :head-title=\"loginWay? '登录':'密码登录'\" goBack=\"true\">\n       "
  },
  {
    "path": "src/page/msite/msite.vue",
    "chars": 5425,
    "preview": "<template>\n    <div>\n    \t<head-top signin-up='msite'>\n    \t\t<router-link :to=\"'/search/geohash'\" class=\"link_search\" sl"
  },
  {
    "path": "src/page/order/children/orderDetail.vue",
    "chars": 9836,
    "preview": " <template>\n  <div class=\"order_detail_page\">\n        <head-top head-title=\"订单详情\" go-back='true'></head-top>\n        <se"
  },
  {
    "path": "src/page/order/order.vue",
    "chars": 8092,
    "preview": " <template>\n    <div class=\"order_page\">\n        <head-top head-title=\"订单列表\" go-back='true'></head-top>\n        <ul clas"
  },
  {
    "path": "src/page/points/children/detail.vue",
    "chars": 1855,
    "preview": " <template>\n    <div class=\"page\">\n        <head-top head-title=\"积分问题\" go-back='true'></head-top>\n        <div class=\"ma"
  },
  {
    "path": "src/page/points/points.vue",
    "chars": 4197,
    "preview": " <template>\r\n  <div class=\"page\">\r\n        <head-top head-title=\"我的积分\" go-back='true'></head-top>\r\n        <section clas"
  },
  {
    "path": "src/page/profile/children/children/address.vue",
    "chars": 4584,
    "preview": " <template>\n  \t<div class=\"rating_page\">\n        <head-top head-title=\"编辑地址\" go-back='true'>\n        \t<span slot=\"edit\" "
  },
  {
    "path": "src/page/profile/children/children/children/add.vue",
    "chars": 7182,
    "preview": " <template>\n  <div class=\"rating_page\">\n        <head-top head-title=\"新增地址\" go-back='true'></head-top>\n        <section "
  },
  {
    "path": "src/page/profile/children/children/children/children/addDetail.vue",
    "chars": 4026,
    "preview": " <template>\n  \t<div class=\"rating_page\">\n        <head-top head-title=\"搜索地址\" go-back='true'></head-top>\n        <section"
  },
  {
    "path": "src/page/profile/children/children/setusername.vue",
    "chars": 3870,
    "preview": " <template>\n    <div class=\"rating_page\">\n        <head-top head-title=\"修改用户名\" go-back='true'></head-top>\n        <secti"
  },
  {
    "path": "src/page/profile/children/info.vue",
    "chars": 15650,
    "preview": " <template>\n    <div class=\"rating_page\">\n        <head-top head-title=\"账户信息\" go-back='true'></head-top>\n        <sectio"
  },
  {
    "path": "src/page/profile/profile.vue",
    "chars": 13730,
    "preview": "<template>\r\n    <div class=\"profile_page\">\r\n        <head-top go-back='true' :head-title=\"profiletitle\"></head-top>\r\n   "
  },
  {
    "path": "src/page/search/search.vue",
    "chars": 9672,
    "preview": "<template>\n  \t<div class=\"paddingTop search_page\">\n        <head-top head-title=\"搜索\" goBack=\"true\"></head-top>\n        <"
  },
  {
    "path": "src/page/service/children/questionDetail.vue",
    "chars": 1921,
    "preview": " <template>\n  <div class=\"detail_page\">\n        <head-top :head-title=\"question.title\" go-back='true'></head-top>\n      "
  },
  {
    "path": "src/page/service/service.vue",
    "chars": 4788,
    "preview": " <template>\r\n  <div class=\"rating_page\">\r\n        <head-top head-title=\"服务中心\" go-back='true'></head-top>\r\n        <secti"
  },
  {
    "path": "src/page/shop/children/children/shopSafe.vue",
    "chars": 7653,
    "preview": " <template>\n\t<div class=\"safe_shop\">\n        <head-top head-title=\"食品监督安全公示\" go-back='true'></head-top>\n        <section"
  },
  {
    "path": "src/page/shop/children/foodDetail.vue",
    "chars": 4706,
    "preview": " <template>\n\t<div class=\"rating_page\">\n        <head-top :head-title=\"name\" go-back='true'></head-top>\n        <section "
  },
  {
    "path": "src/page/shop/children/shopDetail.vue",
    "chars": 8135,
    "preview": " <template>\n\t<div class=\"rating_page\">\n        <head-top head-title=\"商家详情\" go-back='true'></head-top>\n        <section c"
  },
  {
    "path": "src/page/shop/shop.vue",
    "chars": 65983,
    "preview": " <template>\n    <div>\n        <section v-if=\"!showLoading\" class=\"shop_container\">\n            <nav class=\"goback\" @clic"
  },
  {
    "path": "src/page/vipcard/children/invoiceRecord.vue",
    "chars": 1523,
    "preview": " <template>\n  <div class=\"page_container\">\n        <head-top head-title=\"购买记录\" go-back='true'></head-top>\n        <!-- 没"
  },
  {
    "path": "src/page/vipcard/children/useCart.vue",
    "chars": 3501,
    "preview": " <template>\n  <div class=\"page_container\">\n        <head-top head-title=\"兑换会员\" go-back='true'></head-top>\n        <p cla"
  },
  {
    "path": "src/page/vipcard/children/vipDescription.vue",
    "chars": 2635,
    "preview": " <template>\n  <div class=\"page_container\">\n        <head-top head-title=\"我的优惠\" go-back='true'></head-top>\n        <div c"
  },
  {
    "path": "src/page/vipcard/vipcard.vue",
    "chars": 6668,
    "preview": " <template>\n  <div class=\"rating_page\">\n        <head-top head-title=\"会员中心\" go-back='true'></head-top>\n        <section "
  },
  {
    "path": "src/router/router.js",
    "chars": 10105,
    "preview": "import App from '../App'\n\nconst home = r => require.ensure([], () => r(require('../page/home/home')), 'home')\nconst city"
  },
  {
    "path": "src/service/getData.js",
    "chars": 7478,
    "preview": "import fetch from '../config/fetch'\nimport {getStore} from '../config/mUtils'\n\n/**\n * 获取首页默认地址\n */\n\nexport const cityGue"
  },
  {
    "path": "src/store/action.js",
    "chars": 446,
    "preview": "import {\n\tgetUser,\n\tgetAddressList\n} from '../service/getData'\nimport {\n\tGET_USERINFO,\n\tSAVE_ADDRESS\n} from './mutation-"
  },
  {
    "path": "src/store/getters.js",
    "chars": 20,
    "preview": "export default {\n\t\n}"
  },
  {
    "path": "src/store/index.js",
    "chars": 947,
    "preview": "import Vue from 'vue'\nimport Vuex from 'vuex'\nimport mutations from './mutations'\nimport actions from './action'\nimport "
  },
  {
    "path": "src/store/mutation-types.js",
    "chars": 1309,
    "preview": "export const RECORD_ADDRESS = 'RECORD_ADDRESS'\nexport const ADD_CART = 'ADD_CART'\nexport const REDUCE_CART = 'REDUCE_CAR"
  },
  {
    "path": "src/store/mutations.js",
    "chars": 4819,
    "preview": "import {\n\tRECORD_ADDRESS,\n\tADD_CART,\n\tREDUCE_CART,\n\tINIT_BUYCART,\n\tCLEAR_CART,\n\tRECORD_SHOPDETAIL,\n\tRECORD_USERINFO,\n\tGE"
  },
  {
    "path": "src/style/common.scss",
    "chars": 1924,
    "preview": "body, div, span, header, footer, nav, section, aside, article, ul, dl, dt, dd, li, a, p, h1, h2, h3, h4,h5, h6, i, b, te"
  },
  {
    "path": "src/style/mixin.scss",
    "chars": 1089,
    "preview": "$blue: #3190e8;  \n$bc: #e4e4e4;\n$fc:#fff;\n\n// 背景图片地址和大小\n@mixin bis($url) { \n\tbackground-image: url($url);\n\tbackground-re"
  }
]

About this extraction

This page contains the full source code of the bailicangdu/vue2-elm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 87 files (507.2 KB), approximately 142.2k tokens, and a symbol index with 63 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!