Compare commits
785 Commits
Author | SHA1 | Date |
---|---|---|
花裤衩 | 33a93a12b4 | |
花裤衩 | 1bc2e5c198 | |
花裤衩 | 9cc3fa732a | |
花裤衩 | 44e23d00ca | |
花裤衩 | 8fd08c9167 | |
花裤衩 | 5e7113935c | |
Kerollos Magdy | 46e11caafc | |
dyz | ea60478304 | |
crayymumu | fe22b3cd94 | |
花裤衩 | 7c06214190 | |
花裤衩 | 73a9ab0379 | |
花裤衩 | 585391228e | |
Dihak | ae2aa61880 | |
花裤衩 | f6d8204b0b | |
花裤衩 | 435db380d3 | |
qige2016 | 6d88db5c73 | |
花裤衩 | 1c943509f9 | |
花裤衩 | 4e7665c072 | |
花裤衩 | a87218e266 | |
Silentdoer | 7702b3d809 | |
MaYuanhai | a50180f653 | |
Cat73 | fc68f56d13 | |
花裤衩 | d3bd933a8e | |
花裤衩 | 0bf61aac53 | |
花裤衩 | 2ef49493c3 | |
花裤衩 | f14805d0cd | |
花裤衩 | c5abe7532c | |
Cat73 | 534cd5bc26 | |
花裤衩 | f1feb2a86d | |
Edwin Betancourt | 0ae5079b2a | |
Nickbing Lao | 6f80263b42 | |
cooper | 5890499077 | |
AiMe1991 | 29b4ff636b | |
花裤衩 | e692876c28 | |
garethx | 6dacb783b2 | |
Phạm Ngọc Hòa | a2784dd6ef | |
花裤衩 | fc26c3106f | |
ntnyq | 9580c43a8e | |
Aisen | 1b8f726529 | |
花裤衩 | d4405464ce | |
Alex S | 9d8c7edf91 | |
花裤衩 | 6eccffeb2f | |
花裤衩 | f7a9d21109 | |
花裤衩 | 993a6c72e8 | |
echofly | 9e0435ac85 | |
Aisen60 | 776f10e197 | |
echofly | c2a5a15956 | |
花裤衩 | a45e64fcb2 | |
Shota Aratono | fec25fedba | |
RoBlues | d6816c547d | |
李小斐 | 6850312e89 | |
花裤衩 | d634e2ae2f | |
花裤衩 | b57f2008bd | |
花裤衩 | c9affcf2ad | |
花裤衩 | fbad7f481b | |
RussXD | 088f64eecc | |
AndyLZC/AndyLZC.github.io | 55b1bbac99 | |
Kaitian Xie | fd5a2e8da2 | |
任羽飞 | a0b39d5043 | |
韬 | 4f563a7bfe | |
花裤衩 | 262c0ba08e | |
flitrue | 594fc58d0c | |
monkeycf | 65d8c451e8 | |
xuanzai | e1554fdbd0 | |
Phạm Ngọc Hòa | 53803d067d | |
花裤衩 | 25dddbbce8 | |
Phạm Ngọc Hòa | 683f68b838 | |
bbigcd | 44203f88a7 | |
Phạm Ngọc Hòa | d5c013a48c | |
Phạm Ngọc Hòa | b11acb2171 | |
Phạm Ngọc Hòa | b2dd7caee6 | |
Phạm Ngọc Hòa | a4fa1199ba | |
Phạm Ngọc Hòa | 6a194d1b4f | |
花裤衩 | 6739ab543b | |
BradyBromley | 6a214f0eac | |
花裤衩 | 5273e02259 | |
花裤衩 | b51590b982 | |
MaYuanhai | 12b44f5d4b | |
花裤衩 | 197948dc44 | |
花裤衩 | b4cdf528ba | |
花裤衩 | f266713daf | |
monkeycf | 0343988f3d | |
monkeycf | 9c723c6618 | |
花裤衩 | e3cbf4ad90 | |
花裤衩 | 8235011665 | |
MaYuanhai | 0e9ce78b8a | |
Serge | 3a08b6e471 | |
Francis | 4d2d52ef03 | |
MaYuanhai | 1336b92c2f | |
花裤衩 | c7c815eef0 | |
Baskerville* | ee287d8314 | |
花裤衩 | 12c8d85873 | |
why | 46cc375d0d | |
Pan | c8039a5ce3 | |
itsccn | 1909018dbd | |
Pan | 018c20a3f6 | |
MaYuanhai | ef167ff064 | |
TinaryTree | 35adfcef3f | |
MaYuanhai | d3a2b6b34e | |
肖敏 | 4bd8f7f670 | |
Jessynt | 8e9f2e1479 | |
MaYuanhai | a0793dbeab | |
Pan | 9538d1b766 | |
Pan | 054ed40e07 | |
Serge | ac8c12c82d | |
花裤衩 | e8837d161e | |
花裤衩 | f891202706 | |
花裤衩 | e28701cde4 | |
bpzhang | 5b943d71e9 | |
Pan | 2584dcce16 | |
花裤衩 | 6a322c9def | |
花裤衩 | ab1922ef14 | |
花裤衩 | 13c1ecf25c | |
Pan | 8ce250a44e | |
Pan | 2f5c2eebcd | |
花裤衩 | 6770963672 | |
Pan | 131b9b9eff | |
花裤衩 | cd30d25459 | |
Yamel Senih | d0fcbbaa28 | |
花裤衩 | 40431fdfc8 | |
花裤衩 | 1e598e9684 | |
花裤衩 | be3dfac13b | |
liugq | 4f620c4a0d | |
Pan | 36060d5daf | |
Yamel Senih | a0b2014e85 | |
Yamel Senih | dbfcc9dc19 | |
Pan | 45edf7b048 | |
Pan | 2096ae1b6e | |
花裤衩 | 27df997915 | |
toruksmakto | 3a4543478f | |
花裤衩 | 7b0d527bf9 | |
Pan | 0b8baeb14d | |
Pan | 4ef0782189 | |
Pan | 0bf339b6db | |
Pan | 013f4fd91b | |
Pan | 2364fecbdd | |
花裤衩 | 7e8a6a4759 | |
Pan | 4dcd4fbbb1 | |
花裤衩 | 00a19db299 | |
Pan | e8e6c7e79c | |
Pan | 41318aa0d9 | |
Pan | 90af74eb40 | |
Pan | fd9ad8986c | |
dolonfly | 09a80688d2 | |
linzhengen | abac07820a | |
花裤衩 | 9e318f80ba | |
Pan | 9c28b1dd92 | |
Pan | d4be15d9d9 | |
Pan | f24b64392e | |
Tuan Duong | c58e2078bc | |
Pan | f9f51986e6 | |
Pan | 3625f92041 | |
anson | f0ca1735d3 | |
Pan | d8dbf92b47 | |
Pan | 120c78622d | |
Pan | 7dc9e681bf | |
toruksmakto | 7ca42be603 | |
dingangang | ea91066b18 | |
Pan | 50d0957409 | |
花裤衩 | 806f960a80 | |
Pan | 3f71147385 | |
Pan | 154b75b47c | |
Tuan Duong | 6a08c79bfb | |
yuntao1997 | c00564617e | |
Pan | 952da32879 | |
Pan | 3678bd18fb | |
Pan | 4ee334ad83 | |
Pan | 067a2910d4 | |
Pan | 9ecec0970f | |
花裤衩 | be7ec4c0ff | |
非空 | 26d0f40df2 | |
linfei | 14580da5b3 | |
花裤衩 | fdea6c684a | |
Pan | a6be6af46d | |
Tuan Duong | d0651ad2f2 | |
Pan | 43ae8520b3 | |
Pan | 5dd98ea47f | |
Pan | 035c7d78f1 | |
Pan | aa9d48905f | |
花裤衩 | 9cba45e971 | |
Pan | dbee6ff707 | |
derrick | b627d3d0ba | |
花裤衩 | 8f45dbe328 | |
Pan | 342b7b428a | |
Pan | c833cb6efa | |
Pan | afb62edc58 | |
MaYuanhai | 0358667a73 | |
花裤衩 | e3b6602bbf | |
花裤衩 | 79e2a604af | |
Pan | 083a4ada9d | |
花裤衩 | 90b7c2fbde | |
花裤衩 | f11839c8a4 | |
anson | 7492e2097f | |
Pan | 770753eff2 | |
花裤衩 | 0d40222b64 | |
Estelle00 | e363c7a77b | |
花裤衩 | c923726464 | |
花裤衩 | 43115e5538 | |
Pan | 184125bdd3 | |
Pan | 25414f1fd9 | |
Pan | cba0b789d0 | |
Pan | 4ad51be2db | |
MaYuanhai | a1708e9b68 | |
Pan | 55fa5acb85 | |
Pan | a8c6e11ee6 | |
Pan | 26d1bf09fd | |
花裤衩 | b94e69be6f | |
MaYuanhai | 96d3cfa215 | |
Pan | 20f6150741 | |
Pan | 7703005013 | |
zhu yu | 9a5c404ef8 | |
sun ao | 9d975b5eff | |
MaYuanhai | 331173ffee | |
Pan | f890685d8d | |
Pan | fb30079477 | |
Pan | 3100d0cff4 | |
Yuga Sun | ae6bbf7858 | |
MaYuanhai | 63dba8b7d8 | |
toruksmakto | ccb227fbec | |
Pan | 715fe3e684 | |
Mrli2016 | abb1d91a9e | |
花裤衩 | d1f32a05a8 | |
Pan | e601da38d0 | |
Jere | b8d47bd847 | |
Pan | 8d242a002f | |
小新 | 763b31d915 | |
Serge | c963f56686 | |
yuntao1997 | 17f0d84b35 | |
Yunfei | f38d5810d9 | |
裤裆三重奏 | cf48ed218b | |
Jesonhu | 9574643e92 | |
花裤衩 | 8edf209498 | |
Pan | 698df4942d | |
花裤衩 | 1e2fc52ac9 | |
Pan | 3e92814f13 | |
花裤衩 | 5ca6f79836 | |
liugq | dc6030bce6 | |
花裤衩 | fc9e7249e7 | |
花裤衩 | 9677406002 | |
Pan | 1e06f1da67 | |
MaYuanhai | aa2eb7d40f | |
kaisawind | 6255f54f41 | |
王洪莹 | c2495545a5 | |
Pan | fc277c75ee | |
frank10000 | e544c01e63 | |
花裤衩 | c0f378e50a | |
WangXinhai | 6b88c41ffc | |
花裤衩 | 2e89ef444b | |
Pan | fe950801c9 | |
Pan | 070a3343f2 | |
花裤衩 | 48e47e86f1 | |
Pan | 4e0559833f | |
花裤衩 | 8c18c000d4 | |
Pan | 9ed5db044f | |
Pan | 0fed69f367 | |
Pan | a1d6ad3453 | |
花裤衩 | c71f3110fb | |
Pan | fe381503eb | |
Pan | 24ee761809 | |
Pan | 0b6e7515ce | |
Pan | dd9fb09a29 | |
Pan | 6e42b4c896 | |
花裤衩 | 3b9abde89a | |
花裤衩 | 4b3a41c535 | |
花裤衩 | b44000c9de | |
Pan | 727c1a45dd | |
Pan | 9daeb1cb34 | |
花裤衩 | 3153a1b10b | |
xbigcat | 23055c9b2c | |
Pan | 8ef6c7ee7d | |
花裤衩 | eb1d3381f4 | |
Yuga Sun | 8cf279fbe1 | |
Pan | ac8eddf3d7 | |
Jiankian | 6234db924e | |
花裤衩 | d84a17688d | |
花裤衩 | f767fab4cc | |
Pan | 77a40745bb | |
花裤衩 | 109c393cc6 | |
Pan | c54e99d0a9 | |
Duy Nguyen Hoang | 5ea614fe5d | |
Nikita Sobolev | 1bb9283edd | |
Pan | 9cea3c3abe | |
Pan | 68a19d55de | |
Pan | 3dd29ab07a | |
Pan | c98d578757 | |
花裤衩 | 311796a14b | |
Pan | cc7572820e | |
花裤衩 | deb6840174 | |
董雨 | 07c3211989 | |
Pan | afdb893dcd | |
Pan | 90ee05df93 | |
Pan | 6f1db28ea2 | |
Pan | a56145509d | |
Pan | 1b394ae417 | |
Yulong Jing | c2a2fec067 | |
Pan | 999ea3a443 | |
Pan | 46d6f455af | |
Pan | 4d6e9a5358 | |
Pan | c68e68897b | |
花裤衩 | b37a789f63 | |
Heedong Im | 54dc9ddfaa | |
Pan | c6843f9646 | |
Pan | ea60729c0a | |
samuelchlui | 4a07432468 | |
Pan | a51d72f42e | |
Pan | c13b574794 | |
Pan | 9df740bcf1 | |
Pan | 4a7b50ed46 | |
Pan | a0862ca547 | |
jaysunxiao | 9f1552d98f | |
Pan | a25c63a580 | |
LarchLiu | 1701fcce5d | |
Pan | 1d684b7632 | |
花裤衩 | cbdad9cb1b | |
花裤衩 | 1a345a7c65 | |
花裤衩 | ec58373a52 | |
Pan | bf2629ffba | |
Pan | baa7172a70 | |
Pan | bc003fd78b | |
花裤衩 | 41a5615ee5 | |
花裤衩 | df23405bde | |
Pan | f94aa1aca3 | |
frank10000 | 96bda5515c | |
Pan | 0f6d830c19 | |
CNine | e8ab82c2c1 | |
Ramón Menor | a284c1f007 | |
Pan | 323408f8d9 | |
Pan | 90d3e314c0 | |
happystory | 4780ac334f | |
花裤衩 | b0bd91cd0f | |
Pan | ae2754a568 | |
Pan | 6e07d18b1d | |
花裤衩 | f58db95be5 | |
Pan | 616b65c238 | |
Pan | 68cd051bb6 | |
花裤衩 | 935d9aaba8 | |
花裤衩 | 616f173aab | |
花裤衩 | d1cceb69b7 | |
花裤衩 | ff13ee1f27 | |
Pan | dc84e7b9fb | |
zhaoguoweiLLHC | b82e8e860d | |
Pan | 98a8277a37 | |
花裤衩 | 63ff44f8e5 | |
Pan | dd5646ffbc | |
Pan | 371c8504c2 | |
Pan | 87b319d96a | |
inklake | 4c49259c92 | |
花裤衩 | 83516aeb17 | |
花裤衩 | 24602755cd | |
花裤衩 | 11163146c0 | |
Pan | 3277343804 | |
jiuwuxiaohun | 0740bb36f7 | |
Pan | 9c03dd3514 | |
Pan | fbb3641406 | |
花裤衩 | f85b044ff8 | |
花裤衩 | ed4427243d | |
花裤衩 | 9c5352ecd6 | |
Chong Guo | 62fb5d1e14 | |
Pan | 14e693339c | |
Pan | c58bce603b | |
Pan | fa54b927f7 | |
Pan | ba6bf3e217 | |
Shaw | 6ecf8b820a | |
Pan | a5dd905b46 | |
Pan | 676aaf3485 | |
Pan | 44e4bddc21 | |
花裤衩 | a03d1edac6 | |
Pan | 2938e33d0e | |
花裤衩 | 2fb26525fa | |
花裤衩 | d0d1addba8 | |
Pan | 0fe3f181ad | |
花裤衩 | 68de01e828 | |
Pan | 6e569c4f4a | |
花裤衩 | 0fbda3c8c7 | |
Pan | 5bbb4abe21 | |
Pan | 1e50d4a93b | |
ZYSzys | ccf1791fca | |
Pan | 325120b653 | |
Pan | 2e1f36fe00 | |
花裤衩 | 00d292f67e | |
Pan | 0e75dcc42a | |
mimimi | 189e645b23 | |
Pan | d5a8fb1e71 | |
Pan | b2570f891d | |
Pan | 4035bf58f2 | |
花裤衩 | e5d4290938 | |
Leo | 8f58baf617 | |
Pan | fded36c990 | |
Pan | 53f3e7d5e6 | |
花裤衩 | 93e01b64d4 | |
Pan | a871e147d6 | |
花裤衩 | 378ca2c217 | |
Andrey Dos | 1df59cc4b6 | |
shufangyi | 312a2ca8ed | |
Pan | f3733c0b37 | |
Pan | 0ef14ff5c6 | |
Pan | c57c6045c9 | |
_xiaotian | fe190b6188 | |
Pan | 48a966fe1c | |
Pan | 63d39727ac | |
Pan | 1e0b9c0055 | |
mimimi | 5f20bfc780 | |
mimimi | 8851a68066 | |
Pan | 878628b0ed | |
Pan | e254fc6c1a | |
花裤衩 | 513eb66d97 | |
Pan | 62e1c851c8 | |
Pan | f0a01f0fd1 | |
博文 | aa7eab58f9 | |
花裤衩 | 77cb6b1f43 | |
iGoo丶 | 5fbf1cf5da | |
Pan | 6a5197ad51 | |
Pan | 9b7a9a64e5 | |
Pan | 89ce53e185 | |
Pan | 9e04f58163 | |
花裤衩 | d98c5032f8 | |
ZYSzys | a575670cef | |
花裤衩 | 44fa96f142 | |
Pan | e4481a9d34 | |
Pan | 572a2d9c34 | |
Pan | 5070e20dea | |
Pan | 59789d92cf | |
Pan | 775f6f5f3a | |
Pan | 2687b2eb3c | |
Pan | 76327a8f26 | |
Pan | 03b708870b | |
花裤衩 | bdc31cea1a | |
Liu Xinyu | ae2ca072f5 | |
花裤衩 | d995cdb332 | |
Pan | cbc3ddd827 | |
HiiTea | 9cf00fd63a | |
Pan | 03691739e1 | |
Pan | 3f479664b6 | |
临书 | cbee7b6f20 | |
临书 | 2a590a2087 | |
Pan | c93fcefe54 | |
Pan | 9f8ac37497 | |
Pan | 8c685cc4c6 | |
kuviki | e40fd27775 | |
Pan | f3ccd9f04e | |
Pan | 914a4ec62c | |
Pan | 739aef4387 | |
Insua | a7942636c6 | |
Pan | 31d9da8b9f | |
Pan | 600e75d0a2 | |
Pan | 9ba1ea6933 | |
Pan | 320e941d9a | |
花裤衩 | d0f6d3f1f6 | |
Pan | 0375542009 | |
Pan | 03e5f762b3 | |
Heedong Im | bd0227feed | |
Pan | 20aad46416 | |
花裤衩 | 4fc25241fe | |
Pan | 6327869106 | |
Pan | c861dd10cf | |
花裤衩 | 0a196f79ba | |
Pan | d2d323bb02 | |
Pan | 66613f0373 | |
Pan | 6795c26d02 | |
花裤衩 | 597df4844a | |
Pan | 1e103cf151 | |
花裤衩 | 99d53ee0ca | |
Pan | f9d510ea78 | |
Pan | 9fbb028124 | |
Pan | 9b5f0160af | |
花裤衩 | 0e4ea0871c | |
Pan | 88429bd809 | |
xVirus | 62a9565f86 | |
Pan | f663b23b29 | |
Pan | afd255d5ba | |
Pan | b7c8079350 | |
Yuga Sun | 543a9928cf | |
Pan | 8f37950589 | |
Pan | 6821eac35b | |
Pan | cc5e62d5f5 | |
Pan | 0cccc636b8 | |
Pan | 563ce873bd | |
Pan | 44e94b2d16 | |
Pan | a160848367 | |
Pan | 7099e6a3eb | |
花裤衩 | 14fee27a92 | |
Pan | 7003a79ef6 | |
花裤衩 | c5faa63ee5 | |
weiwei Wang | d29a9486a2 | |
weiqinl | 01442ce4d7 | |
Pan | f28a7149fb | |
Pan | 51ad902d8f | |
linlinjava | 3cff6dcf4c | |
Pan | afe975b3c2 | |
Pan | d0eebf83c4 | |
花裤衩 | a55b149b27 | |
Pan | fc19121311 | |
Pan | de06619266 | |
Yuga Sun | 88c28f5d7e | |
Yuga Sun | 26b84847dd | |
Pan | 3cc3e134c2 | |
Pan | 2afb1dfabb | |
Pan | 5fe3d70246 | |
Pan | 4aa9345d90 | |
amedora | 0fcbf4b53b | |
Pan | 8142c06a99 | |
Pan | c398ee0ddc | |
Pan | a633729215 | |
Pan | f9c4dd7af3 | |
Pan | 5f4ce7fc71 | |
Pan | 01928cd4ec | |
Pan | 27effcc54c | |
Pan | 7cacd5a4ac | |
Pan | 31b7fa6f55 | |
Pan | 2cb6211cd6 | |
Yusril Herlian Syah | ebb0b4a0ff | |
happystory | c356695f2e | |
花裤衩 | 112e3b977c | |
Pan | ae41459cb1 | |
Pan | aa592cfb69 | |
Pan | 9205a85c2d | |
Pan | 6938dd3caf | |
Pan | 398d59d78a | |
Pan | dc35d1ae92 | |
Pan | 2f411b870c | |
Pan | 305d659431 | |
Pan | 55c08ab666 | |
Pan | 09e613b33a | |
Pan | c0ed44932e | |
Pan | a48a1bd8be | |
Pan | 55e8cd5306 | |
Zenon | dc9e27e4b1 | |
Pan | d754eae662 | |
Pan | 94ae1f8719 | |
Pan | 48070e5abf | |
Pan | eef99d3d14 | |
Pan | 6f2a7ce804 | |
Zenon | 2e0d3fd0e4 | |
Pan | bc01171466 | |
Pan | 4e65890b6a | |
Pan | 79c5cb4fcd | |
Pan | 0d47e3454e | |
Pan | 3253a91a7e | |
Pan | fea6e5feee | |
Zenon | 1610945813 | |
Pan | 840eda6e27 | |
Pan | 700e08b795 | |
Pan | 3c0696d1a9 | |
Pan | 76a6eb12e7 | |
Pan | 2c147649ba | |
Pan | de3b29b5f3 | |
Pan | 54acf1e0d5 | |
Pan | de08e49f19 | |
Pan | 2472107768 | |
Pan | d18902dfee | |
Pan | 9ba2648689 | |
Pan | 1d0b26cec8 | |
Pan | ea7e139696 | |
Pan | deac95da1b | |
Pan | 2b51b987be | |
花裤衩 | 45fef9b431 | |
Pan | 83e56488d8 | |
Pan | f3bfaa0f2b | |
Pan | e261fbcbfb | |
Pan | 471c297f13 | |
Pan | 093475ee50 | |
Pan | cb3578e5c3 | |
tlx6550 | fe25c4d96b | |
Pan | 7fef8568c2 | |
Pan | 0dfa56c73e | |
Pan | 642d48e372 | |
Pan | 021c147b31 | |
Pan | 04d9b849dd | |
Pan | 2e74f0d782 | |
花裤衩 | dc162093cc | |
Pan | 8fd786c4ed | |
Pan | 54e7ce2b76 | |
Pan | f5563b4eed | |
Pan | 0c80fba84c | |
Pan | 4d3bbae183 | |
leij1ang | b6d97f1806 | |
Pan | a68413cb8f | |
Pan | f9aaaa9091 | |
Pan | 85492f148f | |
Pan | b7ca786751 | |
花裤衩 | c32bd73b42 | |
Pan | 3aacd3cccd | |
Pan | e7f626f015 | |
Pan | b53d0945ab | |
Pan | ca75f7bcbc | |
lvsmart | b7939165d1 | |
Pan | ebc2ac08b7 | |
Pan | a9d2978c31 | |
Pan | a4597887ac | |
Pan | 44b180a7b3 | |
Pan | acebaeae0c | |
Pan | d09923ff4f | |
Pan | fc1a13d10b | |
Pan | 705b9ccefd | |
Pan | c84964d77c | |
Pan | 8f9de5c641 | |
Pan | 96a7035b1d | |
Pan | 7f2bd58035 | |
Pan | b4b9d166c4 | |
Pan | da24d61008 | |
Pan | 8ce571b61d | |
Pan | 38192b828d | |
Pan | 72f653dcc7 | |
donng | 4dfa878fc6 | |
Pan | cef1f11931 | |
Pan | 443c7aed3c | |
Pan | 0f5304112c | |
Pan | dd3e22d5a1 | |
Pan | d99cb068aa | |
Pan | 394f366aac | |
Pan | e5ed2a39a5 | |
Pan | 39d26068ec | |
Pan | d68d464142 | |
Pan | d476e32032 | |
Pan | 8f2b0c94ba | |
Pan | e00f2aedc7 | |
Pan | df28ad7078 | |
Pan | 4feb89c94e | |
Pan | a56d6f0cbd | |
Pan | bee26561aa | |
Pan | 2ec9fe74a8 | |
Pan | dec160fd1e | |
Pan | c06baffb17 | |
Pan | f876b9b678 | |
Pan | 061fa1f2a5 | |
Pan | e0b8f09a9e | |
Pan | ede541e2f5 | |
Pan | e0f6248d0e | |
Pan | 1c4c3380e6 | |
Pan | 073b7219ff | |
Pan | 98604af104 | |
Pan | 3cb1e321d3 | |
Pan | f2fcdee815 | |
Pan | 497b96f931 | |
Pan | ed34ea3e07 | |
花裤衩 | 47a373803e | |
花裤衩 | e8ad1f835c | |
Pan | 43a51148fe | |
Pan | 3f9df15c30 | |
Pan | a9363ce541 | |
Pan | 690c779c64 | |
Pan | f6279077de | |
Pan | 6b9e89055d | |
Pan | 6b13ffce66 | |
Pan | d20585a3f9 | |
Pan | 46b4f74969 | |
Pan | 8c204b9837 | |
Pan | 339d760771 | |
Pan | 6d6a9df5b8 | |
Pan | 1286324214 | |
Pan | 372c4489f0 | |
Pan | 1511fe3778 | |
Pan | 122f7cafa6 | |
Pan | 6d1059f6a8 | |
Reza Haidari .A | 1d4f12187f | |
花裤衩 | 925dbeb045 | |
Pan | 35055c5e51 | |
Pan | e0a1e249ee | |
Pan | a0d83e2ffc | |
Pan | 53059d5ccf | |
Pan | fa5e6d9ecf | |
Pan | 4e25a17bff | |
Pan | 61095a9f2c | |
Pan | 61deec548c | |
Pan | 5eda0685ed | |
Pan | 11beefdb44 | |
Pan | 7e1ba16d12 | |
Pan | 7451ed6299 | |
Pan | 71aa416d71 | |
Pan | 4723a02a4b | |
Pan | e05da2650b | |
Pan | bb1d939a94 | |
Pan | ac5d087ea4 | |
Pan | c53fb7fbb1 | |
Pan | 660ff765f5 | |
Pan | aaf24b4654 | |
Pan | 8211016078 | |
Pan | 374fd3ffeb | |
Pan | e8b34bbc0d | |
花裤衩 | 74cbb26209 | |
Pan | fe31c88193 | |
Pan | 3b89cde53a | |
Pan | 59e240eb9a | |
Pan | 98d5f9a247 | |
Pan | 3666148ddc | |
Pan | d56831679e | |
Pan | 2c868f47d9 | |
Pan | 1ae31fdd45 | |
Pan | a932272b8f | |
Pan | 577e4dc17e | |
Pan | 0d9188b206 | |
Pan | 5b3b8b87d1 | |
Pan | 2c82d0a28e | |
Pan | 913f6c8bec | |
Pan | 76f4017470 | |
Pan | feb6785654 | |
Pan | 59073fb013 | |
Pan | c82ed3fcbf | |
Pan | f99b97d9f1 | |
Pan | 99417081ed | |
Pan | 88d1338f29 | |
Pan | 3ded46cf23 | |
Pan | 5857db3393 | |
Pan | a465652be6 | |
Pan | a8459fa572 | |
Pan | cddace507d | |
Pan | e762056e80 | |
Pan | 18ec63d238 | |
Pan | ccddfe87bc | |
Pan | 87a44ae7f5 | |
dingyi1993 | 1c852db0ef | |
Pan | 9463c50e06 | |
Pan | 658abf664d | |
spiritree | 4940dd4040 | |
spiritree | 91bd31e1e2 | |
spiritree | a8602e78f0 | |
Pan | 516897b97a | |
Pan | 2725285d26 | |
Pan | a842a4b451 | |
Pan | be0606ebbc | |
Pan | a10de2e8d8 | |
Pan | 2282135b44 | |
Pan | 329f3b3714 | |
Pan | 065eaa93a2 | |
Pan | 4f2f136dd0 | |
Pan | 8d53ae1259 | |
spiritree | a185412446 | |
spiritree | 3cf048e80b | |
spiritree | fcf7c0ba50 | |
Pan | 807aa548b2 | |
Pan | db61251d89 | |
Pan | 582c6f4ae4 | |
Pan | 9c2a7e9485 | |
lei.jiang | fde12e8ef9 | |
lei.jiang | 8945476c22 | |
lei.jiang | 14ff09a414 | |
Pan | a14547aaf9 | |
Pan | b1311322ad | |
Pan | ffec6b6df7 | |
Pan | f0afbf7ea5 | |
Pan | a4f8e0b805 | |
花裤衩 | 2d72df3605 | |
花裤衩 | e9f92a7d3d | |
花裤衩 | ee362f22b2 | |
花裤衩 | 11426c8494 | |
Hex | fa5f5e9d26 | |
dongsuo | cda292dec1 | |
Svend | 877b73cd67 | |
maemo | 53d7243316 | |
Pan | 5379510013 | |
Pan | f712d4682e | |
Pan | cb0e889829 | |
Pan | 6a8a02f839 | |
Pan | d56cd59474 | |
Pan | a10cfcc837 | |
Pan | c8e632f0c3 | |
Pan | c182a119e1 | |
Pan | 90fd4328b7 | |
Pan | 97570fa612 | |
Pan | bae698c9ad | |
Pan | f7aee3b5a3 | |
Pan | b98860ace1 | |
Pan | 3c05519a09 | |
Pan | 385ec5a762 | |
Pan | 33a4369cd7 | |
Pan | 8fa2364a3b | |
Pan | 551e911eb4 | |
Pan | b8ecda19d8 | |
Pan | 62d2f62bff | |
Pan | 0094f44910 | |
Pan | d06d476b50 | |
Pan | aa5f9059b3 | |
Pan | 9768305166 | |
Pan | e912cea26a | |
Pan | eac12e3ac0 | |
花裤衩 | c32fc58a3a | |
spiritree | bf0f2e7ee3 | |
Pan | 2e9a3a849b | |
Pan | cdebb5c012 | |
Pan | 00a83d1e5a | |
Pan | 17ada3c65e | |
Pan | 391e7703ed | |
Pan | 97e94c067d | |
Pan | a3b1dd81fd | |
花裤衩 | c96bdeb99d |
8
.babelrc
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
["env", { "modules": false }],
|
|
||||||
"stage-2"
|
|
||||||
],
|
|
||||||
"plugins": ["transform-runtime"],
|
|
||||||
"comments": false
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
# http://editorconfig.org
|
# https://editorconfig.org
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# just a flag
|
||||||
|
ENV = 'development'
|
||||||
|
|
||||||
|
# base api
|
||||||
|
VUE_APP_BASE_API = '/dev-api'
|
|
@ -0,0 +1,6 @@
|
||||||
|
# just a flag
|
||||||
|
ENV = 'production'
|
||||||
|
|
||||||
|
# base api
|
||||||
|
VUE_APP_BASE_API = '/prod-api'
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
NODE_ENV = production
|
||||||
|
|
||||||
|
# just a flag
|
||||||
|
ENV = 'staging'
|
||||||
|
|
||||||
|
# base api
|
||||||
|
VUE_APP_BASE_API = '/stage-api'
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
build/*.js
|
build/*.js
|
||||||
config/*.js
|
|
||||||
src/assets
|
src/assets
|
||||||
|
public
|
||||||
|
dist
|
||||||
|
|
492
.eslintrc.js
|
@ -1,318 +1,198 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
parser: 'babel-eslint',
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint',
|
||||||
sourceType: 'module'
|
sourceType: 'module'
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
node: true
|
node: true,
|
||||||
},
|
es6: true,
|
||||||
extends: 'eslint:recommended',
|
|
||||||
// required to lint *.vue files
|
|
||||||
plugins: [
|
|
||||||
'html'
|
|
||||||
],
|
|
||||||
// check if imports actually resolve
|
|
||||||
'settings': {
|
|
||||||
'import/resolver': {
|
|
||||||
'webpack': {
|
|
||||||
'config': 'build/webpack.base.conf.js'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
||||||
|
|
||||||
// add your custom rules here
|
// add your custom rules here
|
||||||
'rules': {
|
//it is base on https://github.com/vuejs/eslint-config-vue
|
||||||
// don't require .vue extension when importing
|
rules: {
|
||||||
// 'import/extensions': ['error', 'always', {
|
"vue/max-attributes-per-line": [2, {
|
||||||
// 'js': 'never',
|
"singleline": 10,
|
||||||
// 'vue': 'never'
|
"multiline": {
|
||||||
// }],
|
"max": 1,
|
||||||
// allow debugger during development
|
"allowFirstLine": false
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
}
|
||||||
/*
|
}],
|
||||||
* Possible Errors
|
"vue/singleline-html-element-content-newline": "off",
|
||||||
*/
|
"vue/multiline-html-element-content-newline":"off",
|
||||||
|
"vue/name-property-casing": ["error", "PascalCase"],
|
||||||
// disallow unnecessary parentheses
|
"vue/no-v-html": "off",
|
||||||
'no-extra-parens': ['error', 'all', {'nestedBinaryExpressions': false}],
|
'accessor-pairs': 2,
|
||||||
|
'arrow-spacing': [2, {
|
||||||
// disallow negating the left operand of relational operators
|
'before': true,
|
||||||
'no-unsafe-negation': 'error',
|
'after': true
|
||||||
|
}],
|
||||||
// enforce valid JSDoc comments
|
'block-spacing': [2, 'always'],
|
||||||
'valid-jsdoc': 'off',
|
'brace-style': [2, '1tbs', {
|
||||||
|
'allowSingleLine': true
|
||||||
/*
|
}],
|
||||||
* Best Practices
|
'camelcase': [0, {
|
||||||
*/
|
'properties': 'always'
|
||||||
|
}],
|
||||||
// enforce return statements in callbacks of array methods
|
'comma-dangle': [2, 'never'],
|
||||||
'array-callback-return': 'error',
|
'comma-spacing': [2, {
|
||||||
|
'before': false,
|
||||||
// enforce consistent brace style for all control statements
|
'after': true
|
||||||
curly: ['error', 'multi-line'],
|
}],
|
||||||
|
'comma-style': [2, 'last'],
|
||||||
// enforce consistent newlines before and after dots
|
'constructor-super': 2,
|
||||||
'dot-location': ['error', 'property'],
|
'curly': [2, 'multi-line'],
|
||||||
|
'dot-location': [2, 'property'],
|
||||||
// enforce dot notation whenever possible
|
'eol-last': 2,
|
||||||
'dot-notation': 'error',
|
'eqeqeq': ["error", "always", {"null": "ignore"}],
|
||||||
|
'generator-star-spacing': [2, {
|
||||||
// require the use of === and !==
|
'before': true,
|
||||||
'eqeqeq': ['error', 'smart'],
|
'after': true
|
||||||
|
}],
|
||||||
// disallow the use of arguments.caller or arguments.callee
|
'handle-callback-err': [2, '^(err|error)$'],
|
||||||
'no-caller': 'error',
|
'indent': [2, 2, {
|
||||||
|
'SwitchCase': 1
|
||||||
// disallow empty functions
|
}],
|
||||||
'no-empty-function': 'error',
|
'jsx-quotes': [2, 'prefer-single'],
|
||||||
|
'key-spacing': [2, {
|
||||||
// disallow unnecessary calls to .bind()
|
'beforeColon': false,
|
||||||
'no-extra-bind': 'error',
|
'afterColon': true
|
||||||
|
}],
|
||||||
// disallow unnecessary labels
|
'keyword-spacing': [2, {
|
||||||
'no-extra-label': 'error',
|
'before': true,
|
||||||
|
'after': true
|
||||||
// disallow leading or trailing decimal points in numeric literals
|
}],
|
||||||
'no-floating-decimal': 'error',
|
'new-cap': [2, {
|
||||||
|
'newIsCap': true,
|
||||||
// disallow assignments to native objects or read-only global variables
|
'capIsNew': false
|
||||||
'no-global-assign': 'error',
|
}],
|
||||||
|
'new-parens': 2,
|
||||||
// disallow the use of eval()-like methods
|
'no-array-constructor': 2,
|
||||||
'no-implied-eval': 'error',
|
'no-caller': 2,
|
||||||
|
|
||||||
// disallow the use of the __iterator__ property
|
|
||||||
'no-iterator': 'error',
|
|
||||||
|
|
||||||
// disallow unnecessary nested blocks
|
|
||||||
'no-lone-blocks': 'error',
|
|
||||||
|
|
||||||
// disallow multiple spaces
|
|
||||||
'no-multi-spaces': 'error',
|
|
||||||
|
|
||||||
// disallow new operators with the String, Number, and Boolean objects
|
|
||||||
'no-new-wrappers': 'error',
|
|
||||||
|
|
||||||
// disallow octal escape sequences in string literals
|
|
||||||
'no-octal-escape': 'error',
|
|
||||||
|
|
||||||
// disallow the use of the __proto__ property
|
|
||||||
'no-proto': 'error',
|
|
||||||
|
|
||||||
// disallow comparisons where both sides are exactly the same
|
|
||||||
'no-self-compare': 'error',
|
|
||||||
|
|
||||||
// disallow throwing literals as exceptions
|
|
||||||
'no-throw-literal': 'error',
|
|
||||||
|
|
||||||
// disallow unused expressions
|
|
||||||
'no-unused-expressions': 'error',
|
|
||||||
|
|
||||||
// disallow unnecessary calls to .call() and .apply()
|
|
||||||
'no-useless-call': 'error',
|
|
||||||
|
|
||||||
// disallow unnecessary concatenation of literals or template literals
|
|
||||||
'no-useless-concat': 'error',
|
|
||||||
|
|
||||||
// disallow unnecessary escape characters
|
|
||||||
'no-useless-escape': 'error',
|
|
||||||
|
|
||||||
// disallow void operators
|
|
||||||
'no-void': 'error',
|
|
||||||
|
|
||||||
// require parentheses around immediate function invocations
|
|
||||||
'wrap-iife': 'error',
|
|
||||||
|
|
||||||
// require or disallow “Yoda” conditions
|
|
||||||
yoda: 'error',
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Variables
|
|
||||||
*/
|
|
||||||
|
|
||||||
// disallow labels that share a name with a variable
|
|
||||||
'no-label-var': 'error',
|
|
||||||
|
|
||||||
// disallow initializing variables to undefined
|
|
||||||
'no-undef-init': 'error',
|
|
||||||
'no-undef': 'off',
|
|
||||||
// disallow the use of variables before they are defined
|
|
||||||
'no-use-before-define': 'error',
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Node.js and CommonJS
|
|
||||||
*/
|
|
||||||
|
|
||||||
// disallow new operators with calls to require
|
|
||||||
'no-new-require': 'error',
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stylistic Issues
|
|
||||||
*/
|
|
||||||
|
|
||||||
// enforce consistent spacing inside array brackets
|
|
||||||
'array-bracket-spacing': 'error',
|
|
||||||
|
|
||||||
// enforce consistent spacing inside single-line blocks
|
|
||||||
'block-spacing': 'error',
|
|
||||||
|
|
||||||
// enforce consistent brace style for blocks
|
|
||||||
'brace-style': ['error', '1tbs', {'allowSingleLine': true}],
|
|
||||||
|
|
||||||
// require or disallow trailing commas
|
|
||||||
'comma-dangle': 'error',
|
|
||||||
|
|
||||||
// enforce consistent spacing before and after commas
|
|
||||||
'comma-spacing': 'error',
|
|
||||||
|
|
||||||
// enforce consistent comma style
|
|
||||||
'comma-style': 'error',
|
|
||||||
|
|
||||||
// enforce consistent spacing inside computed property brackets
|
|
||||||
'computed-property-spacing': 'error',
|
|
||||||
|
|
||||||
// require or disallow spacing between function identifiers and their invocations
|
|
||||||
'func-call-spacing': 'error',
|
|
||||||
|
|
||||||
// enforce consistent indentation
|
|
||||||
indent: ['error', 2, {SwitchCase: 1}],
|
|
||||||
|
|
||||||
// enforce the consistent use of either double or single quotes in JSX attributes
|
|
||||||
'jsx-quotes': 'error',
|
|
||||||
|
|
||||||
// enforce consistent spacing between keys and values in object literal properties
|
|
||||||
'key-spacing': 'error',
|
|
||||||
|
|
||||||
// enforce consistent spacing before and after keywords
|
|
||||||
'keyword-spacing': 'error',
|
|
||||||
|
|
||||||
// enforce consistent linebreak style
|
|
||||||
'linebreak-style': 'error',
|
|
||||||
|
|
||||||
// require or disallow newlines around directives
|
|
||||||
'lines-around-directive': 'error',
|
|
||||||
|
|
||||||
// require constructor names to begin with a capital letter
|
|
||||||
'new-cap': 'off',
|
|
||||||
|
|
||||||
// require parentheses when invoking a constructor with no arguments
|
|
||||||
'new-parens': 'error',
|
|
||||||
|
|
||||||
// disallow Array constructors
|
|
||||||
'no-array-constructor': 'error',
|
|
||||||
|
|
||||||
// disallow Object constructors
|
|
||||||
'no-new-object': 'error',
|
|
||||||
|
|
||||||
// disallow trailing whitespace at the end of lines
|
|
||||||
'no-trailing-spaces': 'error',
|
|
||||||
|
|
||||||
// disallow ternary operators when simpler alternatives exist
|
|
||||||
'no-unneeded-ternary': 'error',
|
|
||||||
|
|
||||||
// disallow whitespace before properties
|
|
||||||
'no-whitespace-before-property': 'error',
|
|
||||||
|
|
||||||
// enforce consistent spacing inside braces
|
|
||||||
'object-curly-spacing': ['error', 'always'],
|
|
||||||
|
|
||||||
// require or disallow padding within blocks
|
|
||||||
'padded-blocks': ['error', 'never'],
|
|
||||||
|
|
||||||
// require quotes around object literal property names
|
|
||||||
'quote-props': ['error', 'as-needed'],
|
|
||||||
|
|
||||||
// enforce the consistent use of either backticks, double, or single quotes
|
|
||||||
quotes: ['error', 'single'],
|
|
||||||
|
|
||||||
// enforce consistent spacing before and after semicolons
|
|
||||||
'semi-spacing': 'error',
|
|
||||||
|
|
||||||
// require or disallow semicolons instead of ASI
|
|
||||||
// semi: ['error', 'never'],
|
|
||||||
|
|
||||||
// enforce consistent spacing before blocks
|
|
||||||
'space-before-blocks': 'error',
|
|
||||||
|
|
||||||
'no-console': 'off',
|
'no-console': 'off',
|
||||||
|
'no-class-assign': 2,
|
||||||
// enforce consistent spacing before function definition opening parenthesis
|
'no-cond-assign': 2,
|
||||||
'space-before-function-paren': ['error', 'never'],
|
'no-const-assign': 2,
|
||||||
|
'no-control-regex': 0,
|
||||||
// enforce consistent spacing inside parentheses
|
'no-delete-var': 2,
|
||||||
'space-in-parens': 'error',
|
'no-dupe-args': 2,
|
||||||
|
'no-dupe-class-members': 2,
|
||||||
// require spacing around infix operators
|
'no-dupe-keys': 2,
|
||||||
'space-infix-ops': 'error',
|
'no-duplicate-case': 2,
|
||||||
|
'no-empty-character-class': 2,
|
||||||
// enforce consistent spacing before or after unary operators
|
'no-empty-pattern': 2,
|
||||||
'space-unary-ops': 'error',
|
'no-eval': 2,
|
||||||
|
'no-ex-assign': 2,
|
||||||
// enforce consistent spacing after the // or /* in a comment
|
'no-extend-native': 2,
|
||||||
'spaced-comment': 'error',
|
'no-extra-bind': 2,
|
||||||
|
'no-extra-boolean-cast': 2,
|
||||||
// require or disallow Unicode byte order mark (BOM)
|
'no-extra-parens': [2, 'functions'],
|
||||||
'unicode-bom': 'error',
|
'no-fallthrough': 2,
|
||||||
|
'no-floating-decimal': 2,
|
||||||
|
'no-func-assign': 2,
|
||||||
/*
|
'no-implied-eval': 2,
|
||||||
* ECMAScript 6
|
'no-inner-declarations': [2, 'functions'],
|
||||||
*/
|
'no-invalid-regexp': 2,
|
||||||
|
'no-irregular-whitespace': 2,
|
||||||
// require braces around arrow function bodies
|
'no-iterator': 2,
|
||||||
'arrow-body-style': 'error',
|
'no-label-var': 2,
|
||||||
|
'no-labels': [2, {
|
||||||
// require parentheses around arrow function arguments
|
'allowLoop': false,
|
||||||
'arrow-parens': ['error', 'as-needed'],
|
'allowSwitch': false
|
||||||
|
}],
|
||||||
// enforce consistent spacing before and after the arrow in arrow functions
|
'no-lone-blocks': 2,
|
||||||
'arrow-spacing': 'error',
|
'no-mixed-spaces-and-tabs': 2,
|
||||||
|
'no-multi-spaces': 2,
|
||||||
// enforce consistent spacing around * operators in generator functions
|
'no-multi-str': 2,
|
||||||
'generator-star-spacing': ['error', 'after'],
|
'no-multiple-empty-lines': [2, {
|
||||||
|
'max': 1
|
||||||
// disallow duplicate module imports
|
}],
|
||||||
'no-duplicate-imports': 'error',
|
'no-native-reassign': 2,
|
||||||
|
'no-negated-in-lhs': 2,
|
||||||
// disallow unnecessary computed property keys in object literals
|
'no-new-object': 2,
|
||||||
'no-useless-computed-key': 'error',
|
'no-new-require': 2,
|
||||||
|
'no-new-symbol': 2,
|
||||||
// disallow unnecessary constructors
|
'no-new-wrappers': 2,
|
||||||
'no-useless-constructor': 'error',
|
'no-obj-calls': 2,
|
||||||
|
'no-octal': 2,
|
||||||
// disallow renaming import, export, and destructured assignments to the same name
|
'no-octal-escape': 2,
|
||||||
'no-useless-rename': 'error',
|
'no-path-concat': 2,
|
||||||
|
'no-proto': 2,
|
||||||
// require let or const instead of var
|
'no-redeclare': 2,
|
||||||
'no-var': 'error',
|
'no-regex-spaces': 2,
|
||||||
|
'no-return-assign': [2, 'except-parens'],
|
||||||
// require or disallow method and property shorthand syntax for object literals
|
'no-self-assign': 2,
|
||||||
'object-shorthand': 'error',
|
'no-self-compare': 2,
|
||||||
|
'no-sequences': 2,
|
||||||
// require arrow functions as callbacks
|
'no-shadow-restricted-names': 2,
|
||||||
'prefer-arrow-callback': 'error',
|
'no-spaced-func': 2,
|
||||||
|
'no-sparse-arrays': 2,
|
||||||
// require const declarations for variables that are never reassigned after declared
|
'no-this-before-super': 2,
|
||||||
'prefer-const': 'error',
|
'no-throw-literal': 2,
|
||||||
|
'no-trailing-spaces': 2,
|
||||||
// disallow parseInt() in favor of binary, octal, and hexadecimal literals
|
'no-undef': 2,
|
||||||
'prefer-numeric-literals': 'error',
|
'no-undef-init': 2,
|
||||||
|
'no-unexpected-multiline': 2,
|
||||||
// require rest parameters instead of arguments
|
'no-unmodified-loop-condition': 2,
|
||||||
'prefer-rest-params': 'error',
|
'no-unneeded-ternary': [2, {
|
||||||
|
'defaultAssignment': false
|
||||||
// require spread operators instead of .apply()
|
}],
|
||||||
'prefer-spread': 'error',
|
'no-unreachable': 2,
|
||||||
|
'no-unsafe-finally': 2,
|
||||||
// enforce spacing between rest and spread operators and their expressions
|
'no-unused-vars': [2, {
|
||||||
'rest-spread-spacing': 'error',
|
'vars': 'all',
|
||||||
|
'args': 'none'
|
||||||
// require or disallow spacing around embedded expressions of template strings
|
}],
|
||||||
'template-curly-spacing': 'error',
|
'no-useless-call': 2,
|
||||||
|
'no-useless-computed-key': 2,
|
||||||
// require or disallow spacing around the * in yield* expressions
|
'no-useless-constructor': 2,
|
||||||
'yield-star-spacing': 'error'
|
'no-useless-escape': 0,
|
||||||
|
'no-whitespace-before-property': 2,
|
||||||
|
'no-with': 2,
|
||||||
|
'one-var': [2, {
|
||||||
|
'initialized': 'never'
|
||||||
|
}],
|
||||||
|
'operator-linebreak': [2, 'after', {
|
||||||
|
'overrides': {
|
||||||
|
'?': 'before',
|
||||||
|
':': 'before'
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
'padded-blocks': [2, 'never'],
|
||||||
|
'quotes': [2, 'single', {
|
||||||
|
'avoidEscape': true,
|
||||||
|
'allowTemplateLiterals': true
|
||||||
|
}],
|
||||||
|
'semi': [2, 'never'],
|
||||||
|
'semi-spacing': [2, {
|
||||||
|
'before': false,
|
||||||
|
'after': true
|
||||||
|
}],
|
||||||
|
'space-before-blocks': [2, 'always'],
|
||||||
|
'space-before-function-paren': [2, 'never'],
|
||||||
|
'space-in-parens': [2, 'never'],
|
||||||
|
'space-infix-ops': 2,
|
||||||
|
'space-unary-ops': [2, {
|
||||||
|
'words': true,
|
||||||
|
'nonwords': false
|
||||||
|
}],
|
||||||
|
'spaced-comment': [2, 'always', {
|
||||||
|
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
||||||
|
}],
|
||||||
|
'template-curly-spacing': [2, 'never'],
|
||||||
|
'use-isnan': 2,
|
||||||
|
'valid-typeof': 2,
|
||||||
|
'wrap-iife': [2, 'any'],
|
||||||
|
'yield-star-spacing': [2, 'both'],
|
||||||
|
'yoda': [2, 'never'],
|
||||||
|
'prefer-const': 2,
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
||||||
|
'object-curly-spacing': [2, 'always', {
|
||||||
|
objectsInObjects: false
|
||||||
|
}],
|
||||||
|
'array-bracket-spacing': [2, 'never']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
patreon: panjiachen
|
||||||
|
custom: https://panjiachen.github.io/vue-element-admin-site/donate
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
name: Bug report(报告问题)
|
||||||
|
about: Create a report to help us improve
|
||||||
|
---
|
||||||
|
<!--
|
||||||
|
注意:为更好的解决你的问题,请参考模板提供完整信息,准确描述问题,信息不全的 issue 将被关闭。
|
||||||
|
|
||||||
|
Note: In order to better solve your problem, please refer to the template to provide complete information, accurately describe the problem, and the incomplete information issue will be closed.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
## Bug report(问题描述)
|
||||||
|
|
||||||
|
#### Steps to reproduce(问题复现步骤)
|
||||||
|
<!--
|
||||||
|
1. [xxx]
|
||||||
|
2. [xxx]
|
||||||
|
3. [xxxx]
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Screenshot or Gif(截图或动态图)
|
||||||
|
|
||||||
|
|
||||||
|
#### Link to minimal reproduction(最小可在线还原demo)
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please only use Codepen, JSFiddle, CodeSandbox or a github repo
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Other relevant information(格外信息)
|
||||||
|
- Your OS:
|
||||||
|
- Node.js version:
|
||||||
|
- vue-element-admin version:
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
name: Feature Request(新功能建议)
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
---
|
||||||
|
|
||||||
|
## Feature request(新功能建议)
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
name: Question(提问)
|
||||||
|
about: Asking questions about use
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question(提问)
|
||||||
|
|
||||||
|
<!--
|
||||||
|
提问之前,请确定你已经过自己的努力,尝试解决过这个问题。
|
||||||
|
若是代码相关问题,请不要只截图,请提供在线 demo,以便节约彼此的时间。
|
||||||
|
|
||||||
|
Before asking a question, please make sure that you have tried your best to solve this problem.
|
||||||
|
If it's a code-related issue, please don't just take screenshots. Please provide an online demo to save each other's time.
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Steps to reproduce(问题复现步骤)
|
||||||
|
<!--
|
||||||
|
1. [xxx]
|
||||||
|
2. [xxx]
|
||||||
|
3. [xxxx]
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Screenshot or Gif(截图或动态图)
|
||||||
|
|
||||||
|
|
||||||
|
#### Link to minimal reproduction(最小可在线还原demo)
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please only use Codepen, JSFiddle, CodeSandbox or a github repo
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Other relevant information(格外信息)
|
||||||
|
- Your OS:
|
||||||
|
- Node.js version:
|
||||||
|
- vue-element-admin version:
|
|
@ -1,10 +1,23 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
static/ckeditor
|
npm-debug.log*
|
||||||
gifs/
|
yarn-debug.log*
|
||||||
npm-debug.log
|
yarn-error.log*
|
||||||
test/unit/coverage
|
**/*.log
|
||||||
test/e2e/reports
|
|
||||||
|
tests/**/coverage/
|
||||||
|
tests/e2e/reports
|
||||||
selenium-debug.log
|
selenium-debug.log
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
.idea
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.local
|
||||||
|
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
"plugins": {
|
|
||||||
// to edit target browsers: use "browserlist" field in package.json
|
|
||||||
"autoprefixer": {}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
language: node_js
|
||||||
|
node_js: 10
|
||||||
|
script: npm run test
|
||||||
|
notifications:
|
||||||
|
email: false
|
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 PanJiaChen
|
Copyright (c) 2017-present PanJiaChen
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
177
README-en.md
|
@ -1,177 +0,0 @@
|
||||||
## Intro
|
|
||||||
|
|
||||||
> In the past half year, I have been building a backend for management dashboard using Vue. Though the backend has contained greater than 70 pages and over 10 permissions, it still takes insignificant effort to maintain the project. So I decide to make it open source so as to share my development experience and progress on backend. The tech stack is mainly [Vue.js](https://github.com/vuejs/vue)+[Element](https://github.com/ElemeFE/element)+[axios](https://github.com/mzabriskie/axios). Since it's a personal project, all data requests are simulated with [Mock.js](https://github.com/nuysoft/Mock). **Note:** if anyone wants to modify or develop based on this project, please remove the mock files.
|
|
||||||
|
|
||||||
**Live demo:** http://panjiachen.github.io/vue-element-admin
|
|
||||||
|
|
||||||
**Note: element-ui@1.3.3 is used in the project, so vue 2.3.0+ is required.**
|
|
||||||
|
|
||||||
More tutorials incoming. Including articles on:
|
|
||||||
|
|
||||||
- How to build structure of a backend dashboard project from scratch
|
|
||||||
- How to make a complete user system (e.g. permission authentication, two-factor authentication)
|
|
||||||
- How to package components (e.g. rich text)
|
|
||||||
- How to integrate with [Qiniu](https://www.qiniu.com/)
|
|
||||||
- Other development experience on backend
|
|
||||||
|
|
||||||
Join the group on QQ 591724180.
|
|
||||||
|
|
||||||
**Tutorials:**
|
|
||||||
|
|
||||||
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
|
||||||
- [Step by step instructions on playing with backend using Vue Part 1 - Fundamentals](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
|
|
||||||
- [Step by step instructions on playing with backend using Vue Part 2 - Login permission](https://juejin.im/post/591aa14f570c35006961acac)
|
|
||||||
- [Step by step instructions on packaging a Vue component](https://segmentfault.com/a/1190000009090836)
|
|
||||||
|
|
||||||
**Please read the Wiki and articles above before creating any issue. Feel free to contribute by making a pull request.**
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Login/Logout
|
|
||||||
- Permission authentication
|
|
||||||
- Sidebar
|
|
||||||
- Breadcrumb
|
|
||||||
- Rich text editor
|
|
||||||
- Markdown editor
|
|
||||||
- JSON editor
|
|
||||||
- Drag & drop list
|
|
||||||
- SplitPane
|
|
||||||
- Dropzone
|
|
||||||
- Sticky
|
|
||||||
- CountTo
|
|
||||||
- ECharts
|
|
||||||
- 401, 404 error page
|
|
||||||
- Error log
|
|
||||||
- Exporting to Excel
|
|
||||||
- Table example
|
|
||||||
- Interactive table example
|
|
||||||
- Drag & drop table example
|
|
||||||
- Form example
|
|
||||||
- Multi-environments distribution
|
|
||||||
- Dashboard
|
|
||||||
- Two-factor authentication
|
|
||||||
- Collapsing sidebar (support nested routes)
|
|
||||||
- Mock data
|
|
||||||
- cache tabs example
|
|
||||||
- screenfull
|
|
||||||
- markdown2html
|
|
||||||
- views-tab
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Clone project
|
|
||||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Or (not recommended for cnpm due to unknown bugs, use taobao mirror instead)
|
|
||||||
npm install --registry=https://registry.npm.taobao.org
|
|
||||||
|
|
||||||
# Run local dev server
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
Visit in browser: http://localhost:9527
|
|
||||||
|
|
||||||
## Distribution
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build staged environment with webpack-bundle-analyzer
|
|
||||||
npm run build:sit-preview
|
|
||||||
|
|
||||||
# Build production environment
|
|
||||||
npm run build:prod
|
|
||||||
```
|
|
||||||
|
|
||||||
## Directory structure
|
|
||||||
|
|
||||||
```
|
|
||||||
├── build // build
|
|
||||||
├── config // config
|
|
||||||
├── src // source code
|
|
||||||
│ ├── api // all requests
|
|
||||||
│ ├── assets // static resource like themes, fonts
|
|
||||||
│ ├── components // global public components
|
|
||||||
│ ├── directive // global directive
|
|
||||||
│ ├── filters // global filters
|
|
||||||
│ ├── mock // mock data
|
|
||||||
│ ├── router // router
|
|
||||||
│ ├── store // global status management
|
|
||||||
│ ├── styles // global styles
|
|
||||||
│ ├── utils // global public functions
|
|
||||||
│ ├── view // view
|
|
||||||
│ ├── App.vue // entry view
|
|
||||||
│ └── main.js // entry for loading components, initialization
|
|
||||||
├── static // third-party libraries not packed with Webpack
|
|
||||||
│ ├── jquery
|
|
||||||
│ └── Tinymce // rich text
|
|
||||||
├── .babelrc // babel-loader config
|
|
||||||
├── eslintrc.js // eslint config
|
|
||||||
├── .gitignore // gitignore
|
|
||||||
├── favicon.ico // favicon
|
|
||||||
├── index.html // html template
|
|
||||||
└── package.json // package.json
|
|
||||||
```
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
|
|
||||||
|
|
||||||
## State Management
|
|
||||||
|
|
||||||
Only status of user and app configuration is managed by Vuex. Other data are managed by their own business pages.
|
|
||||||
|
|
||||||
## Demo
|
|
||||||
|
|
||||||
#### Two-factor authentication, supporting WeChat and QQ
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/2login.gif)
|
|
||||||
|
|
||||||
#### Realtime switching themes
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/theme.gif)
|
|
||||||
|
|
||||||
#### tabs
|
|
||||||
|
|
||||||
![tabs](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/tabs.gif)<br />
|
|
||||||
|
|
||||||
#### Collapsing sidebar
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/leftmenu.gif)
|
|
||||||
|
|
||||||
#### Drag & drop table
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/order.gif)
|
|
||||||
|
|
||||||
#### Interactive table
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/dynamictable.gif)
|
|
||||||
|
|
||||||
#### Uploading cropped avatar
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/uploadAvatar.gif)
|
|
||||||
|
|
||||||
#### Error log
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/errorlog.gif)
|
|
||||||
|
|
||||||
#### Rich text (integrated with Qiniu, watermark and customization)
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/editor.gif)
|
|
||||||
|
|
||||||
#### Packaging table component
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/table.gif)
|
|
||||||
|
|
||||||
#### Charts
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/echarts.gif)
|
|
||||||
|
|
||||||
#### Exporting to Excel
|
|
||||||
|
|
||||||
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/excel.png)
|
|
||||||
|
|
||||||
#### More
|
|
||||||
|
|
||||||
http://panjiachen.github.io/vue-element-admin
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
<p align="center">
|
||||||
|
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/vuejs/vue">
|
||||||
|
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/ElemeFE/element">
|
||||||
|
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
|
||||||
|
</a>
|
||||||
|
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||||
|
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Estado de Construcción">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="Licencia">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||||
|
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="Liberación Github">
|
||||||
|
</a>
|
||||||
|
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||||
|
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="Gitter">
|
||||||
|
</a>
|
||||||
|
<a href="https://panjiachen.github.io/vue-element-admin-site/donate">
|
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="Donación">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Español | [English](./README.md) | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md)
|
||||||
|
|
||||||
|
## Introducción
|
||||||
|
|
||||||
|
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) es una interfáz de administración preparada para producción. Está basada en [vue](https://github.com/vuejs/vue) y usa [element-ui](https://github.com/ElemeFE/element) como conjunto de herramientas de interfáz de usuario.
|
||||||
|
|
||||||
|
Vue Element Admin es una solución práctica basada en la nueva plataforma de desarrollo de vue, construida con soporte a i18 para el manejo de múltiples lenguajes, plantillas estándares para aplicaciones de negocio y un conjunto de asombrosas características. Esta herramienta ayuda a construir largas y complejas Aplicacones de una sola página (SPA). Creo que lo que necesites hacer, este proyecto te ayudará.
|
||||||
|
|
||||||
|
- [Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
|
- [Documentación](https://panjiachen.github.io/vue-element-admin-site/)
|
||||||
|
|
||||||
|
- [Canal de Gitter](https://gitter.im/vue-element-admin/discuss)
|
||||||
|
|
||||||
|
- [Para Donaciones](https://panjiachen.github.io/vue-element-admin-site/donate/)
|
||||||
|
|
||||||
|
- [Enlace de Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||||
|
|
||||||
|
- [Canal de Gitee](https://panjiachen.gitee.io/vue-element-admin/)
|
||||||
|
|
||||||
|
- Plantilla base recomendada para usar: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||||
|
- Aplicación de Escritorio: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||||
|
- Plantilla de Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Créditos: [@Armour](https://github.com/Armour))
|
||||||
|
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
|
||||||
|
|
||||||
|
**Después de la versión `v4.1.0+`, la rama por defecto master no tendrá soporte para i18n. Por favor utilice la rama [i18n](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), los cambios serán incluidos en la rama master**
|
||||||
|
|
||||||
|
**la versión actual es `v4.0+` construida con `vue-cli`. Si encuentra algún problema, por favor coloque un [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). Si desea usar la versión anterior, puede cambiar de rama a [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0), no relacionado con `vue-cli`**
|
||||||
|
|
||||||
|
**Este proyecto no está soportado para versiones antigüas de navegadores (ej. IE).**
|
||||||
|
|
||||||
|
## Preparación
|
||||||
|
|
||||||
|
Necesita instalar [node](https://nodejs.org/) y [git](https://git-scm.com/) localmente. El proyecto es basado en [ES2015+](https://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), toda la solicitud de datos simulada se realiza a través de [Mock.js](https://github.com/nuysoft/Mock).
|
||||||
|
Entendiendo y aprendiendo esto pudiera ayudarle con su proyecto.
|
||||||
|
|
||||||
|
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Patrocinantes
|
||||||
|
|
||||||
|
Sea un patrocinante y coloque su logo en nuestro LEEME en GitHub con un enlace directo a su sitio web. [[Se un Patrocinante]](https://www.patreon.com/panjiachen)
|
||||||
|
|
||||||
|
### Akveo
|
||||||
|
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Get Java backend for Vue admin with 20% discount for 39$ use coupon code SWB0RAZPZR1M
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### Flatlogic
|
||||||
|
|
||||||
|
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
||||||
|
|
||||||
|
## Características
|
||||||
|
|
||||||
|
```
|
||||||
|
- Iniciar / Cerrar Sesión
|
||||||
|
|
||||||
|
- Permisos de Autenticación
|
||||||
|
- Página de Permisos
|
||||||
|
- Directivas de permisos
|
||||||
|
- Página de configuración de permisos
|
||||||
|
- Autenticación por dos pasos
|
||||||
|
|
||||||
|
- Construcción Multi-entorno
|
||||||
|
- Desarrollo (dev)
|
||||||
|
- sit
|
||||||
|
- Escenario de pruebas (stage),
|
||||||
|
- Producción (prod)
|
||||||
|
|
||||||
|
- Características Globales
|
||||||
|
- I18n
|
||||||
|
- Temas dinámicos
|
||||||
|
- Menu lateral dinámico (soporte a rutas multi-nivel)
|
||||||
|
- Barra de rutas dinámica
|
||||||
|
- Tags-view (Pestañas de página, Soporta operación de clic derecho)
|
||||||
|
- Svg Sprite
|
||||||
|
- Datos de simulación con Mock
|
||||||
|
- Pantalla completa
|
||||||
|
- Menu lateral responsivo
|
||||||
|
|
||||||
|
- Editor
|
||||||
|
- Editor de Texto Enriquecido
|
||||||
|
- Editor Markdown
|
||||||
|
- Editor JSON
|
||||||
|
|
||||||
|
- Excel
|
||||||
|
- Exportación a Excel
|
||||||
|
- Carga de Excel
|
||||||
|
- Visualización de Excel
|
||||||
|
- Exportación como ZIP
|
||||||
|
|
||||||
|
- Tabla
|
||||||
|
- Tabla Dinámica
|
||||||
|
- Tabla con Arrastrar y Soltar
|
||||||
|
- Tabla de edición en línea
|
||||||
|
|
||||||
|
- Páginas de Error
|
||||||
|
- 401
|
||||||
|
- 404
|
||||||
|
|
||||||
|
- Componentes
|
||||||
|
- Carga de Avatar
|
||||||
|
- Botón para subir al inicio
|
||||||
|
- Arrastrar y Soltar (Diaglogo)
|
||||||
|
- Arrastrar y Soltar (Seleccionar)
|
||||||
|
- Arrastrar y Soltar (Kanban)
|
||||||
|
- Arrastrar y Soltar (Lista)
|
||||||
|
- Panel de división
|
||||||
|
- Componente para soltar archivos
|
||||||
|
- Adhesión de objetos
|
||||||
|
- Contador hasta
|
||||||
|
|
||||||
|
- Ejemplo Avanzado
|
||||||
|
- Registro de Errores
|
||||||
|
- Tablero de indicadores
|
||||||
|
- Página de Guías
|
||||||
|
- ECharts (Gráficos)
|
||||||
|
- Portapapeles
|
||||||
|
- Convertidor de Markdown a HTML
|
||||||
|
```
|
||||||
|
|
||||||
|
## Iniciando
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# clone el proyecto
|
||||||
|
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||||
|
|
||||||
|
# vaya al directorio clonado
|
||||||
|
cd vue-element-admin
|
||||||
|
|
||||||
|
# instale las dependencias
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# corra el proyecto como desarrollador
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Automáticamente se abrirá el siguiente enlace en su navegador http://localhost:9527
|
||||||
|
|
||||||
|
## Construcción
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Construcción para entornos de prueba
|
||||||
|
npm run build:stage
|
||||||
|
|
||||||
|
# Construcción para entornos de producción
|
||||||
|
npm run build:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
## Avanzado
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vista previa con efectos de entorno
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# Vista previa con efectos + análisis de recursos estáticos
|
||||||
|
npm run preview -- --report
|
||||||
|
|
||||||
|
# Chequeo de formato de código
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# Chequeo de formato de código y auto-corrección
|
||||||
|
npm run lint -- --fix
|
||||||
|
```
|
||||||
|
|
||||||
|
Vaya a [Documentación](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) para mayor información
|
||||||
|
|
||||||
|
## Registro de Cambios
|
||||||
|
|
||||||
|
Los cambios detallados por cada liberación se encuentran en [notas de liberación](https://github.com/PanJiaChen/vue-element-admin/releases).
|
||||||
|
|
||||||
|
## Demostración en línea
|
||||||
|
|
||||||
|
[Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
|
## Donación
|
||||||
|
|
||||||
|
Si este proyecto es de mucha ayuda para ti, puedes comprarle al autor un vaso de jugo :tropical_drink:
|
||||||
|
|
||||||
|
![Donar](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
|
||||||
|
|
||||||
|
[dona por Paypal](https://www.paypal.me/panfree23)
|
||||||
|
|
||||||
|
[Comprame un Café](https://www.buymeacoffee.com/Pan)
|
||||||
|
|
||||||
|
## Navegadores Soportados
|
||||||
|
|
||||||
|
Navegadores modernos e Internet Explorer 10+.
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
|
| --------- | --------- | --------- | --------- |
|
||||||
|
| IE10, IE11, Edge | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones |
|
||||||
|
|
||||||
|
## Licencia
|
||||||
|
|
||||||
|
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||||
|
|
||||||
|
Copyright (c) 2017-presente PanJiaChen
|
|
@ -0,0 +1,224 @@
|
||||||
|
<p align="center">
|
||||||
|
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/vuejs/vue">
|
||||||
|
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/ElemeFE/element">
|
||||||
|
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
|
||||||
|
</a>
|
||||||
|
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||||
|
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||||
|
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||||
|
</a>
|
||||||
|
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||||
|
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
|
||||||
|
</a>
|
||||||
|
<a href="https://panjiachen.gitee.io/vue-element-admin-site/zh/donate">
|
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
日本語 | [English](./README.md) | [简体中文](./README.zh-CN.md) | [Spanish](./README.es.md)
|
||||||
|
|
||||||
|
## 概要
|
||||||
|
|
||||||
|
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) は管理画面のフロントエンドのインタフェースで、[vue](https://github.com/vuejs/vue) と [element-ui](https://github.com/ElemeFE/element)を使っています。i18nの多言語対応、可変ルート、権限、典型的なビジネスアプリテンプレートであり、豊富なコンポーネントを提供しています。素早くビジネス用の管理画面の現型を構築に役立ちます。
|
||||||
|
|
||||||
|
- [デモページ](https://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
|
- [ドキュメント](https://panjiachen.github.io/vue-element-admin-site/)
|
||||||
|
|
||||||
|
- [Gitter](https://gitter.im/vue-element-admin/discuss)
|
||||||
|
|
||||||
|
- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
|
||||||
|
|
||||||
|
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||||
|
|
||||||
|
- おすすめシンプルテンプレート: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||||
|
- デスクトップバージョン: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||||
|
- Typescriptバージョン: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (感謝: [@Armour](https://github.com/Armour))
|
||||||
|
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
|
||||||
|
|
||||||
|
**バージョン`v4.1.0+`以降について、デフォルトのmasterブランチではi18nをサポートしていません。masterブランチと共にアップデートされる[i18n Branch](https://github.com/PanJiaChen/vue-element-admin/tree/i18n)を使用してください。 **
|
||||||
|
|
||||||
|
**現在のバージョン `v4.0+` は `vue-cli` で構築していて、バグ報告は[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)のissueでお願いします。旧バージョン[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)もあります。こちらは`vue-cli`に依存しないです。**
|
||||||
|
|
||||||
|
**低いバージョンのブラウザはサーポートしないです(例えば ie),必要があれば polyfill を追加してください。 [詳細はこちら](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
|
||||||
|
|
||||||
|
## 前準備
|
||||||
|
|
||||||
|
ローカル環境に [node](http://nodejs.org/) と [git](https://git-scm.com/)のインストールが必要です。[ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) と [element-ui](https://github.com/ElemeFE/element)で開発しています。Requestは[Mock.js](https://github.com/nuysoft/Mock)のモックデータを使っています。
|
||||||
|
|
||||||
|
**バグ修正や新規機能追加のissue と pull requestは大歓迎です。**
|
||||||
|
|
||||||
|
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
|
||||||
|
|
||||||
|
### Akveo
|
||||||
|
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Get Java backend for Vue admin with 20% discount for 39$ use coupon code SWB0RAZPZR1M
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### Flatlogic
|
||||||
|
|
||||||
|
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
||||||
|
|
||||||
|
## 機能一覧
|
||||||
|
|
||||||
|
```
|
||||||
|
- ログイン / ログアウト
|
||||||
|
|
||||||
|
- Auth認証
|
||||||
|
- ページ権限
|
||||||
|
- 権限パーミッション
|
||||||
|
- 権限設定
|
||||||
|
- 外部IDでログイン
|
||||||
|
|
||||||
|
- 複数環境デプロイ
|
||||||
|
- dev
|
||||||
|
- sit
|
||||||
|
- stage
|
||||||
|
- prod
|
||||||
|
|
||||||
|
- 共通機能
|
||||||
|
- 多言語切替
|
||||||
|
- テーマ切替
|
||||||
|
- サイトメニュー(ルートから生成)
|
||||||
|
- パンくずリストナビゲーション
|
||||||
|
- タブナビゲーション
|
||||||
|
- Svg Sprite アイコン
|
||||||
|
- ローカル/バックエンド モック データ
|
||||||
|
- Screenfull
|
||||||
|
|
||||||
|
- WYSIWYG
|
||||||
|
- TinyMCE
|
||||||
|
- Markdown
|
||||||
|
- JSON
|
||||||
|
|
||||||
|
- Excel
|
||||||
|
- エクスポート
|
||||||
|
- インポート
|
||||||
|
- リード
|
||||||
|
- Zip
|
||||||
|
|
||||||
|
- テーブル
|
||||||
|
- ダイナミックテーブル
|
||||||
|
- ドラッグアンドドロップテーブル
|
||||||
|
- インラインエディットテーブル
|
||||||
|
|
||||||
|
- エラーページ
|
||||||
|
- 401
|
||||||
|
- 404
|
||||||
|
|
||||||
|
- コンポーネント
|
||||||
|
- アバターアップロード
|
||||||
|
- トップに戻る
|
||||||
|
- ドラッグダイアログ
|
||||||
|
- ドラッグ選択
|
||||||
|
- ドラッグKanban
|
||||||
|
- ドラッグリスト
|
||||||
|
- ペインの分割
|
||||||
|
- Dropzone
|
||||||
|
- スティッキー
|
||||||
|
- CountTo
|
||||||
|
|
||||||
|
- 高度なサンプル
|
||||||
|
- エラーログ
|
||||||
|
- ダッシュボード
|
||||||
|
- ガイドページ
|
||||||
|
- ECharts
|
||||||
|
- クリップボード
|
||||||
|
- Markdown to html
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# clone the project
|
||||||
|
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||||
|
|
||||||
|
# enter the project directory
|
||||||
|
cd vue-element-admin
|
||||||
|
|
||||||
|
# install dependency
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# develop
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
http://localhost:9527 が自動的に開きます。
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# build for test environment
|
||||||
|
npm run build:stage
|
||||||
|
|
||||||
|
# build for production environment
|
||||||
|
npm run build:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# preview the release environment effect
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# preview the release environment effect + static resource analysis
|
||||||
|
npm run preview -- --report
|
||||||
|
|
||||||
|
# code format check
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# code format check and auto fix
|
||||||
|
npm run lint -- --fix
|
||||||
|
```
|
||||||
|
|
||||||
|
詳細は [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) を参照してください。
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
各リリースの詳細は [release notes](https://github.com/PanJiaChen/vue-element-admin/releases) にあります。
|
||||||
|
|
||||||
|
## Online Demo
|
||||||
|
|
||||||
|
[Preview](https://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
|
## Donate
|
||||||
|
|
||||||
|
If you find this project useful, you can buy author a glass of juice :tropical_drink:
|
||||||
|
|
||||||
|
![donate](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
|
||||||
|
|
||||||
|
[Paypal Me](https://www.paypal.me/panfree23)
|
||||||
|
|
||||||
|
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
|
||||||
|
|
||||||
|
## Browsers support
|
||||||
|
|
||||||
|
Modern browsers and Internet Explorer 10+.
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
|
| --------- | --------- | --------- | --------- |
|
||||||
|
| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions |
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||||
|
|
||||||
|
Copyright (c) 2017-present PanJiaChen
|
340
README.md
|
@ -1,192 +1,250 @@
|
||||||
# vue-element-admin #
|
<p align="center">
|
||||||
[线上地址](http://panjiachen.github.io/vue-element-admin)
|
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
|
||||||
|
</p>
|
||||||
|
|
||||||
[English Document](https://github.com/PanJiaChen/vue-element-admin/blob/master/README-en.md)
|
<p align="center">
|
||||||
|
<a href="https://github.com/vuejs/vue">
|
||||||
|
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/ElemeFE/element">
|
||||||
|
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
|
||||||
|
</a>
|
||||||
|
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||||
|
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||||
|
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||||
|
</a>
|
||||||
|
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||||
|
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
|
||||||
|
</a>
|
||||||
|
<a href="https://panjiachen.github.io/vue-element-admin-site/donate">
|
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
[wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
English | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md) | [Spanish](./README.es.md)
|
||||||
|
|
||||||
**本项目的定位是后台集成方案,不适合当基础模板来开发,模板建议使用 [vueAdmin-template](https://github.com/PanJiaChen/vueAdmin-template) , 桌面端 [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)**
|
<p align="center">
|
||||||
|
<b>SPONSORED BY</b>
|
||||||
|
</p>
|
||||||
|
<table align="center" cellspacing="0" cellpadding="0">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="middle" width="250">
|
||||||
|
<a href="https://www.duohui.cn/?utm_source=vue-element-admin&utm_medium=web&utm_campaign=vue-element-admin_github" title="多会" target="_blank">
|
||||||
|
<img height="60px" src="https://qiniu.cdn.duohui.co/brand/duohui.png" title="多会 - 活动服务销售平台">
|
||||||
|
<p>活动服务销售平台</p>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center" valign="middle" width="250">
|
||||||
|
<a href="https://youke.co/?utm_source=vue-element-admin&utm_medium=web&utm_campaign=vue-element-admin_github" title="有客" target="_blank">
|
||||||
|
<img height="60px" src="https://qiniu.cdn.duohui.co/brand/youke.png" title="有客 - 客户消息直达工作群">
|
||||||
|
<p>客户消息直达工作群</p>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) is a production-ready front-end solution for admin interfaces. It is based on [vue](https://github.com/vuejs/vue) and uses the UI Toolkit [element-ui](https://github.com/ElemeFE/element).
|
||||||
|
|
||||||
**注意:该项目目前使用element-ui@1.3.3版本,所以最低兼容 Vue 2.3.0**
|
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) is based on the newest development stack of vue and it has a built-in i18n solution, typical templates for enterprise applications, and lots of awesome features. It helps you build large and complex Single-Page Applications. I believe whatever your needs are, this project will help you.
|
||||||
|
|
||||||
## 前言
|
- [Preview](https://panjiachen.github.io/vue-element-admin)
|
||||||
> 这半年来一直在用vue写管理后台,目前后台已经有百来个页面,十几种权限,但维护成本依然很低,所以准备开源分享一下后台开发的经验和成果。目前的技术栈主要的采用vue+element+axios由webpack2打包。由于是个人项目,所以数据请求都是用了mockjs模拟。注意:在此项目基础上改造开发时请移除mock文件。
|
|
||||||
|
|
||||||
|
- [Documentation](https://panjiachen.github.io/vue-element-admin-site/)
|
||||||
|
|
||||||
写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
|
- [Gitter](https://gitter.im/vue-element-admin/discuss)
|
||||||
|
|
||||||
- [wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
- [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/)
|
||||||
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
|
|
||||||
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
|
|
||||||
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
|
|
||||||
- [手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
|
|
||||||
- [手摸手,带你封装一个vue component](https://segmentfault.com/a/1190000009090836)
|
|
||||||
|
|
||||||
相应需求,开了一个qq群 `591724180` 方便大家交流
|
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||||
|
|
||||||
**如有问题请先看上述文章和Wiki,若不能满足,欢迎 issue 和 pr ~**
|
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
|
||||||
|
|
||||||
**该项目并不是一个脚手架,更倾向于是一个集成解决方案**
|
- Base template recommends using: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||||
|
- Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||||
|
- Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
|
||||||
|
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
|
||||||
|
|
||||||
**该项目不支持低版本游览器,有需求请自行添加polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
|
**After the `v4.1.0+` version, the default master branch will not support i18n. Please use [i18n Branch](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), it will keep up with the master update**
|
||||||
|
|
||||||
|
**The current version is `v4.0+` build on `vue-cli`. If you find a problem, please put [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0), it does not rely on `vue-cli`**
|
||||||
|
|
||||||
## 功能
|
**This project does not support low version browsers (e.g. IE). Please add polyfill by yourself.**
|
||||||
- 登录/注销
|
|
||||||
- 权限验证
|
## Preparation
|
||||||
- 侧边栏
|
|
||||||
- 面包屑
|
You need to install [node](https://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [ES2015+](https://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), all request data is simulated using [Mock.js](https://github.com/nuysoft/Mock).
|
||||||
- 富文本编辑器
|
Understanding and learning this knowledge in advance will greatly help the use of this project.
|
||||||
- Markdown编辑器
|
|
||||||
- JSON编辑器
|
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
|
||||||
- 列表拖拽
|
|
||||||
- plitPane
|
<p align="center">
|
||||||
|
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
|
||||||
|
|
||||||
|
### Akveo
|
||||||
|
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Get Java backend for Vue admin with 20% discount for 39$ use coupon code SWB0RAZPZR1M
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### Flatlogic
|
||||||
|
|
||||||
|
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
```
|
||||||
|
- Login / Logout
|
||||||
|
|
||||||
|
- Permission Authentication
|
||||||
|
- Page permission
|
||||||
|
- Directive permission
|
||||||
|
- Permission configuration page
|
||||||
|
- Two-step login
|
||||||
|
|
||||||
|
- Multi-environment build
|
||||||
|
- Develop (dev)
|
||||||
|
- sit
|
||||||
|
- Stage Test (stage)
|
||||||
|
- Production (prod)
|
||||||
|
|
||||||
|
- Global Features
|
||||||
|
- I18n
|
||||||
|
- Multiple dynamic themes
|
||||||
|
- Dynamic sidebar (supports multi-level routing)
|
||||||
|
- Dynamic breadcrumb
|
||||||
|
- Tags-view (Tab page Support right-click operation)
|
||||||
|
- Svg Sprite
|
||||||
|
- Mock data
|
||||||
|
- Screenfull
|
||||||
|
- Responsive Sidebar
|
||||||
|
|
||||||
|
- Editor
|
||||||
|
- Rich Text Editor
|
||||||
|
- Markdown Editor
|
||||||
|
- JSON Editor
|
||||||
|
|
||||||
|
- Excel
|
||||||
|
- Export Excel
|
||||||
|
- Upload Excel
|
||||||
|
- Visualization Excel
|
||||||
|
- Export zip
|
||||||
|
|
||||||
|
- Table
|
||||||
|
- Dynamic Table
|
||||||
|
- Drag And Drop Table
|
||||||
|
- Inline Edit Table
|
||||||
|
|
||||||
|
- Error Page
|
||||||
|
- 401
|
||||||
|
- 404
|
||||||
|
|
||||||
|
- Components
|
||||||
|
- Avatar Upload
|
||||||
|
- Back To Top
|
||||||
|
- Drag Dialog
|
||||||
|
- Drag Select
|
||||||
|
- Drag Kanban
|
||||||
|
- Drag List
|
||||||
|
- SplitPane
|
||||||
- Dropzone
|
- Dropzone
|
||||||
- Sticky
|
- Sticky
|
||||||
- CountTo
|
- CountTo
|
||||||
- echarts图表
|
|
||||||
- 401,404错误页面
|
|
||||||
- 错误日志
|
|
||||||
- 导出excel
|
|
||||||
- table example
|
|
||||||
- 动态table example
|
|
||||||
- 拖拽table example
|
|
||||||
- 内联编辑table example
|
|
||||||
- form example
|
|
||||||
- 多环境发布
|
|
||||||
- dashboard
|
|
||||||
- 二次登录
|
|
||||||
- 动态侧边栏(支持多级路由)
|
|
||||||
- mock数据
|
|
||||||
- cache tabs example
|
|
||||||
- screenfull
|
|
||||||
- markdown2html
|
|
||||||
- views-tab
|
|
||||||
|
|
||||||
|
- Advanced Example
|
||||||
|
- Error Log
|
||||||
|
- Dashboard
|
||||||
|
- Guide Page
|
||||||
|
- ECharts
|
||||||
|
- Clipboard
|
||||||
|
- Markdown to html
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
## 开发
|
|
||||||
```bash
|
```bash
|
||||||
# 克隆项目
|
# clone the project
|
||||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||||
|
|
||||||
# 安装依赖
|
# enter the project directory
|
||||||
npm install
|
cd vue-element-admin
|
||||||
//or # 建议不要用cnpm 安装有各种诡异的bug 可以通过如下操作解决npm速度慢的问题
|
|
||||||
npm install --registry=https://registry.npm.taobao.org
|
|
||||||
|
|
||||||
# 本地开发 开启服务
|
# install dependency
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# develop
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
浏览器访问 http://localhost:9527
|
|
||||||
|
|
||||||
## 发布
|
This will automatically open http://localhost:9527
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 发布测试环境 带webpack ananalyzer
|
# build for test environment
|
||||||
npm run build:sit-preview
|
npm run build:stage
|
||||||
|
|
||||||
# 构建生成环境
|
# build for production environment
|
||||||
npm run build:prod
|
npm run build:prod
|
||||||
```
|
```
|
||||||
|
|
||||||
## 目录结构
|
## Advanced
|
||||||
```shell
|
|
||||||
├── build // 构建相关
|
|
||||||
├── config // 配置相关
|
|
||||||
├── src // 源代码
|
|
||||||
│ ├── api // 所有请求
|
|
||||||
│ ├── assets // 主题 字体等静态资源
|
|
||||||
│ ├── components // 全局公用组件
|
|
||||||
│ ├── directive // 全局指令
|
|
||||||
│ ├── filtres // 全局filter
|
|
||||||
│ ├── mock // mock数据
|
|
||||||
│ ├── router // 路由
|
|
||||||
│ ├── store // 全局store管理
|
|
||||||
│ ├── styles // 全局样式
|
|
||||||
│ ├── utils // 全局公用方法
|
|
||||||
│ ├── view // view
|
|
||||||
│ ├── App.vue // 入口页面
|
|
||||||
│ └── main.js // 入口 加载组件 初始化等
|
|
||||||
├── static // 第三方不打包资源
|
|
||||||
│ ├── jquery
|
|
||||||
│ └── Tinymce // 富文本
|
|
||||||
├── .babelrc // babel-loader 配置
|
|
||||||
├── eslintrc.js // eslint 配置项
|
|
||||||
├── .gitignore // git 忽略项
|
|
||||||
├── favicon.ico // favicon图标
|
|
||||||
├── index.html // html模板
|
|
||||||
└── package.json // package.json
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# preview the release environment effect
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# preview the release environment effect + static resource analysis
|
||||||
|
npm run preview -- --report
|
||||||
|
|
||||||
|
# code format check
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# code format check and auto fix
|
||||||
|
npm run lint -- --fix
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
|
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
|
||||||
|
|
||||||
## 状态管理
|
## Online Demo
|
||||||
后台只有user和app配置相关状态使用vuex存在全局,其它数据都由每个业务页面自己管理。
|
|
||||||
|
|
||||||
|
[Preview](https://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
## 效果图
|
## Donate
|
||||||
|
|
||||||
#### 两步验证登录 支持微信和qq
|
If you find this project useful, you can buy author a glass of juice :tropical_drink:
|
||||||
|
|
||||||
![两步验证 here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/2login.gif)
|
![donate](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
|
||||||
|
|
||||||
#### 真正的动态换肤
|
[Paypal Me](https://www.paypal.me/panfree23)
|
||||||
|
|
||||||
![真正的动态换肤](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/theme.gif)<br />
|
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
|
||||||
|
|
||||||
#### tabs
|
## Browsers support
|
||||||
|
|
||||||
![tabs](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/tabs.gif)<br />
|
Modern browsers and Internet Explorer 10+.
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
|
| --------- | --------- | --------- | --------- |
|
||||||
#### 可收起侧边栏
|
| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions |
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/leftmenu.gif)
|
|
||||||
|
|
||||||
#### table拖拽排序
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/order.gif)
|
|
||||||
|
|
||||||
|
|
||||||
#### 动态table
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/dynamictable.gif)
|
|
||||||
|
|
||||||
|
|
||||||
#### 上传裁剪头像
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/uploadAvatar.gif)
|
|
||||||
|
|
||||||
|
|
||||||
#### 错误统计
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/errorlog.gif)
|
|
||||||
|
|
||||||
|
|
||||||
#### 富文本(整合七牛 打水印等个性化功能)
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/editor.gif)
|
|
||||||
|
|
||||||
#### 封装table组件
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/table.gif)
|
|
||||||
|
|
||||||
#### 图表
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/echarts.gif)
|
|
||||||
|
|
||||||
|
|
||||||
#### 导出excel
|
|
||||||
|
|
||||||
![enter image description here](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/excel.png)
|
|
||||||
|
|
||||||
|
|
||||||
## [查看更多demo](http://panjiachen.github.io/vue-element-admin)
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||||
|
|
||||||
|
Copyright (c) 2017-present PanJiaChen
|
||||||
|
|
|
@ -0,0 +1,273 @@
|
||||||
|
<p align="center">
|
||||||
|
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/vuejs/vue">
|
||||||
|
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/ElemeFE/element">
|
||||||
|
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
|
||||||
|
</a>
|
||||||
|
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||||
|
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||||
|
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||||
|
</a>
|
||||||
|
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||||
|
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
|
||||||
|
</a>
|
||||||
|
<a href="https://panjiachen.gitee.io/vue-element-admin-site/zh/donate">
|
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
简体中文 | [English](./README.md) | [日本語](./README.ja.md) | [Spanish](./README.es.md)
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<b>SPONSORED BY</b>
|
||||||
|
</p>
|
||||||
|
<table align="center" cellspacing="0" cellpadding="0">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="middle" width="250">
|
||||||
|
<a href="https://www.duohui.cn/?utm_source=vue-element-admin&utm_medium=web&utm_campaign=vue-element-admin_github" title="多会" target="_blank">
|
||||||
|
<img height="60px" src="https://qiniu.cdn.duohui.co/brand/duohui.png" title="多会 - 活动服务销售平台">
|
||||||
|
<p>活动服务销售平台</p>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center" valign="middle" width="250">
|
||||||
|
<a href="https://youke.co/?utm_source=vue-element-admin&utm_medium=web&utm_campaign=vue-element-admin_github" title="有客" target="_blank">
|
||||||
|
<img height="60px" src="https://qiniu.cdn.duohui.co/brand/youke.png" title="有客 - 客户消息直达工作群">
|
||||||
|
<p>客户消息直达工作群</p>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) 是一个后台前端解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element-ui](https://github.com/ElemeFE/element)实现。它使用了最新的前端技术栈,内置了 i18n 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
|
||||||
|
|
||||||
|
- [在线预览](https://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
|
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
|
||||||
|
|
||||||
|
- [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
|
||||||
|
|
||||||
|
- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
|
||||||
|
|
||||||
|
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||||
|
|
||||||
|
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 在线预览(国内用户可访问该地址)
|
||||||
|
|
||||||
|
- [国内访问文档](https://panjiachen.gitee.io/vue-element-admin-site/zh/) 文档(方便没翻墙的用户查看)
|
||||||
|
|
||||||
|
- 基础模板建议使用: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||||
|
- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||||
|
- Typescript 版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
|
||||||
|
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
|
||||||
|
|
||||||
|
**`v4.1.0+`版本之后默认 master 分支将不支持国际化,有需要的请使用[i18n](https://github.com/PanJiaChen/vue-element-admin/tree/i18n)分支,它会和 master 保持同步更新**
|
||||||
|
|
||||||
|
**该项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
|
||||||
|
|
||||||
|
**目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若发现问题,欢迎提[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)。若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0),它不依赖 `vue-cli`**
|
||||||
|
|
||||||
|
群主 **[圈子](https://jianshiapp.com/circles/1209)** 群主会经常分享一些技术相关的东西,或者加入 [qq 群](https://github.com/PanJiaChen/vue-element-admin/issues/602) 或者关注 [微博](https://weibo.com/u/3423485724?is_all=1)
|
||||||
|
|
||||||
|
## 前序准备
|
||||||
|
|
||||||
|
你需要在本地安装 [node](http://nodejs.org/) 和 [git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)进行模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。
|
||||||
|
|
||||||
|
同时配套了系列教程文章,如何从零构建后一个完整的后台项目,建议大家先看完这些文章再来实践本项目
|
||||||
|
|
||||||
|
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
|
||||||
|
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
|
||||||
|
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
|
||||||
|
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
|
||||||
|
- [手摸手,带你用vue撸后台 系列五(v4.0新版本)](https://juejin.im/post/5c92ff94f265da6128275a85)
|
||||||
|
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
|
||||||
|
- [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
|
||||||
|
- [手摸手,带你用合理的姿势使用 webpack4(上)](https://juejin.im/post/5b56909a518825195f499806)
|
||||||
|
- [手摸手,带你用合理的姿势使用 webpack4(下)](https://juejin.im/post/5b5d6d6f6fb9a04fea58aabc)
|
||||||
|
|
||||||
|
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr**
|
||||||
|
|
||||||
|
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
|
||||||
|
|
||||||
|
### Akveo
|
||||||
|
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Java 后端整合,可以使用优惠码:SWB0RAZPZR1M,获得20%的价格优化</p>
|
||||||
|
|
||||||
|
### Flatlogic
|
||||||
|
|
||||||
|
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
||||||
|
|
||||||
|
|
||||||
|
## 功能
|
||||||
|
|
||||||
|
```
|
||||||
|
- 登录 / 注销
|
||||||
|
|
||||||
|
- 权限验证
|
||||||
|
- 页面权限
|
||||||
|
- 指令权限
|
||||||
|
- 权限配置
|
||||||
|
- 二步登录
|
||||||
|
|
||||||
|
- 多环境发布
|
||||||
|
- dev
|
||||||
|
- sit
|
||||||
|
- stage
|
||||||
|
- prod
|
||||||
|
|
||||||
|
- 全局功能
|
||||||
|
- 国际化多语言
|
||||||
|
- 多种动态换肤
|
||||||
|
- 动态侧边栏(支持多级路由嵌套)
|
||||||
|
- 动态面包屑
|
||||||
|
- 快捷导航(标签页)
|
||||||
|
- Svg Sprite 图标
|
||||||
|
- 本地/后端 mock 数据
|
||||||
|
- Screenfull全屏
|
||||||
|
- 自适应收缩侧边栏
|
||||||
|
|
||||||
|
- 编辑器
|
||||||
|
- 富文本
|
||||||
|
- Markdown
|
||||||
|
- JSON 等多格式
|
||||||
|
|
||||||
|
- Excel
|
||||||
|
- 导出excel
|
||||||
|
- 导入excel
|
||||||
|
- 前端可视化excel
|
||||||
|
- 导出zip
|
||||||
|
|
||||||
|
- 表格
|
||||||
|
- 动态表格
|
||||||
|
- 拖拽表格
|
||||||
|
- 内联编辑
|
||||||
|
|
||||||
|
- 错误页面
|
||||||
|
- 401
|
||||||
|
- 404
|
||||||
|
|
||||||
|
- 組件
|
||||||
|
- 头像上传
|
||||||
|
- 返回顶部
|
||||||
|
- 拖拽Dialog
|
||||||
|
- 拖拽Select
|
||||||
|
- 拖拽看板
|
||||||
|
- 列表拖拽
|
||||||
|
- SplitPane
|
||||||
|
- Dropzone
|
||||||
|
- Sticky
|
||||||
|
- CountTo
|
||||||
|
|
||||||
|
- 综合实例
|
||||||
|
- 错误日志
|
||||||
|
- Dashboard
|
||||||
|
- 引导页
|
||||||
|
- ECharts 图表
|
||||||
|
- Clipboard(剪贴复制)
|
||||||
|
- Markdown2html
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆项目
|
||||||
|
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||||
|
|
||||||
|
# 进入项目目录
|
||||||
|
cd vue-element-admin
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
|
||||||
|
npm install --registry=https://registry.npm.taobao.org
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
浏览器访问 http://localhost:9527
|
||||||
|
|
||||||
|
## 发布
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建测试环境
|
||||||
|
npm run build:stage
|
||||||
|
|
||||||
|
# 构建生产环境
|
||||||
|
npm run build:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
## 其它
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 预览发布环境效果
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# 预览发布环境效果 + 静态资源分析
|
||||||
|
npm run preview -- --report
|
||||||
|
|
||||||
|
# 代码格式检查
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# 代码格式检查并自动修复
|
||||||
|
npm run lint -- --fix
|
||||||
|
```
|
||||||
|
|
||||||
|
更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
|
||||||
|
|
||||||
|
## Online Demo
|
||||||
|
|
||||||
|
[在线 Demo](https://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
|
## Donate
|
||||||
|
|
||||||
|
如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 :tropical_drink:
|
||||||
|
![donate](https://panjiachen.github.io/donate/donation.png)
|
||||||
|
|
||||||
|
[更多捐赠方式](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
|
||||||
|
|
||||||
|
[Paypal Me](https://www.paypal.me/panfree23)
|
||||||
|
|
||||||
|
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
|
||||||
|
|
||||||
|
## 购买贴纸
|
||||||
|
|
||||||
|
你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,本项目将获得 2 元的捐赠。
|
||||||
|
|
||||||
|
## Browsers support
|
||||||
|
|
||||||
|
Modern browsers and Internet Explorer 10+.
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
|
| --------- | --------- | --------- | --------- |
|
||||||
|
| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions |
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||||
|
|
||||||
|
Copyright (c) 2017-present PanJiaChen
|
|
@ -0,0 +1,14 @@
|
||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
|
||||||
|
'@vue/cli-plugin-babel/preset'
|
||||||
|
],
|
||||||
|
'env': {
|
||||||
|
'development': {
|
||||||
|
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
|
||||||
|
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
|
||||||
|
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
|
||||||
|
'plugins': ['dynamic-import-node']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,41 +0,0 @@
|
||||||
require('./check-versions')();
|
|
||||||
var server = require('pushstate-server');
|
|
||||||
var opn = require('opn')
|
|
||||||
var ora = require('ora')
|
|
||||||
var rm = require('rimraf')
|
|
||||||
var path = require('path')
|
|
||||||
var chalk = require('chalk')
|
|
||||||
var webpack = require('webpack');
|
|
||||||
var config = require('../config');
|
|
||||||
var webpackConfig = require('./webpack.prod.conf');
|
|
||||||
|
|
||||||
console.log(process.env.NODE_ENV)
|
|
||||||
|
|
||||||
var spinner = ora('building for ' + process.env.NODE_ENV + '...')
|
|
||||||
spinner.start()
|
|
||||||
|
|
||||||
|
|
||||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
|
||||||
if (err) throw err
|
|
||||||
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\n')
|
|
||||||
|
|
||||||
console.log(chalk.cyan(' Build complete.\n'))
|
|
||||||
if(process.env.npm_config_preview){
|
|
||||||
server.start({
|
|
||||||
port: 9528,
|
|
||||||
directory: './dist',
|
|
||||||
file: '/index.html'
|
|
||||||
});
|
|
||||||
console.log('> Listening at ' + 'http://localhost:9528' + '\n')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,45 +0,0 @@
|
||||||
var chalk = require('chalk')
|
|
||||||
var semver = require('semver')
|
|
||||||
var packageConfig = require('../package.json')
|
|
||||||
|
|
||||||
function exec(cmd) {
|
|
||||||
return require('child_process').execSync(cmd).toString().trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
var versionRequirements = [
|
|
||||||
{
|
|
||||||
name: 'node',
|
|
||||||
currentVersion: semver.clean(process.version),
|
|
||||||
versionRequirement: packageConfig.engines.node
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'npm',
|
|
||||||
currentVersion: exec('npm --version'),
|
|
||||||
versionRequirement: packageConfig.engines.npm
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
var warnings = []
|
|
||||||
for (var i = 0; i < versionRequirements.length; i++) {
|
|
||||||
var mod = versionRequirements[i]
|
|
||||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
|
||||||
warnings.push(mod.name + ': ' +
|
|
||||||
chalk.red(mod.currentVersion) + ' should be ' +
|
|
||||||
chalk.green(mod.versionRequirement)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (warnings.length) {
|
|
||||||
console.log('')
|
|
||||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
|
||||||
console.log()
|
|
||||||
for (var i = 0; i < warnings.length; i++) {
|
|
||||||
var warning = warnings[i]
|
|
||||||
console.log(' ' + warning)
|
|
||||||
}
|
|
||||||
console.log()
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
/* 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()
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -1,84 +0,0 @@
|
||||||
require('./check-versions')(); // 检查 Node 和 npm 版本
|
|
||||||
var config = require('../config');
|
|
||||||
if (!process.env.NODE_ENV) {
|
|
||||||
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
|
|
||||||
}
|
|
||||||
|
|
||||||
var opn = require('opn')
|
|
||||||
var path = require('path');
|
|
||||||
var express = require('express');
|
|
||||||
var webpack = require('webpack');
|
|
||||||
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;
|
|
||||||
// automatically open browser, if not set will be false
|
|
||||||
var autoOpenBrowser = !!config.dev.autoOpenBrowser;
|
|
||||||
// Define HTTP proxies to your custom API backend
|
|
||||||
// https://github.com/chimurai/http-proxy-middleware
|
|
||||||
var proxyTable = config.dev.proxyTable;
|
|
||||||
|
|
||||||
var app = express();
|
|
||||||
var compiler = webpack(webpackConfig);
|
|
||||||
|
|
||||||
var devMiddleware = require('webpack-dev-middleware')(compiler, {
|
|
||||||
publicPath: webpackConfig.output.publicPath,
|
|
||||||
quiet: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
|
|
||||||
log: () => {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
// compiler.apply(new DashboardPlugin());
|
|
||||||
|
|
||||||
// proxy api requests
|
|
||||||
Object.keys(proxyTable).forEach(function (context) {
|
|
||||||
var options = proxyTable[context]
|
|
||||||
if (typeof options === 'string') {
|
|
||||||
options = {target: options}
|
|
||||||
}
|
|
||||||
app.use(proxyMiddleware(options.filter || context, options))
|
|
||||||
});
|
|
||||||
|
|
||||||
// handle fallback for HTML5 history API
|
|
||||||
app.use(require('connect-history-api-fallback')());
|
|
||||||
|
|
||||||
// serve webpack bundle output
|
|
||||||
app.use(devMiddleware);
|
|
||||||
|
|
||||||
// enable hot-reload and state-preserving
|
|
||||||
// compilation error display
|
|
||||||
app.use(hotMiddleware);
|
|
||||||
|
|
||||||
// serve pure static assets
|
|
||||||
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory);
|
|
||||||
app.use(staticPath, express.static('./static'));
|
|
||||||
|
|
||||||
var uri = 'http://localhost:' + port
|
|
||||||
|
|
||||||
devMiddleware.waitUntilValid(function () {
|
|
||||||
console.log('> Listening at ' + uri + '\n')
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = app.listen(port, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// when env is testing, don't need open it
|
|
||||||
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
|
|
||||||
opn(uri)
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
const { run } = require('runjs')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
const config = require('../vue.config.js')
|
||||||
|
const rawArgv = process.argv.slice(2)
|
||||||
|
const args = rawArgv.join(' ')
|
||||||
|
|
||||||
|
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
|
||||||
|
const report = rawArgv.includes('--report')
|
||||||
|
|
||||||
|
run(`vue-cli-service build ${args}`)
|
||||||
|
|
||||||
|
const port = 9526
|
||||||
|
const publicPath = config.publicPath
|
||||||
|
|
||||||
|
var connect = require('connect')
|
||||||
|
var serveStatic = require('serve-static')
|
||||||
|
const app = connect()
|
||||||
|
|
||||||
|
app.use(
|
||||||
|
publicPath,
|
||||||
|
serveStatic('./dist', {
|
||||||
|
index: ['index.html', '/']
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
app.listen(port, function () {
|
||||||
|
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
|
||||||
|
if (report) {
|
||||||
|
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
run(`vue-cli-service build ${args}`)
|
||||||
|
}
|
|
@ -1,71 +0,0 @@
|
||||||
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 || {}
|
|
||||||
|
|
||||||
var cssLoader = {
|
|
||||||
loader: 'css-loader',
|
|
||||||
options: {
|
|
||||||
minimize: process.env.NODE_ENV === 'production',
|
|
||||||
sourceMap: options.sourceMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate loader string to be used with extract text plugin
|
|
||||||
function generateLoaders (loader, loaderOptions) {
|
|
||||||
var loaders = [cssLoader]
|
|
||||||
if (loader) {
|
|
||||||
loaders.push({
|
|
||||||
loader: loader + '-loader',
|
|
||||||
options: Object.assign({}, loaderOptions, {
|
|
||||||
sourceMap: options.sourceMap
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract CSS when that option is specified
|
|
||||||
// (which is the case during production build)
|
|
||||||
if (options.extract) {
|
|
||||||
return ExtractTextPlugin.extract({
|
|
||||||
use: loaders,
|
|
||||||
fallback: 'vue-style-loader'
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return ['vue-style-loader'].concat(loaders)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
|
||||||
return {
|
|
||||||
css: generateLoaders(),
|
|
||||||
postcss: generateLoaders(),
|
|
||||||
less: generateLoaders('less'),
|
|
||||||
sass: generateLoaders('sass', { indentedSyntax: true }),
|
|
||||||
scss: generateLoaders('sass'),
|
|
||||||
stylus: generateLoaders('stylus'),
|
|
||||||
styl: generateLoaders('stylus')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate loaders for standalone style files (outside of .vue)
|
|
||||||
exports.styleLoaders = function (options) {
|
|
||||||
var output = []
|
|
||||||
var loaders = exports.cssLoaders(options)
|
|
||||||
for (var extension in loaders) {
|
|
||||||
var loader = loaders[extension]
|
|
||||||
output.push({
|
|
||||||
test: new RegExp('\\.' + extension + '$'),
|
|
||||||
use: loader
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
var utils = require('./utils')
|
|
||||||
var config = require('../config')
|
|
||||||
var isProduction = process.env.NODE_ENV === 'production'
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
loaders: utils.cssLoaders({
|
|
||||||
sourceMap: isProduction
|
|
||||||
? config.build.productionSourceMap
|
|
||||||
: config.dev.cssSourceMap,
|
|
||||||
extract: isProduction
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
var path = require('path');
|
|
||||||
var utils = require('./utils');
|
|
||||||
var config = require('../config');
|
|
||||||
var vueLoaderConfig = require('./vue-loader.conf');
|
|
||||||
|
|
||||||
function resolve(dir) {
|
|
||||||
return path.join(__dirname, '..', dir)
|
|
||||||
}
|
|
||||||
var src = path.resolve(__dirname, '../src');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
entry: {
|
|
||||||
app: './src/main.js'
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: config.build.assetsRoot,
|
|
||||||
filename: '[name].js',
|
|
||||||
publicPath: process.env.NODE_ENV !== 'development' ? config.build.assetsPublicPath: config.dev.assetsPublicPath
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js', '.vue', '.json'],
|
|
||||||
alias: {
|
|
||||||
'vue$': 'vue/dist/vue.esm.js',
|
|
||||||
'@': resolve('src'),
|
|
||||||
'src': path.resolve(__dirname, '../src'),
|
|
||||||
'assets': path.resolve(__dirname, '../src/assets'),
|
|
||||||
'components': path.resolve(__dirname, '../src/components'),
|
|
||||||
'views': path.resolve(__dirname, '../src/views'),
|
|
||||||
'styles': path.resolve(__dirname, '../src/styles'),
|
|
||||||
'api': path.resolve(__dirname, '../src/api'),
|
|
||||||
'utils': path.resolve(__dirname, '../src/utils'),
|
|
||||||
'store': path.resolve(__dirname, '../src/store'),
|
|
||||||
'router': path.resolve(__dirname, '../src/router'),
|
|
||||||
'mock': path.resolve(__dirname, '../src/mock'),
|
|
||||||
'vendor': path.resolve(__dirname, '../src/vendor'),
|
|
||||||
'static': path.resolve(__dirname, '../static')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
externals: {
|
|
||||||
jquery: 'jQuery'
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
// {
|
|
||||||
// test: /\.(js|vue)$/,
|
|
||||||
// loader: 'eslint-loader',
|
|
||||||
// enforce: "pre",
|
|
||||||
// include: [resolve('src'), resolve('test')],
|
|
||||||
// options: {
|
|
||||||
// formatter: require('eslint-friendly-formatter')
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
{ test: /\.vue$/,
|
|
||||||
loader: 'vue-loader',
|
|
||||||
options: vueLoaderConfig
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
loader: 'babel-loader?cacheDirectory',
|
|
||||||
include: [resolve('src'), resolve('test')]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
query: {
|
|
||||||
limit: 10000,
|
|
||||||
name: utils.assetsPath('img/[name].[hash:7].[ext]')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
query: {
|
|
||||||
limit: 10000,
|
|
||||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
//注入全局mixin
|
|
||||||
// sassResources: path.join(__dirname, '../src/styles/mixin.scss'),
|
|
||||||
// sassLoader: {
|
|
||||||
// data: path.join(__dirname, '../src/styles/index.scss')
|
|
||||||
// },
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
var utils = require('./utils')
|
|
||||||
var path = require('path')
|
|
||||||
var webpack = require('webpack')
|
|
||||||
var config = require('../config')
|
|
||||||
var merge = require('webpack-merge')
|
|
||||||
var baseWebpackConfig = require('./webpack.base.conf')
|
|
||||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
||||||
var FriendlyErrorsPlugin = require('friendly-errors-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])
|
|
||||||
})
|
|
||||||
|
|
||||||
function resolveApp(relativePath) {
|
|
||||||
return path.resolve(relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = merge(baseWebpackConfig, {
|
|
||||||
module: {
|
|
||||||
rules: utils.styleLoaders({sourceMap: config.dev.cssSourceMap})
|
|
||||||
},
|
|
||||||
// cheap-source-map is faster for development
|
|
||||||
devtool: '#cheap-source-map',
|
|
||||||
cache: true,
|
|
||||||
plugins: [
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': config.dev.env
|
|
||||||
}),
|
|
||||||
new webpack.ProvidePlugin({
|
|
||||||
$: 'jquery',
|
|
||||||
'jQuery': 'jquery'
|
|
||||||
}),
|
|
||||||
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
|
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
|
||||||
new webpack.NoEmitOnErrorsPlugin(),
|
|
||||||
// https://github.com/ampedandwired/html-webpack-plugin
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
filename: 'index.html',
|
|
||||||
template: 'index.html',
|
|
||||||
favicon: resolveApp('favicon.ico'),
|
|
||||||
inject: true,
|
|
||||||
path:config.dev.staticPath
|
|
||||||
}),
|
|
||||||
new FriendlyErrorsPlugin()
|
|
||||||
]
|
|
||||||
})
|
|
|
@ -1,121 +0,0 @@
|
||||||
var path = require('path')
|
|
||||||
var utils = require('./utils')
|
|
||||||
var webpack = require('webpack')
|
|
||||||
var config = require('../config')
|
|
||||||
var merge = require('webpack-merge')
|
|
||||||
var baseWebpackConfig = require('./webpack.base.conf')
|
|
||||||
var CopyWebpackPlugin = require('copy-webpack-plugin')
|
|
||||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
||||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
|
||||||
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
|
||||||
|
|
||||||
var env = process.env.NODE_ENV === 'production' ? config.build.prodEnv : config.build.sitEnv
|
|
||||||
|
|
||||||
function resolveApp(relativePath) {
|
|
||||||
return path.resolve(relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
var webpackConfig = merge(baseWebpackConfig, {
|
|
||||||
module: {
|
|
||||||
rules: 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].[chunkhash].js'),
|
|
||||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': env
|
|
||||||
}),
|
|
||||||
new webpack.optimize.UglifyJsPlugin({
|
|
||||||
compress: {
|
|
||||||
warnings: false
|
|
||||||
},
|
|
||||||
sourceMap: true
|
|
||||||
}),
|
|
||||||
// extract css into its own file
|
|
||||||
new ExtractTextPlugin({
|
|
||||||
filename: utils.assetsPath('css/[name].[contenthash].css')
|
|
||||||
}),
|
|
||||||
// Compress extracted CSS. We are using this plugin so that possible
|
|
||||||
// duplicated CSS from different components can be deduped.
|
|
||||||
new OptimizeCSSPlugin(),
|
|
||||||
// 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: process.env.NODE_ENV === 'testing'
|
|
||||||
? 'index.html'
|
|
||||||
: config.build.index,
|
|
||||||
template: 'index.html',
|
|
||||||
inject: true,
|
|
||||||
favicon: resolveApp('favicon.ico'),
|
|
||||||
minify: {
|
|
||||||
removeComments: true,
|
|
||||||
collapseWhitespace: true,
|
|
||||||
removeRedundantAttributes: true,
|
|
||||||
useShortDoctype: true,
|
|
||||||
removeEmptyAttributes: true,
|
|
||||||
removeStyleLinkTypeAttributes: true,
|
|
||||||
keepClosingSlash: true,
|
|
||||||
minifyJS: true,
|
|
||||||
minifyCSS: true,
|
|
||||||
minifyURLs: true
|
|
||||||
},
|
|
||||||
path:config.build.staticPath,
|
|
||||||
// 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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
// split echarts into its own file
|
|
||||||
new webpack.optimize.CommonsChunkPlugin({
|
|
||||||
async:'echarts',
|
|
||||||
minChunks(module) {
|
|
||||||
var context = module.context;
|
|
||||||
return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 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']
|
|
||||||
}),
|
|
||||||
// copy custom static assets
|
|
||||||
new CopyWebpackPlugin([
|
|
||||||
{
|
|
||||||
from: path.resolve(__dirname, '../static'),
|
|
||||||
to: config.build.assetsSubDirectory,
|
|
||||||
ignore: ['.*']
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
new webpack.ProvidePlugin({
|
|
||||||
$: 'jquery',
|
|
||||||
'jQuery': 'jquery'
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
if (config.build.bundleAnalyzerReport) {
|
|
||||||
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
|
||||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
|
|
||||||
}
|
|
||||||
module.exports = webpackConfig
|
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
NODE_ENV: '"development"',
|
|
||||||
BASE_API: '"https://api-dev"',
|
|
||||||
APP_ORIGIN: '"https://wallstreetcn.com"'
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
|
||||||
var path = require('path')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
build: {
|
|
||||||
sitEnv: require('./sit.env'),
|
|
||||||
prodEnv: require('./prod.env'),
|
|
||||||
index: path.resolve(__dirname, '../dist/index.html'),
|
|
||||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
|
||||||
assetsSubDirectory: 'static',
|
|
||||||
assetsPublicPath: './', //请根据自己路径配置更改
|
|
||||||
staticPath:'./static/', //请根据自己路径配置更改
|
|
||||||
productionSourceMap: false,
|
|
||||||
// Gzip off by default as many popular static hosts such as
|
|
||||||
// Surge or Netlify already gzip all static assets for you.
|
|
||||||
// Before setting to `true`, make sure to:
|
|
||||||
// npm install --save-dev compression-webpack-plugin
|
|
||||||
productionGzip: false,
|
|
||||||
productionGzipExtensions: ['js', 'css'],
|
|
||||||
// Run the build command with an extra argument to
|
|
||||||
// View the bundle analyzer report after build finishes:
|
|
||||||
// `npm run build --report`
|
|
||||||
// Set to `true` or `false` to always turn it on or off
|
|
||||||
bundleAnalyzerReport: process.env.npm_config_report
|
|
||||||
},
|
|
||||||
dev: {
|
|
||||||
env: require('./dev.env'),
|
|
||||||
port: 9527,
|
|
||||||
autoOpenBrowser: true,
|
|
||||||
assetsSubDirectory: 'static',
|
|
||||||
assetsPublicPath: '/',
|
|
||||||
staticPath:'/static/',
|
|
||||||
proxyTable: {},
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
NODE_ENV: '"production"',
|
|
||||||
BASE_API: '"https://api-prod"',
|
|
||||||
APP_ORIGIN: '"https://wallstreetcn.com"'
|
|
||||||
};
|
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
NODE_ENV: '"production"',
|
|
||||||
BASE_API: '"https://api-sit"',
|
|
||||||
APP_ORIGIN: '"https://wallstreetcn.com"'
|
|
||||||
};
|
|
BIN
favicon.ico
Before Width: | Height: | Size: 66 KiB |
BIN
gifs/2login.gif
Before Width: | Height: | Size: 275 KiB |
Before Width: | Height: | Size: 41 KiB |
BIN
gifs/echarts.gif
Before Width: | Height: | Size: 229 KiB |
BIN
gifs/editor.gif
Before Width: | Height: | Size: 435 KiB |
Before Width: | Height: | Size: 532 KiB |
BIN
gifs/excel.png
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 601 KiB |
BIN
gifs/login.png
Before Width: | Height: | Size: 51 KiB |
BIN
gifs/order.gif
Before Width: | Height: | Size: 1.1 MiB |
BIN
gifs/table.gif
Before Width: | Height: | Size: 390 KiB |
BIN
gifs/tabs.gif
Before Width: | Height: | Size: 1.2 MiB |
BIN
gifs/theme.gif
Before Width: | Height: | Size: 265 KiB |
BIN
gifs/upload1.gif
Before Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 330 KiB |
|
@ -0,0 +1,24 @@
|
||||||
|
module.exports = {
|
||||||
|
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
|
||||||
|
transform: {
|
||||||
|
'^.+\\.vue$': 'vue-jest',
|
||||||
|
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
|
||||||
|
'jest-transform-stub',
|
||||||
|
'^.+\\.jsx?$': 'babel-jest'
|
||||||
|
},
|
||||||
|
moduleNameMapper: {
|
||||||
|
'^@/(.*)$': '<rootDir>/src/$1'
|
||||||
|
},
|
||||||
|
snapshotSerializers: ['jest-serializer-vue'],
|
||||||
|
testMatch: [
|
||||||
|
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
|
||||||
|
],
|
||||||
|
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
|
||||||
|
coverageDirectory: '<rootDir>/tests/unit/coverage',
|
||||||
|
// 'collectCoverage': true,
|
||||||
|
'coverageReporters': [
|
||||||
|
'lcov',
|
||||||
|
'text-summary'
|
||||||
|
],
|
||||||
|
testURL: 'http://localhost/'
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
const Mock = require('mockjs')
|
||||||
|
|
||||||
|
const List = []
|
||||||
|
const count = 100
|
||||||
|
|
||||||
|
const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
|
||||||
|
const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
List.push(Mock.mock({
|
||||||
|
id: '@increment',
|
||||||
|
timestamp: +Mock.Random.date('T'),
|
||||||
|
author: '@first',
|
||||||
|
reviewer: '@first',
|
||||||
|
title: '@title(5, 10)',
|
||||||
|
content_short: 'mock data',
|
||||||
|
content: baseContent,
|
||||||
|
forecast: '@float(0, 100, 2, 2)',
|
||||||
|
importance: '@integer(1, 3)',
|
||||||
|
'type|1': ['CN', 'US', 'JP', 'EU'],
|
||||||
|
'status|1': ['published', 'draft'],
|
||||||
|
display_time: '@datetime',
|
||||||
|
comment_disabled: true,
|
||||||
|
pageviews: '@integer(300, 5000)',
|
||||||
|
image_uri,
|
||||||
|
platforms: ['a-platform']
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/article/list',
|
||||||
|
type: 'get',
|
||||||
|
response: config => {
|
||||||
|
const { importance, type, title, page = 1, limit = 20, sort } = config.query
|
||||||
|
|
||||||
|
let mockList = List.filter(item => {
|
||||||
|
if (importance && item.importance !== +importance) return false
|
||||||
|
if (type && item.type !== type) return false
|
||||||
|
if (title && item.title.indexOf(title) < 0) return false
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (sort === '-id') {
|
||||||
|
mockList = mockList.reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: {
|
||||||
|
total: mockList.length,
|
||||||
|
items: pageList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/article/detail',
|
||||||
|
type: 'get',
|
||||||
|
response: config => {
|
||||||
|
const { id } = config.query
|
||||||
|
for (const article of List) {
|
||||||
|
if (article.id === +id) {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: article
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/article/pv',
|
||||||
|
type: 'get',
|
||||||
|
response: _ => {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: {
|
||||||
|
pvData: [
|
||||||
|
{ key: 'PC', pv: 1024 },
|
||||||
|
{ key: 'mobile', pv: 1024 },
|
||||||
|
{ key: 'ios', pv: 1024 },
|
||||||
|
{ key: 'android', pv: 1024 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/article/create',
|
||||||
|
type: 'post',
|
||||||
|
response: _ => {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: 'success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/article/update',
|
||||||
|
type: 'post',
|
||||||
|
response: _ => {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: 'success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
const Mock = require('mockjs')
|
||||||
|
const { param2Obj } = require('./utils')
|
||||||
|
|
||||||
|
const user = require('./user')
|
||||||
|
const role = require('./role')
|
||||||
|
const article = require('./article')
|
||||||
|
const search = require('./remote-search')
|
||||||
|
|
||||||
|
const mocks = [
|
||||||
|
...user,
|
||||||
|
...role,
|
||||||
|
...article,
|
||||||
|
...search
|
||||||
|
]
|
||||||
|
|
||||||
|
// for front mock
|
||||||
|
// please use it cautiously, it will redefine XMLHttpRequest,
|
||||||
|
// which will cause many of your third-party libraries to be invalidated(like progress event).
|
||||||
|
function mockXHR() {
|
||||||
|
// mock patch
|
||||||
|
// https://github.com/nuysoft/Mock/issues/300
|
||||||
|
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
|
||||||
|
Mock.XHR.prototype.send = function() {
|
||||||
|
if (this.custom.xhr) {
|
||||||
|
this.custom.xhr.withCredentials = this.withCredentials || false
|
||||||
|
|
||||||
|
if (this.responseType) {
|
||||||
|
this.custom.xhr.responseType = this.responseType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.proxy_send(...arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
function XHR2ExpressReqWrap(respond) {
|
||||||
|
return function(options) {
|
||||||
|
let result = null
|
||||||
|
if (respond instanceof Function) {
|
||||||
|
const { body, type, url } = options
|
||||||
|
// https://expressjs.com/en/4x/api.html#req
|
||||||
|
result = respond({
|
||||||
|
method: type,
|
||||||
|
body: JSON.parse(body),
|
||||||
|
query: param2Obj(url)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
result = respond
|
||||||
|
}
|
||||||
|
return Mock.mock(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const i of mocks) {
|
||||||
|
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mocks,
|
||||||
|
mockXHR
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
const chokidar = require('chokidar')
|
||||||
|
const bodyParser = require('body-parser')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
const path = require('path')
|
||||||
|
const Mock = require('mockjs')
|
||||||
|
|
||||||
|
const mockDir = path.join(process.cwd(), 'mock')
|
||||||
|
|
||||||
|
function registerRoutes(app) {
|
||||||
|
let mockLastIndex
|
||||||
|
const { mocks } = require('./index.js')
|
||||||
|
const mocksForServer = mocks.map(route => {
|
||||||
|
return responseFake(route.url, route.type, route.response)
|
||||||
|
})
|
||||||
|
for (const mock of mocksForServer) {
|
||||||
|
app[mock.type](mock.url, mock.response)
|
||||||
|
mockLastIndex = app._router.stack.length
|
||||||
|
}
|
||||||
|
const mockRoutesLength = Object.keys(mocksForServer).length
|
||||||
|
return {
|
||||||
|
mockRoutesLength: mockRoutesLength,
|
||||||
|
mockStartIndex: mockLastIndex - mockRoutesLength
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unregisterRoutes() {
|
||||||
|
Object.keys(require.cache).forEach(i => {
|
||||||
|
if (i.includes(mockDir)) {
|
||||||
|
delete require.cache[require.resolve(i)]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// for mock server
|
||||||
|
const responseFake = (url, type, respond) => {
|
||||||
|
return {
|
||||||
|
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
|
||||||
|
type: type || 'get',
|
||||||
|
response(req, res) {
|
||||||
|
console.log('request invoke:' + req.path)
|
||||||
|
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = app => {
|
||||||
|
// parse app.body
|
||||||
|
// https://expressjs.com/en/4x/api.html#req.body
|
||||||
|
app.use(bodyParser.json())
|
||||||
|
app.use(bodyParser.urlencoded({
|
||||||
|
extended: true
|
||||||
|
}))
|
||||||
|
|
||||||
|
const mockRoutes = registerRoutes(app)
|
||||||
|
var mockRoutesLength = mockRoutes.mockRoutesLength
|
||||||
|
var mockStartIndex = mockRoutes.mockStartIndex
|
||||||
|
|
||||||
|
// watch files, hot reload mock server
|
||||||
|
chokidar.watch(mockDir, {
|
||||||
|
ignored: /mock-server/,
|
||||||
|
ignoreInitial: true
|
||||||
|
}).on('all', (event, path) => {
|
||||||
|
if (event === 'change' || event === 'add') {
|
||||||
|
try {
|
||||||
|
// remove mock routes stack
|
||||||
|
app._router.stack.splice(mockStartIndex, mockRoutesLength)
|
||||||
|
|
||||||
|
// clear routes cache
|
||||||
|
unregisterRoutes()
|
||||||
|
|
||||||
|
const mockRoutes = registerRoutes(app)
|
||||||
|
mockRoutesLength = mockRoutes.mockRoutesLength
|
||||||
|
mockStartIndex = mockRoutes.mockStartIndex
|
||||||
|
|
||||||
|
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
|
||||||
|
} catch (error) {
|
||||||
|
console.log(chalk.redBright(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
const Mock = require('mockjs')
|
||||||
|
|
||||||
|
const NameList = []
|
||||||
|
const count = 100
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
NameList.push(Mock.mock({
|
||||||
|
name: '@first'
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
NameList.push({ name: 'mock-Pan' })
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
// username search
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/search/user',
|
||||||
|
type: 'get',
|
||||||
|
response: config => {
|
||||||
|
const { name } = config.query
|
||||||
|
const mockNameList = NameList.filter(item => {
|
||||||
|
const lowerCaseName = item.name.toLowerCase()
|
||||||
|
return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: { items: mockNameList }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// transaction list
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/transaction/list',
|
||||||
|
type: 'get',
|
||||||
|
response: _ => {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: {
|
||||||
|
total: 20,
|
||||||
|
'items|20': [{
|
||||||
|
order_no: '@guid()',
|
||||||
|
timestamp: +Mock.Random.date('T'),
|
||||||
|
username: '@name()',
|
||||||
|
price: '@float(1000, 15000, 0, 2)',
|
||||||
|
'status|1': ['success', 'pending']
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,98 @@
|
||||||
|
const Mock = require('mockjs')
|
||||||
|
const { deepClone } = require('../utils')
|
||||||
|
const { asyncRoutes, constantRoutes } = require('./routes.js')
|
||||||
|
|
||||||
|
const routes = deepClone([...constantRoutes, ...asyncRoutes])
|
||||||
|
|
||||||
|
const roles = [
|
||||||
|
{
|
||||||
|
key: 'admin',
|
||||||
|
name: 'admin',
|
||||||
|
description: 'Super Administrator. Have access to view all pages.',
|
||||||
|
routes: routes
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'editor',
|
||||||
|
name: 'editor',
|
||||||
|
description: 'Normal Editor. Can see all pages except permission page',
|
||||||
|
routes: routes.filter(i => i.path !== '/permission')// just a mock
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'visitor',
|
||||||
|
name: 'visitor',
|
||||||
|
description: 'Just a visitor. Can only see the home page and the document page',
|
||||||
|
routes: [{
|
||||||
|
path: '',
|
||||||
|
redirect: 'dashboard',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'dashboard',
|
||||||
|
name: 'Dashboard',
|
||||||
|
meta: { title: 'dashboard', icon: 'dashboard' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
// mock get all routes form server
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/routes',
|
||||||
|
type: 'get',
|
||||||
|
response: _ => {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: routes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// mock get all roles form server
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/roles',
|
||||||
|
type: 'get',
|
||||||
|
response: _ => {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: roles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// add role
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/role',
|
||||||
|
type: 'post',
|
||||||
|
response: {
|
||||||
|
code: 20000,
|
||||||
|
data: {
|
||||||
|
key: Mock.mock('@integer(300, 5000)')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// update role
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/role/[A-Za-z0-9]',
|
||||||
|
type: 'put',
|
||||||
|
response: {
|
||||||
|
code: 20000,
|
||||||
|
data: {
|
||||||
|
status: 'success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// delete role
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/role/[A-Za-z0-9]',
|
||||||
|
type: 'delete',
|
||||||
|
response: {
|
||||||
|
code: 20000,
|
||||||
|
data: {
|
||||||
|
status: 'success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,530 @@
|
||||||
|
// Just a mock data
|
||||||
|
|
||||||
|
const constantRoutes = [
|
||||||
|
{
|
||||||
|
path: '/redirect',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
hidden: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/redirect/:path*',
|
||||||
|
component: 'views/redirect/index'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
component: 'views/login/index',
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/auth-redirect',
|
||||||
|
component: 'views/login/auth-redirect',
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/404',
|
||||||
|
component: 'views/error-page/404',
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/401',
|
||||||
|
component: 'views/error-page/401',
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: 'dashboard',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'dashboard',
|
||||||
|
component: 'views/dashboard/index',
|
||||||
|
name: 'Dashboard',
|
||||||
|
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/documentation',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/documentation/index',
|
||||||
|
name: 'Documentation',
|
||||||
|
meta: { title: 'Documentation', icon: 'documentation', affix: true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/guide',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: '/guide/index',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/guide/index',
|
||||||
|
name: 'Guide',
|
||||||
|
meta: { title: 'Guide', icon: 'guide', noCache: true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const asyncRoutes = [
|
||||||
|
{
|
||||||
|
path: '/permission',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: '/permission/index',
|
||||||
|
alwaysShow: true,
|
||||||
|
meta: {
|
||||||
|
title: 'Permission',
|
||||||
|
icon: 'lock',
|
||||||
|
roles: ['admin', 'editor']
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'page',
|
||||||
|
component: 'views/permission/page',
|
||||||
|
name: 'PagePermission',
|
||||||
|
meta: {
|
||||||
|
title: 'Page Permission',
|
||||||
|
roles: ['admin']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'directive',
|
||||||
|
component: 'views/permission/directive',
|
||||||
|
name: 'DirectivePermission',
|
||||||
|
meta: {
|
||||||
|
title: 'Directive Permission'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'role',
|
||||||
|
component: 'views/permission/role',
|
||||||
|
name: 'RolePermission',
|
||||||
|
meta: {
|
||||||
|
title: 'Role Permission',
|
||||||
|
roles: ['admin']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/icon',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/icons/index',
|
||||||
|
name: 'Icons',
|
||||||
|
meta: { title: 'Icons', icon: 'icon', noCache: true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/components',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: 'noRedirect',
|
||||||
|
name: 'ComponentDemo',
|
||||||
|
meta: {
|
||||||
|
title: 'Components',
|
||||||
|
icon: 'component'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'tinymce',
|
||||||
|
component: 'views/components-demo/tinymce',
|
||||||
|
name: 'TinymceDemo',
|
||||||
|
meta: { title: 'Tinymce' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'markdown',
|
||||||
|
component: 'views/components-demo/markdown',
|
||||||
|
name: 'MarkdownDemo',
|
||||||
|
meta: { title: 'Markdown' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'json-editor',
|
||||||
|
component: 'views/components-demo/json-editor',
|
||||||
|
name: 'JsonEditorDemo',
|
||||||
|
meta: { title: 'Json Editor' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'split-pane',
|
||||||
|
component: 'views/components-demo/split-pane',
|
||||||
|
name: 'SplitpaneDemo',
|
||||||
|
meta: { title: 'SplitPane' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'avatar-upload',
|
||||||
|
component: 'views/components-demo/avatar-upload',
|
||||||
|
name: 'AvatarUploadDemo',
|
||||||
|
meta: { title: 'Avatar Upload' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'dropzone',
|
||||||
|
component: 'views/components-demo/dropzone',
|
||||||
|
name: 'DropzoneDemo',
|
||||||
|
meta: { title: 'Dropzone' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'sticky',
|
||||||
|
component: 'views/components-demo/sticky',
|
||||||
|
name: 'StickyDemo',
|
||||||
|
meta: { title: 'Sticky' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'count-to',
|
||||||
|
component: 'views/components-demo/count-to',
|
||||||
|
name: 'CountToDemo',
|
||||||
|
meta: { title: 'Count To' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'mixin',
|
||||||
|
component: 'views/components-demo/mixin',
|
||||||
|
name: 'ComponentMixinDemo',
|
||||||
|
meta: { title: 'componentMixin' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'back-to-top',
|
||||||
|
component: 'views/components-demo/back-to-top',
|
||||||
|
name: 'BackToTopDemo',
|
||||||
|
meta: { title: 'Back To Top' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'drag-dialog',
|
||||||
|
component: 'views/components-demo/drag-dialog',
|
||||||
|
name: 'DragDialogDemo',
|
||||||
|
meta: { title: 'Drag Dialog' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'drag-select',
|
||||||
|
component: 'views/components-demo/drag-select',
|
||||||
|
name: 'DragSelectDemo',
|
||||||
|
meta: { title: 'Drag Select' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'dnd-list',
|
||||||
|
component: 'views/components-demo/dnd-list',
|
||||||
|
name: 'DndListDemo',
|
||||||
|
meta: { title: 'Dnd List' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'drag-kanban',
|
||||||
|
component: 'views/components-demo/drag-kanban',
|
||||||
|
name: 'DragKanbanDemo',
|
||||||
|
meta: { title: 'Drag Kanban' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/charts',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: 'noRedirect',
|
||||||
|
name: 'Charts',
|
||||||
|
meta: {
|
||||||
|
title: 'Charts',
|
||||||
|
icon: 'chart'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'keyboard',
|
||||||
|
component: 'views/charts/keyboard',
|
||||||
|
name: 'KeyboardChart',
|
||||||
|
meta: { title: 'Keyboard Chart', noCache: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'line',
|
||||||
|
component: 'views/charts/line',
|
||||||
|
name: 'LineChart',
|
||||||
|
meta: { title: 'Line Chart', noCache: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'mixchart',
|
||||||
|
component: 'views/charts/mixChart',
|
||||||
|
name: 'MixChart',
|
||||||
|
meta: { title: 'Mix Chart', noCache: true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/nested',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: '/nested/menu1/menu1-1',
|
||||||
|
name: 'Nested',
|
||||||
|
meta: {
|
||||||
|
title: 'Nested',
|
||||||
|
icon: 'nested'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'menu1',
|
||||||
|
component: 'views/nested/menu1/index',
|
||||||
|
name: 'Menu1',
|
||||||
|
meta: { title: 'Menu1' },
|
||||||
|
redirect: '/nested/menu1/menu1-1',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'menu1-1',
|
||||||
|
component: 'views/nested/menu1/menu1-1',
|
||||||
|
name: 'Menu1-1',
|
||||||
|
meta: { title: 'Menu1-1' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'menu1-2',
|
||||||
|
component: 'views/nested/menu1/menu1-2',
|
||||||
|
name: 'Menu1-2',
|
||||||
|
redirect: '/nested/menu1/menu1-2/menu1-2-1',
|
||||||
|
meta: { title: 'Menu1-2' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'menu1-2-1',
|
||||||
|
component: 'views/nested/menu1/menu1-2/menu1-2-1',
|
||||||
|
name: 'Menu1-2-1',
|
||||||
|
meta: { title: 'Menu1-2-1' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'menu1-2-2',
|
||||||
|
component: 'views/nested/menu1/menu1-2/menu1-2-2',
|
||||||
|
name: 'Menu1-2-2',
|
||||||
|
meta: { title: 'Menu1-2-2' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'menu1-3',
|
||||||
|
component: 'views/nested/menu1/menu1-3',
|
||||||
|
name: 'Menu1-3',
|
||||||
|
meta: { title: 'Menu1-3' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'menu2',
|
||||||
|
name: 'Menu2',
|
||||||
|
component: 'views/nested/menu2/index',
|
||||||
|
meta: { title: 'Menu2' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/example',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: '/example/list',
|
||||||
|
name: 'Example',
|
||||||
|
meta: {
|
||||||
|
title: 'Example',
|
||||||
|
icon: 'example'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
component: 'views/example/create',
|
||||||
|
name: 'CreateArticle',
|
||||||
|
meta: { title: 'Create Article', icon: 'edit' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'edit/:id(\\d+)',
|
||||||
|
component: 'views/example/edit',
|
||||||
|
name: 'EditArticle',
|
||||||
|
meta: { title: 'Edit Article', noCache: true },
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'list',
|
||||||
|
component: 'views/example/list',
|
||||||
|
name: 'ArticleList',
|
||||||
|
meta: { title: 'Article List', icon: 'list' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/tab',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/tab/index',
|
||||||
|
name: 'Tab',
|
||||||
|
meta: { title: 'Tab', icon: 'tab' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/error',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: 'noRedirect',
|
||||||
|
name: 'ErrorPages',
|
||||||
|
meta: {
|
||||||
|
title: 'Error Pages',
|
||||||
|
icon: '404'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '401',
|
||||||
|
component: 'views/error-page/401',
|
||||||
|
name: 'Page401',
|
||||||
|
meta: { title: 'Page 401', noCache: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '404',
|
||||||
|
component: 'views/error-page/404',
|
||||||
|
name: 'Page404',
|
||||||
|
meta: { title: 'Page 404', noCache: true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/error-log',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: 'noRedirect',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'log',
|
||||||
|
component: 'views/error-log/index',
|
||||||
|
name: 'ErrorLog',
|
||||||
|
meta: { title: 'Error Log', icon: 'bug' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/excel',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: '/excel/export-excel',
|
||||||
|
name: 'Excel',
|
||||||
|
meta: {
|
||||||
|
title: 'Excel',
|
||||||
|
icon: 'excel'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'export-excel',
|
||||||
|
component: 'views/excel/export-excel',
|
||||||
|
name: 'ExportExcel',
|
||||||
|
meta: { title: 'Export Excel' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'export-selected-excel',
|
||||||
|
component: 'views/excel/select-excel',
|
||||||
|
name: 'SelectExcel',
|
||||||
|
meta: { title: 'Select Excel' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'export-merge-header',
|
||||||
|
component: 'views/excel/merge-header',
|
||||||
|
name: 'MergeHeader',
|
||||||
|
meta: { title: 'Merge Header' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'upload-excel',
|
||||||
|
component: 'views/excel/upload-excel',
|
||||||
|
name: 'UploadExcel',
|
||||||
|
meta: { title: 'Upload Excel' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/zip',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: '/zip/download',
|
||||||
|
alwaysShow: true,
|
||||||
|
meta: { title: 'Zip', icon: 'zip' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'download',
|
||||||
|
component: 'views/zip/index',
|
||||||
|
name: 'ExportZip',
|
||||||
|
meta: { title: 'Export Zip' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/pdf',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: '/pdf/index',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/pdf/index',
|
||||||
|
name: 'PDF',
|
||||||
|
meta: { title: 'PDF', icon: 'pdf' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/pdf/download',
|
||||||
|
component: 'views/pdf/download',
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/theme',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: 'noRedirect',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/theme/index',
|
||||||
|
name: 'Theme',
|
||||||
|
meta: { title: 'Theme', icon: 'theme' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/clipboard',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
redirect: 'noRedirect',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/clipboard/index',
|
||||||
|
name: 'ClipboardDemo',
|
||||||
|
meta: { title: 'Clipboard Demo', icon: 'clipboard' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/i18n',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: 'views/i18n-demo/index',
|
||||||
|
name: 'I18n',
|
||||||
|
meta: { title: 'I18n', icon: 'international' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: 'external-link',
|
||||||
|
component: 'layout/Layout',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'https://github.com/PanJiaChen/vue-element-admin',
|
||||||
|
meta: { title: 'External Link', icon: 'link' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{ path: '*', redirect: '/404', hidden: true }
|
||||||
|
]
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
constantRoutes,
|
||||||
|
asyncRoutes
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
|
||||||
|
const tokens = {
|
||||||
|
admin: {
|
||||||
|
token: 'admin-token'
|
||||||
|
},
|
||||||
|
editor: {
|
||||||
|
token: 'editor-token'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const users = {
|
||||||
|
'admin-token': {
|
||||||
|
roles: ['admin'],
|
||||||
|
introduction: 'I am a super administrator',
|
||||||
|
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
||||||
|
name: 'Super Admin'
|
||||||
|
},
|
||||||
|
'editor-token': {
|
||||||
|
roles: ['editor'],
|
||||||
|
introduction: 'I am an editor',
|
||||||
|
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
||||||
|
name: 'Normal Editor'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
// user login
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/user/login',
|
||||||
|
type: 'post',
|
||||||
|
response: config => {
|
||||||
|
const { username } = config.body
|
||||||
|
const token = tokens[username]
|
||||||
|
|
||||||
|
// mock error
|
||||||
|
if (!token) {
|
||||||
|
return {
|
||||||
|
code: 60204,
|
||||||
|
message: 'Account and password are incorrect.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// get user info
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/user/info\.*',
|
||||||
|
type: 'get',
|
||||||
|
response: config => {
|
||||||
|
const { token } = config.query
|
||||||
|
const info = users[token]
|
||||||
|
|
||||||
|
// mock error
|
||||||
|
if (!info) {
|
||||||
|
return {
|
||||||
|
code: 50008,
|
||||||
|
message: 'Login failed, unable to get user details.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// user logout
|
||||||
|
{
|
||||||
|
url: '/vue-element-admin/user/logout',
|
||||||
|
type: 'post',
|
||||||
|
response: _ => {
|
||||||
|
return {
|
||||||
|
code: 20000,
|
||||||
|
data: 'success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,48 @@
|
||||||
|
/**
|
||||||
|
* @param {string} url
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
function param2Obj(url) {
|
||||||
|
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
|
||||||
|
if (!search) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
const obj = {}
|
||||||
|
const searchArr = search.split('&')
|
||||||
|
searchArr.forEach(v => {
|
||||||
|
const index = v.indexOf('=')
|
||||||
|
if (index !== -1) {
|
||||||
|
const name = v.substring(0, index)
|
||||||
|
const val = v.substring(index + 1, v.length)
|
||||||
|
obj[name] = val
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is just a simple version of deep copy
|
||||||
|
* Has a lot of edge cases bug
|
||||||
|
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
|
||||||
|
* @param {Object} source
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
function deepClone(source) {
|
||||||
|
if (!source && typeof source !== 'object') {
|
||||||
|
throw new Error('error arguments', 'deepClone')
|
||||||
|
}
|
||||||
|
const targetObj = source.constructor === Array ? [] : {}
|
||||||
|
Object.keys(source).forEach(keys => {
|
||||||
|
if (source[keys] && typeof source[keys] === 'object') {
|
||||||
|
targetObj[keys] = deepClone(source[keys])
|
||||||
|
} else {
|
||||||
|
targetObj[keys] = source[keys]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return targetObj
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
param2Obj,
|
||||||
|
deepClone
|
||||||
|
}
|
180
package.json
|
@ -1,97 +1,111 @@
|
||||||
{
|
{
|
||||||
"name": "juicy",
|
"name": "vue-element-admin",
|
||||||
"version": "1.2.0",
|
"version": "4.4.0",
|
||||||
"description": "A Vue.js admin",
|
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
||||||
"author": "Pan <panfree23@gmail.com>",
|
"author": "Pan <panfree23@gmail.com>",
|
||||||
"license": "MIT",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node build/dev-server.js",
|
"dev": "vue-cli-service serve",
|
||||||
"build:prod": "cross-env NODE_ENV=production node build/build.js",
|
"lint": "eslint --ext .js,.vue src",
|
||||||
"build:sit": "cross-env NODE_ENV=sit node build/build.js",
|
"build:prod": "vue-cli-service build",
|
||||||
"build:sit-preview": "cross-env NODE_ENV=sit npm_config_preview=true npm_config_report=true node build/build.js",
|
"build:stage": "vue-cli-service build --mode staging",
|
||||||
"lint": "eslint --ext .js,.vue src"
|
"preview": "node build/index.js --preview",
|
||||||
|
"new": "plop",
|
||||||
|
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
||||||
|
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
||||||
|
"test:ci": "npm run lint && npm run test:unit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.16.2",
|
"axios": "0.18.1",
|
||||||
"codemirror": "5.26.0",
|
"clipboard": "2.0.4",
|
||||||
"dropzone": "5.1.0",
|
"codemirror": "5.45.0",
|
||||||
"echarts": "3.6.1",
|
"core-js": "3.6.5",
|
||||||
"element-ui": "1.4.1",
|
"driver.js": "0.9.5",
|
||||||
"file-saver": "1.3.3",
|
"dropzone": "5.5.1",
|
||||||
"jquery": "3.1.1",
|
"echarts": "4.2.1",
|
||||||
"js-cookie": "2.1.4",
|
"element-ui": "2.13.2",
|
||||||
"jsonlint": "1.6.2",
|
"file-saver": "2.0.1",
|
||||||
"mockjs": "1.0.1-beta3",
|
"fuse.js": "3.4.4",
|
||||||
"normalize.css": "3.0.2",
|
"js-cookie": "2.2.0",
|
||||||
|
"jsonlint": "1.6.3",
|
||||||
|
"jszip": "3.2.1",
|
||||||
|
"normalize.css": "7.0.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"screenfull": "3.2.2",
|
"path-to-regexp": "2.4.0",
|
||||||
"showdown": "1.7.1",
|
"screenfull": "4.2.0",
|
||||||
"simplemde": "1.11.2",
|
"script-loader": "0.7.2",
|
||||||
"sortablejs": "1.5.1",
|
"sortablejs": "1.8.4",
|
||||||
"vue": "2.4.2",
|
"tui-editor": "1.3.3",
|
||||||
"vue-count-to": "1.0.5",
|
"vue": "2.6.10",
|
||||||
"vue-multiselect": "2.0.0-beta.15",
|
"vue-count-to": "1.0.13",
|
||||||
"vue-router": "2.5.3",
|
"vue-router": "3.0.2",
|
||||||
"vuedraggable": "2.13.1",
|
"vue-splitpane": "1.0.4",
|
||||||
"vuex": "2.3.1",
|
"vuedraggable": "2.20.0",
|
||||||
"xlsx": "^0.10.8"
|
"vuex": "3.1.0",
|
||||||
|
"xlsx": "0.14.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "7.1.1",
|
"@vue/cli-plugin-babel": "4.4.4",
|
||||||
"babel-core": "6.25.0",
|
"@vue/cli-plugin-eslint": "4.4.4",
|
||||||
"babel-eslint": "7.2.3",
|
"@vue/cli-plugin-unit-jest": "4.4.4",
|
||||||
"babel-loader": "7.0.0",
|
"@vue/cli-service": "4.4.4",
|
||||||
"babel-plugin-transform-runtime": "6.23.0",
|
"@vue/test-utils": "1.0.0-beta.29",
|
||||||
"babel-preset-env": "1.5.2",
|
"autoprefixer": "9.5.1",
|
||||||
"babel-preset-stage-2": "6.24.1",
|
"babel-eslint": "10.1.0",
|
||||||
"babel-register": "6.24.1",
|
"babel-jest": "23.6.0",
|
||||||
"chalk": "1.1.3",
|
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||||
"connect-history-api-fallback": "1.3.0",
|
"chalk": "2.4.2",
|
||||||
"copy-webpack-plugin": "4.0.1",
|
"chokidar": "2.1.5",
|
||||||
"cross-env": "5.0.1",
|
"connect": "3.6.6",
|
||||||
"css-loader": "0.28.4",
|
"eslint": "6.7.2",
|
||||||
"eslint": "3.19.0",
|
"eslint-plugin-vue": "6.2.2",
|
||||||
"eslint-friendly-formatter": "3.0.0",
|
"html-webpack-plugin": "3.2.0",
|
||||||
"eslint-import-resolver-webpack": "0.8.1",
|
"husky": "1.3.1",
|
||||||
"eslint-loader": "1.7.1",
|
"lint-staged": "8.1.5",
|
||||||
"eslint-plugin-html": "3.0.0",
|
"mockjs": "1.0.1-beta3",
|
||||||
"eslint-plugin-import": "2.3.0",
|
"plop": "2.3.0",
|
||||||
"eventsource-polyfill": "0.9.6",
|
"runjs": "4.3.2",
|
||||||
"express": "4.15.3",
|
"sass": "1.26.2",
|
||||||
"extract-text-webpack-plugin": "2.1.2",
|
"sass-loader": "8.0.2",
|
||||||
"file-loader": "0.11.2",
|
"script-ext-html-webpack-plugin": "2.1.3",
|
||||||
"friendly-errors-webpack-plugin": "1.6.1",
|
"serve-static": "1.13.2",
|
||||||
"function-bind": "1.1.0",
|
"svg-sprite-loader": "4.1.3",
|
||||||
"html-webpack-plugin": "2.28.0",
|
"svgo": "1.2.0",
|
||||||
"http-proxy-middleware": "0.17.4",
|
"vue-template-compiler": "2.6.10"
|
||||||
"node-sass": "^4.5.0",
|
},
|
||||||
"opn": "4.0.2",
|
"browserslist": [
|
||||||
"optimize-css-assets-webpack-plugin": "1.3.0",
|
"> 1%",
|
||||||
"ora": "1.1.0",
|
"last 2 versions"
|
||||||
"pushstate-server": "2.1.0",
|
],
|
||||||
"rimraf": "2.6.0",
|
"bugs": {
|
||||||
"sass-loader": "6.0.5",
|
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
|
||||||
"script-loader": "0.7.0",
|
|
||||||
"semver": "5.3.0",
|
|
||||||
"style-loader": "0.17.0",
|
|
||||||
"url-loader": "0.5.8",
|
|
||||||
"vue-loader": "12.2.1",
|
|
||||||
"vue-style-loader": "3.0.1",
|
|
||||||
"vue-template-compiler": "2.4.2",
|
|
||||||
"webpack": "2.6.1",
|
|
||||||
"webpack-bundle-analyzer": "2.8.2",
|
|
||||||
"webpack-dev-middleware": "1.10.2",
|
|
||||||
"webpack-hot-middleware": "2.18.0",
|
|
||||||
"webpack-merge": "4.1.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 4.0.0",
|
"node": ">=8.9",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 3.0.0"
|
||||||
},
|
},
|
||||||
"browserlist": [
|
"keywords": [
|
||||||
"> 1%",
|
"vue",
|
||||||
"last 2 versions",
|
"admin",
|
||||||
"not ie <= 8"
|
"dashboard",
|
||||||
|
"element-ui",
|
||||||
|
"boilerplate",
|
||||||
|
"admin-template",
|
||||||
|
"management-system"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"lint-staged": {
|
||||||
|
"src/**/*.{js,vue}": [
|
||||||
|
"eslint --fix",
|
||||||
|
"git add"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
{{#if template}}
|
||||||
|
<template>
|
||||||
|
<div />
|
||||||
|
</template>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if script}}
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: '{{ properCase name }}',
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
mounted() {},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if style}}
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
{{/if}}
|
|
@ -0,0 +1,55 @@
|
||||||
|
const { notEmpty } = require('../utils.js')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
description: 'generate vue component',
|
||||||
|
prompts: [{
|
||||||
|
type: 'input',
|
||||||
|
name: 'name',
|
||||||
|
message: 'component name please',
|
||||||
|
validate: notEmpty('name')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'blocks',
|
||||||
|
message: 'Blocks:',
|
||||||
|
choices: [{
|
||||||
|
name: '<template>',
|
||||||
|
value: 'template',
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '<script>',
|
||||||
|
value: 'script',
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'style',
|
||||||
|
value: 'style',
|
||||||
|
checked: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validate(value) {
|
||||||
|
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
|
||||||
|
return 'Components require at least a <script> or <template> tag.'
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions: data => {
|
||||||
|
const name = '{{properCase name}}'
|
||||||
|
const actions = [{
|
||||||
|
type: 'add',
|
||||||
|
path: `src/components/${name}/index.vue`,
|
||||||
|
templateFile: 'plop-templates/component/index.hbs',
|
||||||
|
data: {
|
||||||
|
name: name,
|
||||||
|
template: data.blocks.includes('template'),
|
||||||
|
script: data.blocks.includes('script'),
|
||||||
|
style: data.blocks.includes('style')
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
return actions
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
{{#if state}}
|
||||||
|
const state = {}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if mutations}}
|
||||||
|
const mutations = {}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if actions}}
|
||||||
|
const actions = {}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
{{options}}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
const { notEmpty } = require('../utils.js')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
description: 'generate store',
|
||||||
|
prompts: [{
|
||||||
|
type: 'input',
|
||||||
|
name: 'name',
|
||||||
|
message: 'store name please',
|
||||||
|
validate: notEmpty('name')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'blocks',
|
||||||
|
message: 'Blocks:',
|
||||||
|
choices: [{
|
||||||
|
name: 'state',
|
||||||
|
value: 'state',
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mutations',
|
||||||
|
value: 'mutations',
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actions',
|
||||||
|
value: 'actions',
|
||||||
|
checked: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validate(value) {
|
||||||
|
if (!value.includes('state') || !value.includes('mutations')) {
|
||||||
|
return 'store require at least state and mutations'
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions(data) {
|
||||||
|
const name = '{{name}}'
|
||||||
|
const { blocks } = data
|
||||||
|
const options = ['state', 'mutations']
|
||||||
|
const joinFlag = `,
|
||||||
|
`
|
||||||
|
if (blocks.length === 3) {
|
||||||
|
options.push('actions')
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = [{
|
||||||
|
type: 'add',
|
||||||
|
path: `src/store/modules/${name}.js`,
|
||||||
|
templateFile: 'plop-templates/store/index.hbs',
|
||||||
|
data: {
|
||||||
|
options: options.join(joinFlag),
|
||||||
|
state: blocks.includes('state'),
|
||||||
|
mutations: blocks.includes('mutations'),
|
||||||
|
actions: blocks.includes('actions')
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
return actions
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
exports.notEmpty = name => v =>
|
||||||
|
!v || v.trim() === '' ? `${name} is required` : true
|
|
@ -0,0 +1,26 @@
|
||||||
|
{{#if template}}
|
||||||
|
<template>
|
||||||
|
<div />
|
||||||
|
</template>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if script}}
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: '{{ properCase name }}',
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
mounted() {},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if style}}
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
{{/if}}
|
|
@ -0,0 +1,55 @@
|
||||||
|
const { notEmpty } = require('../utils.js')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
description: 'generate a view',
|
||||||
|
prompts: [{
|
||||||
|
type: 'input',
|
||||||
|
name: 'name',
|
||||||
|
message: 'view name please',
|
||||||
|
validate: notEmpty('name')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'blocks',
|
||||||
|
message: 'Blocks:',
|
||||||
|
choices: [{
|
||||||
|
name: '<template>',
|
||||||
|
value: 'template',
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '<script>',
|
||||||
|
value: 'script',
|
||||||
|
checked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'style',
|
||||||
|
value: 'style',
|
||||||
|
checked: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validate(value) {
|
||||||
|
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
|
||||||
|
return 'View require at least a <script> or <template> tag.'
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions: data => {
|
||||||
|
const name = '{{name}}'
|
||||||
|
const actions = [{
|
||||||
|
type: 'add',
|
||||||
|
path: `src/views/${name}/index.vue`,
|
||||||
|
templateFile: 'plop-templates/view/index.hbs',
|
||||||
|
data: {
|
||||||
|
name: name,
|
||||||
|
template: data.blocks.includes('template'),
|
||||||
|
script: data.blocks.includes('script'),
|
||||||
|
style: data.blocks.includes('style')
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
return actions
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
const viewGenerator = require('./plop-templates/view/prompt')
|
||||||
|
const componentGenerator = require('./plop-templates/component/prompt')
|
||||||
|
const storeGenerator = require('./plop-templates/store/prompt.js')
|
||||||
|
|
||||||
|
module.exports = function(plop) {
|
||||||
|
plop.setGenerator('view', viewGenerator)
|
||||||
|
plop.setGenerator('component', componentGenerator)
|
||||||
|
plop.setGenerator('store', storeGenerator)
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
autoprefixer: {}
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 66 KiB |
|
@ -5,13 +5,11 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
<meta name="renderer" content="webkit">
|
<meta name="renderer" content="webkit">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<title>Juicy</title>
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title><%= webpackConfig.name %></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src=<%= htmlWebpackPlugin.options.path %>jquery.min.js></script>
|
|
||||||
<script src=<%= htmlWebpackPlugin.options.path %>tinymce/tinymce.min.js></script>
|
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -1,15 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<router-view></router-view>
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'APP'
|
name: 'App'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import './styles/index.scss'; // 全局自定义的css样式
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,16 +1,41 @@
|
||||||
import fetch from 'utils/fetch';
|
import request from '@/utils/request'
|
||||||
|
|
||||||
export function getList() {
|
export function fetchList(query) {
|
||||||
return fetch({
|
return request({
|
||||||
url: '/article/list',
|
url: '/vue-element-admin/article/list',
|
||||||
method: 'get'
|
method: 'get',
|
||||||
});
|
params: query
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getArticle() {
|
export function fetchArticle(id) {
|
||||||
return fetch({
|
return request({
|
||||||
url: '/article/detail',
|
url: '/vue-element-admin/article/detail',
|
||||||
method: 'get'
|
method: 'get',
|
||||||
});
|
params: { id }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fetchPv(pv) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/article/pv',
|
||||||
|
method: 'get',
|
||||||
|
params: { pv }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createArticle(data) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/article/create',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateArticle(data) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/article/update',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import fetch from 'utils/fetch';
|
|
||||||
|
|
||||||
export function fetchList(query) {
|
|
||||||
return fetch({
|
|
||||||
url: '/article_table/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fetchPv(pv) {
|
|
||||||
return fetch({
|
|
||||||
url: '/article_table/pv',
|
|
||||||
method: 'get',
|
|
||||||
params: { pv }
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
import fetch from 'utils/fetch';
|
|
||||||
|
|
||||||
export function loginByEmail(email, password) {
|
|
||||||
const data = {
|
|
||||||
email,
|
|
||||||
password
|
|
||||||
};
|
|
||||||
return fetch({
|
|
||||||
url: '/login/loginbyemail',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function logout() {
|
|
||||||
return fetch({
|
|
||||||
url: '/login/logout',
|
|
||||||
method: 'post'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getInfo(token) {
|
|
||||||
return fetch({
|
|
||||||
url: '/user/info',
|
|
||||||
method: 'get',
|
|
||||||
params: { token }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import fetch from 'utils/fetch';
|
import request from '@/utils/request'
|
||||||
|
|
||||||
export function getToken() {
|
export function getToken() {
|
||||||
return fetch({
|
return request({
|
||||||
url: '/qiniu/upload/token', // 假地址 自行替换
|
url: '/qiniu/upload/token', // 假地址 自行替换
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function searchUser(name) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/search/user',
|
||||||
|
method: 'get',
|
||||||
|
params: { name }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transactionList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/transaction/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
import fetch from 'utils/fetch';
|
|
||||||
|
|
||||||
export function userSearch(name) {
|
|
||||||
return fetch({
|
|
||||||
url: '/search/user',
|
|
||||||
method: 'get',
|
|
||||||
params: { name }
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function getRoutes() {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/routes',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRoles() {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/roles',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addRole(data) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/role',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateRole(id, data) {
|
||||||
|
return request({
|
||||||
|
url: `/vue-element-admin/role/${id}`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteRole(id) {
|
||||||
|
return request({
|
||||||
|
url: `/vue-element-admin/role/${id}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function login(data) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/user/login',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInfo(token) {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/user/info',
|
||||||
|
method: 'get',
|
||||||
|
params: { token }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logout() {
|
||||||
|
return request({
|
||||||
|
url: '/vue-element-admin/user/logout',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,199 +0,0 @@
|
||||||
/* eslint-disable */
|
|
||||||
(function (root, factory) {
|
|
||||||
if (typeof define === 'function' && define.amd) {
|
|
||||||
// AMD. Register as an anonymous module.
|
|
||||||
define(['exports', 'echarts'], factory);
|
|
||||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
|
||||||
// CommonJS
|
|
||||||
factory(exports, require('echarts'));
|
|
||||||
} else {
|
|
||||||
// Browser globals
|
|
||||||
factory({}, root.echarts);
|
|
||||||
}
|
|
||||||
}(this, function (exports, echarts) {
|
|
||||||
var log = function (msg) {
|
|
||||||
if (typeof console !== 'undefined') {
|
|
||||||
console && console.error && console.error(msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!echarts) {
|
|
||||||
log('ECharts is not Loaded');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var colorPalette = [
|
|
||||||
'#2ec7c9','#b6a2de','#5ab1ef','#ffb980','#d87a80',
|
|
||||||
'#8d98b3','#e5cf0d','#97b552','#95706d','#dc69aa',
|
|
||||||
'#07a2a4','#9a7fd1','#588dd5','#f5994e','#c05050',
|
|
||||||
'#59678c','#c9ab00','#7eb00a','#6f5553','#c14089'
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
var theme = {
|
|
||||||
color: colorPalette,
|
|
||||||
|
|
||||||
title: {
|
|
||||||
textStyle: {
|
|
||||||
fontWeight: 'normal',
|
|
||||||
color: '#008acd'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
visualMap: {
|
|
||||||
itemWidth: 15,
|
|
||||||
color: ['#5ab1ef','#e0ffff']
|
|
||||||
},
|
|
||||||
|
|
||||||
toolbox: {
|
|
||||||
iconStyle: {
|
|
||||||
normal: {
|
|
||||||
borderColor: colorPalette[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
tooltip: {
|
|
||||||
backgroundColor: 'rgba(50,50,50,0.5)',
|
|
||||||
axisPointer : {
|
|
||||||
type : 'line',
|
|
||||||
lineStyle : {
|
|
||||||
color: '#008acd'
|
|
||||||
},
|
|
||||||
crossStyle: {
|
|
||||||
color: '#008acd'
|
|
||||||
},
|
|
||||||
shadowStyle : {
|
|
||||||
color: 'rgba(200,200,200,0.2)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
dataZoom: {
|
|
||||||
dataBackgroundColor: '#efefff',
|
|
||||||
fillerColor: 'rgba(182,162,222,0.2)',
|
|
||||||
handleColor: '#008acd'
|
|
||||||
},
|
|
||||||
|
|
||||||
grid: {
|
|
||||||
borderColor: '#eee'
|
|
||||||
},
|
|
||||||
|
|
||||||
categoryAxis: {
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#008acd'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: ['#eee']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
valueAxis: {
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#008acd'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitArea : {
|
|
||||||
show : true,
|
|
||||||
areaStyle : {
|
|
||||||
color: ['rgba(250,250,250,0.1)','rgba(200,200,200,0.1)']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: ['#eee']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
timeline : {
|
|
||||||
lineStyle : {
|
|
||||||
color : '#008acd'
|
|
||||||
},
|
|
||||||
controlStyle : {
|
|
||||||
normal : { color : '#008acd'},
|
|
||||||
emphasis : { color : '#008acd'}
|
|
||||||
},
|
|
||||||
symbol : 'emptyCircle',
|
|
||||||
symbolSize : 3
|
|
||||||
},
|
|
||||||
|
|
||||||
line: {
|
|
||||||
smooth : true,
|
|
||||||
symbol: 'emptyCircle',
|
|
||||||
symbolSize: 3
|
|
||||||
},
|
|
||||||
|
|
||||||
candlestick: {
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: '#d87a80',
|
|
||||||
color0: '#2ec7c9',
|
|
||||||
lineStyle: {
|
|
||||||
color: '#d87a80',
|
|
||||||
color0: '#2ec7c9'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
scatter: {
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 4
|
|
||||||
},
|
|
||||||
|
|
||||||
map: {
|
|
||||||
label: {
|
|
||||||
normal: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#d87a80'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
borderColor: '#eee',
|
|
||||||
areaColor: '#ddd'
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
areaColor: '#fe994e'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
graph: {
|
|
||||||
color: colorPalette
|
|
||||||
},
|
|
||||||
|
|
||||||
gauge : {
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: [[0.2, '#2ec7c9'],[0.8, '#5ab1ef'],[1, '#d87a80']],
|
|
||||||
width: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
splitNumber: 10,
|
|
||||||
length :15,
|
|
||||||
lineStyle: {
|
|
||||||
color: 'auto'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
length :22,
|
|
||||||
lineStyle: {
|
|
||||||
color: 'auto'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pointer : {
|
|
||||||
width : 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
echarts.registerTheme('macarons', theme);
|
|
||||||
}));
|
|
|
@ -1,12 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<transition :name="transitionName">
|
<transition :name="transitionName">
|
||||||
<div class="back-to-top" @click="backToTop" v-show="visible" :style="customStyle">
|
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
|
||||||
<svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height: 16px; width: 16px;">
|
<svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height:16px;width:16px"><path d="M12.036 15.59a1 1 0 0 1-.997.995H5.032a.996.996 0 0 1-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" /></svg>
|
||||||
<title>回到顶部</title>
|
|
||||||
<g>
|
|
||||||
<path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd"></path>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
@ -25,7 +20,8 @@
|
||||||
},
|
},
|
||||||
customStyle: {
|
customStyle: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: {
|
default: function() {
|
||||||
|
return {
|
||||||
right: '50px',
|
right: '50px',
|
||||||
bottom: '50px',
|
bottom: '50px',
|
||||||
width: '40px',
|
width: '40px',
|
||||||
|
@ -34,6 +30,7 @@
|
||||||
'line-height': '45px',
|
'line-height': '45px',
|
||||||
background: '#e7eaf1'
|
background: '#e7eaf1'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
transitionName: {
|
transitionName: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -43,53 +40,57 @@
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
interval: null
|
interval: null,
|
||||||
|
isMoving: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
window.addEventListener('scroll', this.handleScroll);
|
window.addEventListener('scroll', this.handleScroll)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('scroll', this.handleScroll);
|
window.removeEventListener('scroll', this.handleScroll)
|
||||||
if (this.interval) {
|
if (this.interval) {
|
||||||
clearInterval(this.interval);
|
clearInterval(this.interval)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleScroll() {
|
handleScroll() {
|
||||||
this.visible = window.pageYOffset > this.visibilityHeight;
|
this.visible = window.pageYOffset > this.visibilityHeight
|
||||||
},
|
},
|
||||||
backToTop() {
|
backToTop() {
|
||||||
const start = window.pageYOffset;
|
if (this.isMoving) return
|
||||||
let i = 0;
|
const start = window.pageYOffset
|
||||||
|
let i = 0
|
||||||
|
this.isMoving = true
|
||||||
this.interval = setInterval(() => {
|
this.interval = setInterval(() => {
|
||||||
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500));
|
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
|
||||||
if (next <= this.backPosition) {
|
if (next <= this.backPosition) {
|
||||||
window.scrollTo(0, this.backPosition);
|
window.scrollTo(0, this.backPosition)
|
||||||
clearInterval(this.interval)
|
clearInterval(this.interval)
|
||||||
|
this.isMoving = false
|
||||||
} else {
|
} else {
|
||||||
window.scrollTo(0, next);
|
window.scrollTo(0, next)
|
||||||
}
|
}
|
||||||
i++;
|
i++
|
||||||
}, 16.7)
|
}, 16.7)
|
||||||
},
|
},
|
||||||
easeInOutQuad(t, b, c, d) {
|
easeInOutQuad(t, b, c, d) {
|
||||||
if ((t /= d / 2) < 1) return c / 2 * t * t + b;
|
if ((t /= d / 2) < 1) return c / 2 * t * t + b
|
||||||
return -c / 2 * (--t * (t - 2) - 1) + b;
|
return -c / 2 * (--t * (t - 2) - 1) + b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.back-to-top {
|
.back-to-ceiling {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-top:hover {
|
.back-to-ceiling:hover {
|
||||||
background: #d5dbe7;
|
background: #d5dbe7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +104,7 @@
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-top .Icon {
|
.back-to-ceiling .Icon {
|
||||||
fill: #9aaabf;
|
fill: #9aaabf;
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<template>
|
||||||
|
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||||
|
<transition-group name="breadcrumb">
|
||||||
|
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
||||||
|
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
|
||||||
|
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||||
|
</el-breadcrumb-item>
|
||||||
|
</transition-group>
|
||||||
|
</el-breadcrumb>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import pathToRegexp from 'path-to-regexp'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
levelList: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
$route(route) {
|
||||||
|
// if you go to the redirect page, do not update the breadcrumbs
|
||||||
|
if (route.path.startsWith('/redirect/')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.getBreadcrumb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getBreadcrumb()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getBreadcrumb() {
|
||||||
|
// only show routes with meta.title
|
||||||
|
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
||||||
|
const first = matched[0]
|
||||||
|
|
||||||
|
if (!this.isDashboard(first)) {
|
||||||
|
matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||||
|
},
|
||||||
|
isDashboard(route) {
|
||||||
|
const name = route && route.name
|
||||||
|
if (!name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
|
||||||
|
},
|
||||||
|
pathCompile(path) {
|
||||||
|
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
||||||
|
const { params } = this.$route
|
||||||
|
var toPath = pathToRegexp.compile(path)
|
||||||
|
return toPath(params)
|
||||||
|
},
|
||||||
|
handleLink(item) {
|
||||||
|
const { redirect, path } = item
|
||||||
|
if (redirect) {
|
||||||
|
this.$router.push(redirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$router.push(this.pathCompile(path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-breadcrumb.el-breadcrumb {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 50px;
|
||||||
|
margin-left: 8px;
|
||||||
|
|
||||||
|
.no-redirect {
|
||||||
|
color: #97a8be;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import echarts from 'echarts'
|
||||||
|
import resize from './mixins/resize'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [resize],
|
||||||
|
props: {
|
||||||
|
className: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart'
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chart: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initChart()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (!this.chart) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.chart.dispose()
|
||||||
|
this.chart = null
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initChart() {
|
||||||
|
this.chart = echarts.init(document.getElementById(this.id))
|
||||||
|
|
||||||
|
const xAxisData = []
|
||||||
|
const data = []
|
||||||
|
const data2 = []
|
||||||
|
for (let i = 0; i < 50; i++) {
|
||||||
|
xAxisData.push(i)
|
||||||
|
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
|
||||||
|
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
|
||||||
|
}
|
||||||
|
this.chart.setOption({
|
||||||
|
backgroundColor: '#08263a',
|
||||||
|
grid: {
|
||||||
|
left: '5%',
|
||||||
|
right: '5%'
|
||||||
|
},
|
||||||
|
xAxis: [{
|
||||||
|
show: false,
|
||||||
|
data: xAxisData
|
||||||
|
}, {
|
||||||
|
show: false,
|
||||||
|
data: xAxisData
|
||||||
|
}],
|
||||||
|
visualMap: {
|
||||||
|
show: false,
|
||||||
|
min: 0,
|
||||||
|
max: 50,
|
||||||
|
dimension: 0,
|
||||||
|
inRange: {
|
||||||
|
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
axisLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
textStyle: {
|
||||||
|
color: '#4a657a'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#08263f'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: 'back',
|
||||||
|
type: 'bar',
|
||||||
|
data: data2,
|
||||||
|
z: 1,
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
opacity: 0.4,
|
||||||
|
barBorderRadius: 5,
|
||||||
|
shadowBlur: 3,
|
||||||
|
shadowColor: '#111'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: 'Simulate Shadow',
|
||||||
|
type: 'line',
|
||||||
|
data,
|
||||||
|
z: 2,
|
||||||
|
showSymbol: false,
|
||||||
|
animationDelay: 0,
|
||||||
|
animationEasing: 'linear',
|
||||||
|
animationDuration: 1200,
|
||||||
|
lineStyle: {
|
||||||
|
normal: {
|
||||||
|
color: 'transparent'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
normal: {
|
||||||
|
color: '#08263a',
|
||||||
|
shadowBlur: 50,
|
||||||
|
shadowColor: '#000'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: 'front',
|
||||||
|
type: 'bar',
|
||||||
|
data,
|
||||||
|
xAxisIndex: 1,
|
||||||
|
z: 3,
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
barBorderRadius: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
animationEasing: 'elasticOut',
|
||||||
|
animationEasingUpdate: 'elasticOut',
|
||||||
|
animationDelay(idx) {
|
||||||
|
return idx * 20
|
||||||
|
},
|
||||||
|
animationDelayUpdate(idx) {
|
||||||
|
return idx * 20
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,227 @@
|
||||||
|
<template>
|
||||||
|
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import echarts from 'echarts'
|
||||||
|
import resize from './mixins/resize'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [resize],
|
||||||
|
props: {
|
||||||
|
className: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart'
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chart: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initChart()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (!this.chart) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.chart.dispose()
|
||||||
|
this.chart = null
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initChart() {
|
||||||
|
this.chart = echarts.init(document.getElementById(this.id))
|
||||||
|
|
||||||
|
this.chart.setOption({
|
||||||
|
backgroundColor: '#394056',
|
||||||
|
title: {
|
||||||
|
top: 20,
|
||||||
|
text: 'Requests',
|
||||||
|
textStyle: {
|
||||||
|
fontWeight: 'normal',
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#F1F1F3'
|
||||||
|
},
|
||||||
|
left: '1%'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#57617B'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: 20,
|
||||||
|
icon: 'rect',
|
||||||
|
itemWidth: 14,
|
||||||
|
itemHeight: 5,
|
||||||
|
itemGap: 13,
|
||||||
|
data: ['CMCC', 'CTCC', 'CUCC'],
|
||||||
|
right: '4%',
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: '#F1F1F3'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: 100,
|
||||||
|
left: '2%',
|
||||||
|
right: '2%',
|
||||||
|
bottom: '2%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: [{
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#57617B'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
|
||||||
|
}],
|
||||||
|
yAxis: [{
|
||||||
|
type: 'value',
|
||||||
|
name: '(%)',
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#57617B'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
margin: 10,
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#57617B'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
series: [{
|
||||||
|
name: 'CMCC',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 5,
|
||||||
|
showSymbol: false,
|
||||||
|
lineStyle: {
|
||||||
|
normal: {
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
normal: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(137, 189, 27, 0.3)'
|
||||||
|
}, {
|
||||||
|
offset: 0.8,
|
||||||
|
color: 'rgba(137, 189, 27, 0)'
|
||||||
|
}], false),
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||||
|
shadowBlur: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: 'rgb(137,189,27)',
|
||||||
|
borderColor: 'rgba(137,189,2,0.27)',
|
||||||
|
borderWidth: 12
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
|
||||||
|
}, {
|
||||||
|
name: 'CTCC',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 5,
|
||||||
|
showSymbol: false,
|
||||||
|
lineStyle: {
|
||||||
|
normal: {
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
normal: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(0, 136, 212, 0.3)'
|
||||||
|
}, {
|
||||||
|
offset: 0.8,
|
||||||
|
color: 'rgba(0, 136, 212, 0)'
|
||||||
|
}], false),
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||||
|
shadowBlur: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: 'rgb(0,136,212)',
|
||||||
|
borderColor: 'rgba(0,136,212,0.2)',
|
||||||
|
borderWidth: 12
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
|
||||||
|
}, {
|
||||||
|
name: 'CUCC',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 5,
|
||||||
|
showSymbol: false,
|
||||||
|
lineStyle: {
|
||||||
|
normal: {
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
normal: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(219, 50, 51, 0.3)'
|
||||||
|
}, {
|
||||||
|
offset: 0.8,
|
||||||
|
color: 'rgba(219, 50, 51, 0)'
|
||||||
|
}], false),
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||||
|
shadowBlur: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: 'rgb(219,50,51)',
|
||||||
|
borderColor: 'rgba(219,50,51,0.2)',
|
||||||
|
borderWidth: 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,271 @@
|
||||||
|
<template>
|
||||||
|
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import echarts from 'echarts'
|
||||||
|
import resize from './mixins/resize'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [resize],
|
||||||
|
props: {
|
||||||
|
className: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart'
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chart: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initChart()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (!this.chart) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.chart.dispose()
|
||||||
|
this.chart = null
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initChart() {
|
||||||
|
this.chart = echarts.init(document.getElementById(this.id))
|
||||||
|
const xData = (function() {
|
||||||
|
const data = []
|
||||||
|
for (let i = 1; i < 13; i++) {
|
||||||
|
data.push(i + 'month')
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}())
|
||||||
|
this.chart.setOption({
|
||||||
|
backgroundColor: '#344b58',
|
||||||
|
title: {
|
||||||
|
text: 'statistics',
|
||||||
|
x: '20',
|
||||||
|
top: '20',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: '22'
|
||||||
|
},
|
||||||
|
subtextStyle: {
|
||||||
|
color: '#90979c',
|
||||||
|
fontSize: '16'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '5%',
|
||||||
|
right: '5%',
|
||||||
|
borderWidth: 0,
|
||||||
|
top: 150,
|
||||||
|
bottom: 95,
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
x: '5%',
|
||||||
|
top: '10%',
|
||||||
|
textStyle: {
|
||||||
|
color: '#90979c'
|
||||||
|
},
|
||||||
|
data: ['female', 'male', 'average']
|
||||||
|
},
|
||||||
|
calculable: true,
|
||||||
|
xAxis: [{
|
||||||
|
type: 'category',
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#90979c'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
splitArea: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0
|
||||||
|
|
||||||
|
},
|
||||||
|
data: xData
|
||||||
|
}],
|
||||||
|
yAxis: [{
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#90979c'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0
|
||||||
|
},
|
||||||
|
splitArea: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
dataZoom: [{
|
||||||
|
show: true,
|
||||||
|
height: 30,
|
||||||
|
xAxisIndex: [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
bottom: 30,
|
||||||
|
start: 10,
|
||||||
|
end: 80,
|
||||||
|
handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
|
||||||
|
handleSize: '110%',
|
||||||
|
handleStyle: {
|
||||||
|
color: '#d3dee5'
|
||||||
|
|
||||||
|
},
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff' },
|
||||||
|
borderColor: '#90979c'
|
||||||
|
|
||||||
|
}, {
|
||||||
|
type: 'inside',
|
||||||
|
show: true,
|
||||||
|
height: 15,
|
||||||
|
start: 1,
|
||||||
|
end: 35
|
||||||
|
}],
|
||||||
|
series: [{
|
||||||
|
name: 'female',
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'total',
|
||||||
|
barMaxWidth: 35,
|
||||||
|
barGap: '10%',
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: 'rgba(255,144,128,1)',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
position: 'insideTop',
|
||||||
|
formatter(p) {
|
||||||
|
return p.value > 0 ? p.value : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
709,
|
||||||
|
1917,
|
||||||
|
2455,
|
||||||
|
2610,
|
||||||
|
1719,
|
||||||
|
1433,
|
||||||
|
1544,
|
||||||
|
3285,
|
||||||
|
5208,
|
||||||
|
3372,
|
||||||
|
2484,
|
||||||
|
4078
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'male',
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'total',
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: 'rgba(0,191,183,1)',
|
||||||
|
barBorderRadius: 0,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
formatter(p) {
|
||||||
|
return p.value > 0 ? p.value : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
327,
|
||||||
|
1776,
|
||||||
|
507,
|
||||||
|
1200,
|
||||||
|
800,
|
||||||
|
482,
|
||||||
|
204,
|
||||||
|
1390,
|
||||||
|
1001,
|
||||||
|
951,
|
||||||
|
381,
|
||||||
|
220
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
name: 'average',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'total',
|
||||||
|
symbolSize: 10,
|
||||||
|
symbol: 'circle',
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: 'rgba(252,230,48,1)',
|
||||||
|
barBorderRadius: 0,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
formatter(p) {
|
||||||
|
return p.value > 0 ? p.value : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
1036,
|
||||||
|
3693,
|
||||||
|
2962,
|
||||||
|
3810,
|
||||||
|
2519,
|
||||||
|
1915,
|
||||||
|
1748,
|
||||||
|
4675,
|
||||||
|
6209,
|
||||||
|
4323,
|
||||||
|
2865,
|
||||||
|
4298
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,113 +0,0 @@
|
||||||
<template>
|
|
||||||
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import echarts from 'echarts';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chart: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initChart();
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (!this.chart) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chart.dispose();
|
|
||||||
this.chart = null;
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(document.getElementById(this.id));
|
|
||||||
|
|
||||||
const xAxisData = [];
|
|
||||||
const data = [];
|
|
||||||
for (let i = 0; i < 30; i++) {
|
|
||||||
xAxisData.push(i + '号');
|
|
||||||
data.push(Math.round(Math.random() * 2 + 3))
|
|
||||||
}
|
|
||||||
|
|
||||||
this.chart.setOption(
|
|
||||||
{
|
|
||||||
backgroundColor: '#08263a',
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
show: false,
|
|
||||||
data: xAxisData
|
|
||||||
},
|
|
||||||
visualMap: {
|
|
||||||
show: false,
|
|
||||||
min: 0,
|
|
||||||
max: 50,
|
|
||||||
dimension: 0,
|
|
||||||
inRange: {
|
|
||||||
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
axisLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#4a657a'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#08263f'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {}
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
type: 'bar',
|
|
||||||
data,
|
|
||||||
name: '撸文数',
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
barBorderRadius: 5,
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowColor: '#111'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
animationEasing: 'elasticOut',
|
|
||||||
animationEasingUpdate: 'elasticOut',
|
|
||||||
animationDelay(idx) {
|
|
||||||
return idx * 20;
|
|
||||||
},
|
|
||||||
animationDelayUpdate(idx) {
|
|
||||||
return idx * 20;
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,150 +0,0 @@
|
||||||
<template>
|
|
||||||
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import echarts from 'echarts';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chart: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initChart();
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (!this.chart) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chart.dispose();
|
|
||||||
this.chart = null;
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(document.getElementById(this.id));
|
|
||||||
|
|
||||||
const xAxisData = [];
|
|
||||||
const data = [];
|
|
||||||
const data2 = [];
|
|
||||||
for (let i = 0; i < 50; i++) {
|
|
||||||
xAxisData.push(i);
|
|
||||||
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5);
|
|
||||||
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3);
|
|
||||||
}
|
|
||||||
this.chart.setOption(
|
|
||||||
{
|
|
||||||
backgroundColor: '#08263a',
|
|
||||||
xAxis: [{
|
|
||||||
show: false,
|
|
||||||
data: xAxisData
|
|
||||||
}, {
|
|
||||||
show: false,
|
|
||||||
data: xAxisData
|
|
||||||
}],
|
|
||||||
visualMap: {
|
|
||||||
show: false,
|
|
||||||
min: 0,
|
|
||||||
max: 50,
|
|
||||||
dimension: 0,
|
|
||||||
inRange: {
|
|
||||||
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
axisLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#4a657a'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#08263f'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
name: 'back',
|
|
||||||
type: 'bar',
|
|
||||||
data: data2,
|
|
||||||
z: 1,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
opacity: 0.4,
|
|
||||||
barBorderRadius: 5,
|
|
||||||
shadowBlur: 3,
|
|
||||||
shadowColor: '#111'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: 'Simulate Shadow',
|
|
||||||
type: 'line',
|
|
||||||
data,
|
|
||||||
z: 2,
|
|
||||||
showSymbol: false,
|
|
||||||
animationDelay: 0,
|
|
||||||
animationEasing: 'linear',
|
|
||||||
animationDuration: 1200,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'transparent'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: '#08263a',
|
|
||||||
shadowBlur: 50,
|
|
||||||
shadowColor: '#000'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: 'front',
|
|
||||||
type: 'bar',
|
|
||||||
data,
|
|
||||||
xAxisIndex: 1,
|
|
||||||
z: 3,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
barBorderRadius: 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
animationEasing: 'elasticOut',
|
|
||||||
animationEasingUpdate: 'elasticOut',
|
|
||||||
animationDelay(idx) {
|
|
||||||
return idx * 20;
|
|
||||||
},
|
|
||||||
animationDelayUpdate(idx) {
|
|
||||||
return idx * 20;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,222 +0,0 @@
|
||||||
<template>
|
|
||||||
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import echarts from 'echarts';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chart: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initChart();
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (!this.chart) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chart.dispose();
|
|
||||||
this.chart = null;
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(document.getElementById(this.id));
|
|
||||||
|
|
||||||
this.chart.setOption({
|
|
||||||
backgroundColor: '#394056',
|
|
||||||
title: {
|
|
||||||
text: '请求数',
|
|
||||||
textStyle: {
|
|
||||||
fontWeight: 'normal',
|
|
||||||
fontSize: 16,
|
|
||||||
color: '#F1F1F3'
|
|
||||||
},
|
|
||||||
left: '6%'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#57617B'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
icon: 'rect',
|
|
||||||
itemWidth: 14,
|
|
||||||
itemHeight: 5,
|
|
||||||
itemGap: 13,
|
|
||||||
data: ['移动', '电信', '联通'],
|
|
||||||
right: '4%',
|
|
||||||
textStyle: {
|
|
||||||
fontSize: 12,
|
|
||||||
color: '#F1F1F3'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '3%',
|
|
||||||
right: '4%',
|
|
||||||
bottom: '3%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: [{
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#57617B'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
|
|
||||||
}],
|
|
||||||
yAxis: [{
|
|
||||||
type: 'value',
|
|
||||||
name: '单位(%)',
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#57617B'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
margin: 10,
|
|
||||||
textStyle: {
|
|
||||||
fontSize: 14
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#57617B'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
series: [{
|
|
||||||
name: '移动',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 5,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(137, 189, 27, 0.3)'
|
|
||||||
}, {
|
|
||||||
offset: 0.8,
|
|
||||||
color: 'rgba(137, 189, 27, 0)'
|
|
||||||
}], false),
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgb(137,189,27)',
|
|
||||||
borderColor: 'rgba(137,189,2,0.27)',
|
|
||||||
borderWidth: 12
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
|
|
||||||
}, {
|
|
||||||
name: '电信',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 5,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(0, 136, 212, 0.3)'
|
|
||||||
}, {
|
|
||||||
offset: 0.8,
|
|
||||||
color: 'rgba(0, 136, 212, 0)'
|
|
||||||
}], false),
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgb(0,136,212)',
|
|
||||||
borderColor: 'rgba(0,136,212,0.2)',
|
|
||||||
borderWidth: 12
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
|
|
||||||
}, {
|
|
||||||
name: '联通',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 5,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(219, 50, 51, 0.3)'
|
|
||||||
}, {
|
|
||||||
offset: 0.8,
|
|
||||||
color: 'rgba(219, 50, 51, 0)'
|
|
||||||
}], false),
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgb(219,50,51)',
|
|
||||||
borderColor: 'rgba(219,50,51,0.2)',
|
|
||||||
borderWidth: 12
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,268 +0,0 @@
|
||||||
<template>
|
|
||||||
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import echarts from 'echarts';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chart: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initChart();
|
|
||||||
this.chart = null;
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (!this.chart) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chart.dispose();
|
|
||||||
this.chart = null;
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(document.getElementById(this.id));
|
|
||||||
const xData = (function() {
|
|
||||||
const data = [];
|
|
||||||
for (let i = 1; i < 13; i++) {
|
|
||||||
data.push(i + '月份');
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}());
|
|
||||||
this.chart.setOption({
|
|
||||||
backgroundColor: '#344b58',
|
|
||||||
title: {
|
|
||||||
text: '统计',
|
|
||||||
x: '4%',
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: '22'
|
|
||||||
},
|
|
||||||
subtextStyle: {
|
|
||||||
color: '#90979c',
|
|
||||||
fontSize: '16'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
borderWidth: 0,
|
|
||||||
top: 110,
|
|
||||||
bottom: 95,
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
x: '15%',
|
|
||||||
top: '10%',
|
|
||||||
textStyle: {
|
|
||||||
color: '#90979c'
|
|
||||||
},
|
|
||||||
data: ['女', '男', '平均']
|
|
||||||
},
|
|
||||||
calculable: true,
|
|
||||||
xAxis: [{
|
|
||||||
type: 'category',
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#90979c'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
splitArea: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
interval: 0
|
|
||||||
|
|
||||||
},
|
|
||||||
data: xData
|
|
||||||
}],
|
|
||||||
yAxis: [{
|
|
||||||
type: 'value',
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#90979c'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
interval: 0
|
|
||||||
},
|
|
||||||
splitArea: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
dataZoom: [{
|
|
||||||
show: true,
|
|
||||||
height: 30,
|
|
||||||
xAxisIndex: [
|
|
||||||
0
|
|
||||||
],
|
|
||||||
bottom: 30,
|
|
||||||
start: 10,
|
|
||||||
end: 80,
|
|
||||||
handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
|
|
||||||
handleSize: '110%',
|
|
||||||
handleStyle: {
|
|
||||||
color: '#d3dee5'
|
|
||||||
|
|
||||||
},
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff' },
|
|
||||||
borderColor: '#90979c'
|
|
||||||
|
|
||||||
|
|
||||||
}, {
|
|
||||||
type: 'inside',
|
|
||||||
show: true,
|
|
||||||
height: 15,
|
|
||||||
start: 1,
|
|
||||||
end: 35
|
|
||||||
}],
|
|
||||||
series: [{
|
|
||||||
name: '女',
|
|
||||||
type: 'bar',
|
|
||||||
stack: '总量',
|
|
||||||
barMaxWidth: 35,
|
|
||||||
barGap: '10%',
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgba(255,144,128,1)',
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
},
|
|
||||||
position: 'insideTop',
|
|
||||||
formatter(p) {
|
|
||||||
return p.value > 0 ? p.value : '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
709,
|
|
||||||
1917,
|
|
||||||
2455,
|
|
||||||
2610,
|
|
||||||
1719,
|
|
||||||
1433,
|
|
||||||
1544,
|
|
||||||
3285,
|
|
||||||
5208,
|
|
||||||
3372,
|
|
||||||
2484,
|
|
||||||
4078
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: '男',
|
|
||||||
type: 'bar',
|
|
||||||
stack: '总量',
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgba(0,191,183,1)',
|
|
||||||
barBorderRadius: 0,
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'top',
|
|
||||||
formatter(p) {
|
|
||||||
return p.value > 0 ? p.value : '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
327,
|
|
||||||
1776,
|
|
||||||
507,
|
|
||||||
1200,
|
|
||||||
800,
|
|
||||||
482,
|
|
||||||
204,
|
|
||||||
1390,
|
|
||||||
1001,
|
|
||||||
951,
|
|
||||||
381,
|
|
||||||
220
|
|
||||||
]
|
|
||||||
}, {
|
|
||||||
name: '平均',
|
|
||||||
type: 'line',
|
|
||||||
stack: '总量',
|
|
||||||
symbolSize: 10,
|
|
||||||
symbol: 'circle',
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgba(252,230,48,1)',
|
|
||||||
barBorderRadius: 0,
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'top',
|
|
||||||
formatter(p) {
|
|
||||||
return p.value > 0 ? p.value : '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
1036,
|
|
||||||
3693,
|
|
||||||
2962,
|
|
||||||
3810,
|
|
||||||
2519,
|
|
||||||
1915,
|
|
||||||
1748,
|
|
||||||
4675,
|
|
||||||
6209,
|
|
||||||
4323,
|
|
||||||
2865,
|
|
||||||
4298
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { debounce } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
$_sidebarElm: null,
|
||||||
|
$_resizeHandler: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initListener()
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
if (!this.$_resizeHandler) {
|
||||||
|
// avoid duplication init
|
||||||
|
this.initListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
// when keep-alive chart activated, auto resize
|
||||||
|
this.resize()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.destroyListener()
|
||||||
|
},
|
||||||
|
deactivated() {
|
||||||
|
this.destroyListener()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// use $_ for mixins properties
|
||||||
|
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
||||||
|
$_sidebarResizeHandler(e) {
|
||||||
|
if (e.propertyName === 'width') {
|
||||||
|
this.$_resizeHandler()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initListener() {
|
||||||
|
this.$_resizeHandler = debounce(() => {
|
||||||
|
this.resize()
|
||||||
|
}, 100)
|
||||||
|
window.addEventListener('resize', this.$_resizeHandler)
|
||||||
|
|
||||||
|
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||||
|
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||||
|
},
|
||||||
|
destroyListener() {
|
||||||
|
window.removeEventListener('resize', this.$_resizeHandler)
|
||||||
|
this.$_resizeHandler = null
|
||||||
|
|
||||||
|
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||||
|
},
|
||||||
|
resize() {
|
||||||
|
const { chart } = this
|
||||||
|
chart && chart.resize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
<template>
|
||||||
|
<div class="dndList">
|
||||||
|
<div :style="{width:width1}" class="dndList-list">
|
||||||
|
<h3>{{ list1Title }}</h3>
|
||||||
|
<draggable :set-data="setData" :list="list1" group="article" class="dragArea">
|
||||||
|
<div v-for="element in list1" :key="element.id" class="list-complete-item">
|
||||||
|
<div class="list-complete-item-handle">
|
||||||
|
{{ element.id }}[{{ element.author }}] {{ element.title }}
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute;right:0px;">
|
||||||
|
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
|
||||||
|
<i style="color:#ff4949" class="el-icon-delete" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</draggable>
|
||||||
|
</div>
|
||||||
|
<div :style="{width:width2}" class="dndList-list">
|
||||||
|
<h3>{{ list2Title }}</h3>
|
||||||
|
<draggable :list="list2" group="article" class="dragArea">
|
||||||
|
<div v-for="element in list2" :key="element.id" class="list-complete-item">
|
||||||
|
<div class="list-complete-item-handle2" @click="pushEle(element)">
|
||||||
|
{{ element.id }} [{{ element.author }}] {{ element.title }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</draggable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DndList',
|
||||||
|
components: { draggable },
|
||||||
|
props: {
|
||||||
|
list1: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list2: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list1Title: {
|
||||||
|
type: String,
|
||||||
|
default: 'list1'
|
||||||
|
},
|
||||||
|
list2Title: {
|
||||||
|
type: String,
|
||||||
|
default: 'list2'
|
||||||
|
},
|
||||||
|
width1: {
|
||||||
|
type: String,
|
||||||
|
default: '48%'
|
||||||
|
},
|
||||||
|
width2: {
|
||||||
|
type: String,
|
||||||
|
default: '48%'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isNotInList1(v) {
|
||||||
|
return this.list1.every(k => v.id !== k.id)
|
||||||
|
},
|
||||||
|
isNotInList2(v) {
|
||||||
|
return this.list2.every(k => v.id !== k.id)
|
||||||
|
},
|
||||||
|
deleteEle(ele) {
|
||||||
|
for (const item of this.list1) {
|
||||||
|
if (item.id === ele.id) {
|
||||||
|
const index = this.list1.indexOf(item)
|
||||||
|
this.list1.splice(index, 1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isNotInList2(ele)) {
|
||||||
|
this.list2.unshift(ele)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pushEle(ele) {
|
||||||
|
for (const item of this.list2) {
|
||||||
|
if (item.id === ele.id) {
|
||||||
|
const index = this.list2.indexOf(item)
|
||||||
|
this.list2.splice(index, 1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isNotInList1(ele)) {
|
||||||
|
this.list1.push(ele)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setData(dataTransfer) {
|
||||||
|
// to avoid Firefox bug
|
||||||
|
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||||
|
dataTransfer.setData('Text', '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.dndList {
|
||||||
|
background: #fff;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.dndList-list {
|
||||||
|
float: left;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
&:first-of-type {
|
||||||
|
margin-right: 2%;
|
||||||
|
}
|
||||||
|
.dragArea {
|
||||||
|
margin-top: 15px;
|
||||||
|
min-height: 50px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-complete-item {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 5px 12px;
|
||||||
|
margin-top: 4px;
|
||||||
|
border: 1px solid #bfcbd9;
|
||||||
|
transition: all 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-complete-item-handle {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-complete-item-handle2 {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-complete-item.sortable-chosen {
|
||||||
|
background: #4AB7BD;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-complete-item.sortable-ghost {
|
||||||
|
background: #30B08F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-complete-enter,
|
||||||
|
.list-complete-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,65 @@
|
||||||
|
<template>
|
||||||
|
<el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
|
||||||
|
<slot />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Sortable from 'sortablejs'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DragSelect',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectVal: {
|
||||||
|
get() {
|
||||||
|
return [...this.value]
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('input', [...val])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setSort()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setSort() {
|
||||||
|
const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
|
||||||
|
this.sortable = Sortable.create(el, {
|
||||||
|
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
|
||||||
|
setData: function(dataTransfer) {
|
||||||
|
dataTransfer.setData('Text', '')
|
||||||
|
// to avoid Firefox bug
|
||||||
|
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||||
|
},
|
||||||
|
onEnd: evt => {
|
||||||
|
const targetRow = this.value.splice(evt.oldIndex, 1)[0]
|
||||||
|
this.value.splice(evt.newIndex, 0, targetRow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.drag-select {
|
||||||
|
::v-deep {
|
||||||
|
.sortable-ghost {
|
||||||
|
opacity: .8;
|
||||||
|
color: #fff !important;
|
||||||
|
background: #42b983 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,151 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div :ref="id" :action="url" class="dropzone" :id="id">
|
<div :id="id" :ref="id" :action="url" class="dropzone">
|
||||||
<input type="file" name="file">
|
<input type="file" name="file">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Dropzone from 'dropzone';
|
import Dropzone from 'dropzone'
|
||||||
import 'dropzone/dist/dropzone.css';
|
import 'dropzone/dist/dropzone.css'
|
||||||
// import { getToken } from 'api/qiniu';
|
// import { getToken } from 'api/qiniu';
|
||||||
|
|
||||||
Dropzone.autoDiscover = false;
|
Dropzone.autoDiscover = false
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dropzone: '',
|
|
||||||
initOnce: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
const element = document.getElementById(this.id);
|
|
||||||
const vm = this;
|
|
||||||
this.dropzone = new Dropzone(element, {
|
|
||||||
clickable: this.clickable,
|
|
||||||
thumbnailWidth: this.thumbnailWidth,
|
|
||||||
thumbnailHeight: this.thumbnailHeight,
|
|
||||||
maxFiles: this.maxFiles,
|
|
||||||
maxFilesize: this.maxFilesize,
|
|
||||||
dictRemoveFile: 'Remove',
|
|
||||||
addRemoveLinks: this.showRemoveLink,
|
|
||||||
acceptedFiles: this.acceptedFiles,
|
|
||||||
autoProcessQueue: this.autoProcessQueue,
|
|
||||||
dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload',
|
|
||||||
dictMaxFilesExceeded: '只能一个图',
|
|
||||||
previewTemplate: '<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
|
|
||||||
init() {
|
|
||||||
const val = vm.defaultImg;
|
|
||||||
if (!val) return;
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
if (val.length === 0) return;
|
|
||||||
val.map((v, i) => {
|
|
||||||
const mockFile = { name: 'name' + i, size: 12345, url: v };
|
|
||||||
this.options.addedfile.call(this, mockFile);
|
|
||||||
this.options.thumbnail.call(this, mockFile, v);
|
|
||||||
mockFile.previewElement.classList.add('dz-success');
|
|
||||||
mockFile.previewElement.classList.add('dz-complete');
|
|
||||||
vm.initOnce = false;
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const mockFile = { name: 'name', size: 12345, url: val };
|
|
||||||
this.options.addedfile.call(this, mockFile);
|
|
||||||
this.options.thumbnail.call(this, mockFile, val);
|
|
||||||
mockFile.previewElement.classList.add('dz-success');
|
|
||||||
mockFile.previewElement.classList.add('dz-complete');
|
|
||||||
vm.initOnce = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
accept: (file, done) => {
|
|
||||||
/* 七牛*/
|
|
||||||
// const token = this.$store.getters.token;
|
|
||||||
// getToken(token).then(response => {
|
|
||||||
// file.token = response.data.qiniu_token;
|
|
||||||
// file.key = response.data.qiniu_key;
|
|
||||||
// file.url = response.data.qiniu_url;
|
|
||||||
// done();
|
|
||||||
// })
|
|
||||||
done();
|
|
||||||
},
|
|
||||||
sending: (file, xhr, formData) => {
|
|
||||||
/* 七牛*/
|
|
||||||
console.log(file, xhr, formData)
|
|
||||||
// formData.append('token', file.token);
|
|
||||||
// formData.append('key', file.key);
|
|
||||||
vm.initOnce = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.couldPaste) {
|
|
||||||
document.addEventListener('paste', this.pasteImg)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dropzone.on('success', file => {
|
|
||||||
vm.$emit('dropzone-success', file, vm.dropzone.element)
|
|
||||||
});
|
|
||||||
this.dropzone.on('addedfile', file => {
|
|
||||||
vm.$emit('dropzone-fileAdded', file)
|
|
||||||
});
|
|
||||||
this.dropzone.on('removedfile', file => {
|
|
||||||
vm.$emit('dropzone-removedFile', file)
|
|
||||||
});
|
|
||||||
this.dropzone.on('error', (file, error, xhr) => {
|
|
||||||
vm.$emit('dropzone-error', file, error, xhr)
|
|
||||||
});
|
|
||||||
this.dropzone.on('successmultiple', (file, error, xhr) => {
|
|
||||||
vm.$emit('dropzone-successmultiple', file, error, xhr)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
removeAllFiles() {
|
|
||||||
this.dropzone.removeAllFiles(true)
|
|
||||||
},
|
|
||||||
processQueue() {
|
|
||||||
this.dropzone.processQueue()
|
|
||||||
},
|
|
||||||
pasteImg(event) {
|
|
||||||
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
|
||||||
if (items[0].kind === 'file') {
|
|
||||||
this.dropzone.addFile(items[0].getAsFile())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initImages(val) {
|
|
||||||
if (!val) return;
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
val.map((v, i) => {
|
|
||||||
const mockFile = { name: 'name' + i, size: 12345, url: v };
|
|
||||||
this.dropzone.options.addedfile.call(this.dropzone, mockFile);
|
|
||||||
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v);
|
|
||||||
mockFile.previewElement.classList.add('dz-success');
|
|
||||||
mockFile.previewElement.classList.add('dz-complete');
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const mockFile = { name: 'name', size: 12345, url: val };
|
|
||||||
this.dropzone.options.addedfile.call(this.dropzone, mockFile);
|
|
||||||
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val);
|
|
||||||
mockFile.previewElement.classList.add('dz-success');
|
|
||||||
mockFile.previewElement.classList.add('dz-complete');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
document.removeEventListener('paste', this.pasteImg);
|
|
||||||
this.dropzone.destroy();
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
defaultImg(val) {
|
|
||||||
if (val.length === 0) {
|
|
||||||
this.initOnce = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.initOnce) return;
|
|
||||||
this.initImages(val);
|
|
||||||
this.initOnce = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -164,7 +30,8 @@
|
||||||
default: '上传图片'
|
default: '上传图片'
|
||||||
},
|
},
|
||||||
acceptedFiles: {
|
acceptedFiles: {
|
||||||
type: String
|
type: String,
|
||||||
|
default: ''
|
||||||
},
|
},
|
||||||
thumbnailHeight: {
|
thumbnailHeight: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -195,11 +62,145 @@
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
defaultImg: {
|
defaultImg: {
|
||||||
default: false
|
default: '',
|
||||||
|
type: [String, Array]
|
||||||
},
|
},
|
||||||
couldPaste: {
|
couldPaste: {
|
||||||
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dropzone: '',
|
||||||
|
initOnce: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
defaultImg(val) {
|
||||||
|
if (val.length === 0) {
|
||||||
|
this.initOnce = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.initOnce) return
|
||||||
|
this.initImages(val)
|
||||||
|
this.initOnce = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const element = document.getElementById(this.id)
|
||||||
|
const vm = this
|
||||||
|
this.dropzone = new Dropzone(element, {
|
||||||
|
clickable: this.clickable,
|
||||||
|
thumbnailWidth: this.thumbnailWidth,
|
||||||
|
thumbnailHeight: this.thumbnailHeight,
|
||||||
|
maxFiles: this.maxFiles,
|
||||||
|
maxFilesize: this.maxFilesize,
|
||||||
|
dictRemoveFile: 'Remove',
|
||||||
|
addRemoveLinks: this.showRemoveLink,
|
||||||
|
acceptedFiles: this.acceptedFiles,
|
||||||
|
autoProcessQueue: this.autoProcessQueue,
|
||||||
|
dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload',
|
||||||
|
dictMaxFilesExceeded: '只能一个图',
|
||||||
|
previewTemplate: '<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
|
||||||
|
init() {
|
||||||
|
const val = vm.defaultImg
|
||||||
|
if (!val) return
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
if (val.length === 0) return
|
||||||
|
val.map((v, i) => {
|
||||||
|
const mockFile = { name: 'name' + i, size: 12345, url: v }
|
||||||
|
this.options.addedfile.call(this, mockFile)
|
||||||
|
this.options.thumbnail.call(this, mockFile, v)
|
||||||
|
mockFile.previewElement.classList.add('dz-success')
|
||||||
|
mockFile.previewElement.classList.add('dz-complete')
|
||||||
|
vm.initOnce = false
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const mockFile = { name: 'name', size: 12345, url: val }
|
||||||
|
this.options.addedfile.call(this, mockFile)
|
||||||
|
this.options.thumbnail.call(this, mockFile, val)
|
||||||
|
mockFile.previewElement.classList.add('dz-success')
|
||||||
|
mockFile.previewElement.classList.add('dz-complete')
|
||||||
|
vm.initOnce = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
accept: (file, done) => {
|
||||||
|
/* 七牛*/
|
||||||
|
// const token = this.$store.getters.token;
|
||||||
|
// getToken(token).then(response => {
|
||||||
|
// file.token = response.data.qiniu_token;
|
||||||
|
// file.key = response.data.qiniu_key;
|
||||||
|
// file.url = response.data.qiniu_url;
|
||||||
|
// done();
|
||||||
|
// })
|
||||||
|
done()
|
||||||
|
},
|
||||||
|
sending: (file, xhr, formData) => {
|
||||||
|
// formData.append('token', file.token);
|
||||||
|
// formData.append('key', file.key);
|
||||||
|
vm.initOnce = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.couldPaste) {
|
||||||
|
document.addEventListener('paste', this.pasteImg)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dropzone.on('success', file => {
|
||||||
|
vm.$emit('dropzone-success', file, vm.dropzone.element)
|
||||||
|
})
|
||||||
|
this.dropzone.on('addedfile', file => {
|
||||||
|
vm.$emit('dropzone-fileAdded', file)
|
||||||
|
})
|
||||||
|
this.dropzone.on('removedfile', file => {
|
||||||
|
vm.$emit('dropzone-removedFile', file)
|
||||||
|
})
|
||||||
|
this.dropzone.on('error', (file, error, xhr) => {
|
||||||
|
vm.$emit('dropzone-error', file, error, xhr)
|
||||||
|
})
|
||||||
|
this.dropzone.on('successmultiple', (file, error, xhr) => {
|
||||||
|
vm.$emit('dropzone-successmultiple', file, error, xhr)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
document.removeEventListener('paste', this.pasteImg)
|
||||||
|
this.dropzone.destroy()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
removeAllFiles() {
|
||||||
|
this.dropzone.removeAllFiles(true)
|
||||||
|
},
|
||||||
|
processQueue() {
|
||||||
|
this.dropzone.processQueue()
|
||||||
|
},
|
||||||
|
pasteImg(event) {
|
||||||
|
const items = (event.clipboardData || event.originalEvent.clipboardData).items
|
||||||
|
if (items[0].kind === 'file') {
|
||||||
|
this.dropzone.addFile(items[0].getAsFile())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initImages(val) {
|
||||||
|
if (!val) return
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
val.map((v, i) => {
|
||||||
|
const mockFile = { name: 'name' + i, size: 12345, url: v }
|
||||||
|
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
|
||||||
|
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v)
|
||||||
|
mockFile.previewElement.classList.add('dz-success')
|
||||||
|
mockFile.previewElement.classList.add('dz-complete')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const mockFile = { name: 'name', size: 12345, url: val }
|
||||||
|
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
|
||||||
|
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val)
|
||||||
|
mockFile.previewElement.classList.add('dz-success')
|
||||||
|
mockFile.previewElement.classList.add('dz-complete')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -236,7 +237,7 @@
|
||||||
|
|
||||||
.dropzone .dz-preview:hover .dz-image img {
|
.dropzone .dz-preview:hover .dz-image img {
|
||||||
transform: none;
|
transform: none;
|
||||||
-webkit-filter: none;
|
filter: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<el-badge :is-dot="true" style="line-height: 30px;" @click.native="dialogTableVisible=true">
|
|
||||||
<el-button size="small" type="primary">
|
|
||||||
<svg t="1492682037685" class="bug-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1863"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
|
|
||||||
<path d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
|
|
||||||
p-id="1864"></path>
|
|
||||||
</svg>
|
|
||||||
</el-button>
|
|
||||||
</el-badge>
|
|
||||||
<el-dialog title="bug日志" :visible.sync="dialogTableVisible">
|
|
||||||
<el-table :data="logsList">
|
|
||||||
<el-table-column label="message">
|
|
||||||
<template scope="scope">
|
|
||||||
<div>msg:{{ scope.row.err.message }}</div>
|
|
||||||
<br/>
|
|
||||||
<div>url: {{scope.row.url}}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="stack">
|
|
||||||
<template scope="scope">
|
|
||||||
{{ scope.row.err.stack}}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
</el-table>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'errLog',
|
|
||||||
props: {
|
|
||||||
logsList: {
|
|
||||||
type: Array
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogTableVisible: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.bug-svg {
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
vertical-align: -0.15em;
|
|
||||||
fill: currentColor;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
</style>
|
|