├── .babelrc ├── .editorconfig ├── .eslintignore ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── build ├── build.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── composer.json ├── config ├── dev.env.js ├── index.js ├── prod.env.js └── test.env.js ├── doc ├── img │ ├── basecharts.jpg │ ├── container-layout.jpg │ ├── custom1.jpg │ ├── custom2.jpg │ ├── custom3.jpg │ ├── custom4.jpg │ ├── form.jpg │ ├── login.jpg │ ├── logo.png │ └── main.jpg ├── semantic-ui-custom.rar └── site.variables ├── index.html ├── package.json ├── src ├── App.vue ├── assets │ └── img │ │ ├── avatar_small.jpg │ │ ├── logo.png │ │ └── logo2.png ├── components │ ├── Breadcrumb.vue │ ├── Form.vue │ ├── Home.vue │ ├── List.vue │ ├── ListForm.vue │ ├── Login.vue │ ├── Page1.vue │ ├── Page2.vue │ ├── Pagination.vue │ ├── charts │ │ ├── Bar.vue │ │ ├── BaseChart.vue │ │ ├── Bubble.vue │ │ ├── Meter.vue │ │ └── Polar.vue │ └── menu │ │ ├── Menu.vue │ │ └── menu.conf.js ├── filters.js ├── http │ ├── host.config.js │ └── http.interceptors.js ├── main.js ├── router │ ├── alias.js │ └── routes.js ├── services │ └── auth-service.js └── vuex │ ├── actions.js │ ├── middlewares.js │ ├── modules │ ├── auth.js │ ├── menu.js │ └── progress.js │ ├── store.js │ └── types.js └── test ├── e2e ├── custom-assertions │ └── elementCount.js ├── nightwatch.conf.js ├── runner.js └── specs │ └── test.js └── unit ├── .eslintrc ├── index.js ├── karma.conf.js └── specs └── Pagination.spec.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-runtime"], 4 | "comments": false 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | selenium-debug.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "5" 5 | 6 | before_script: 7 | - "export DISPLAY=:0.0" 8 | - "sh -e /etc/init.d/xvfb start" 9 | - sleep 3 10 | 11 | before_install: 12 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :0 -ac -screen 0 1280x1024x16" 13 | 14 | after_success: 15 | - npm i coveralls 16 | - cat ./coverage/*/lcov.info | coveralls 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/rootsli/vueadmin/blob/master/doc/img/logo.png) 2 | 3 | vue-admin - A background manager scaffolding base Vue.js 4 | ======================================================== 5 | 6 | [![Packagist](https://img.shields.io/badge/packagist-1.1.2-blue.svg)](https://packagist.org/packages/vueadmin/vue-admin) 7 | [![Vuejs](https://img.shields.io/badge/%20Powered%20by%20-%20Vuejs%201.x.x%20-green.svg?style=flat)](http://cn.vuejs.org/) 8 | 9 | A Vue.js background manager scaffolding base vue.js(1.0.x) + Semantic UI + vuex + vue-router + vue-resource(whatwg-fetch) + vue-validator + vue-loader + webpack 10 | 11 | 使用Vue.js作为基础框架,Semantic UI作为UI层,实现了一个后台管理系统的基础框架。可以基于此框架实现功能复杂的后台管理系统。 12 | 13 | [点此查看运行效果](http://vueadmin.duapp.com)(登录名:admin,密码:admin) 14 | 15 | ※ 已基于 vue2 + webpack2 + elementUI 实现了一套全新的后台管理框架,具体请移步 [https://github.com/rootsli/vue2admin] (https://github.com/rootsli/vue2admin)查看 16 | 17 | 18 | ## 主要依赖组件 19 | * vue.js ^1.0.21 20 | * semantic-ui-css ^2.2.2 21 | 由于semantic-ui经过了定制,因此建议将下文“关于semanticUI css的本地化定制”章节附件semantic-ui-custom.rar直接解压到node_modules\semantic-ui-css目录下即可(需先运行npm install)。否则项目跑起来后,界面和截图不一致。 22 | * 百度 echarts3 23 | 24 | ## Build Setup 25 | 26 | ``` bash 27 | # install dependencies 28 | npm install 29 | 30 | # serve with hot reload at localhost:8080 31 | npm run dev 32 | 33 | # build for production with minification 34 | npm run build 35 | 36 | # run unit tests 37 | npm run unit 38 | 39 | # run e2e tests 40 | npm run e2e 41 | 42 | # run all tests 43 | npm test 44 | ``` 45 | 46 | ## 关于semanticUI css的本地化定制 47 | * 本项目虽然使用的是semantic-ui-css,但是由于Semantic UI 默认使用的是谷歌提供的字体,并且是直接使用了谷歌的官方链接。因此建议对css进行本地化定制,使用定制后编译生成的文件替换semantic-ui-css中的文件。 48 | 具体定制方法请参考Semantic UI官方文档,主要变更如下: 49 | * 默认字体改为使用微软雅黑 50 | 51 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/custom1.jpg) 52 | 53 | * 关闭google字体动态链接 54 | 55 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/custom2.jpg) 56 | 57 | * 修改控件样式的默认颜色 58 | 59 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/custom3.jpg) 60 | 61 | * 修改默认背景色 62 | 63 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/custom4.jpg) 64 | 65 | ### 附:[semantic-ui-custom.rar](https://github.com/rootsli/vueadmin/blob/master/doc/semantic-ui-custom.rar)(可通过右键另存为保存)。另,定制文件请见文件[site.variables](https://github.com/rootsli/vueadmin/blob/master/doc/site.variables) 66 | ### 如不想自己定制,也可以直接解压semantic-ui-custom.rar内容覆盖掉node_modules\semantic-ui-css目录下内容即可(需先运行npm install)。 67 | ## 菜单右侧主页面布局说明 68 | * 典型的布局结构(推荐布局) 69 | ```html 70 | ... 71 | 72 |
73 |

标题

74 |
75 |
76 | 77 |
78 |
79 | 80 |
81 |
82 |
83 | ... 84 | ``` 85 | 86 | * 界面说明 87 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/container-layout.jpg) 88 | 89 | ## Change Log 90 | - 20160820 91 | - 新增表单示例 92 | - 20160812 93 | - list示例新增项目的新增,编辑case 94 | - 20160811 95 | - 更新README.md 96 | - 20160810 97 | - 新增翻页组件 98 | - 新增表格示例 99 | - 20160808 100 | - 菜单支持折叠与隐藏 101 | - 20160805 102 | - 菜单隐藏使用动画 103 | - 页面加载支持进度条 104 | - 20161012 105 | - 整合vue-echarts 106 | - 整合百度echarts3 107 | - 实现基本图形示例 108 | - 页面F5刷新时,菜单展开错误问题修复 109 | - 20161014 110 | - 生产打包js文件生成6位数的hash 111 | - 添加运行效果 112 | 113 | ## To Do List 114 | - 报表实例:地图示例 115 | 116 | ## UI截图 117 | - 登录界面 118 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/login.jpg) 119 | 120 | - 表格示例 121 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/main.jpg) 122 | 123 | - 表单 124 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/form.jpg) 125 | 126 | - 基本图形 127 | ![image](https://github.com/rootsli/vueadmin/blob/master/doc/img/basecharts.jpg) 128 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('shelljs/global') 3 | env.NODE_ENV = 'production' 4 | 5 | var path = require('path') 6 | var config = require('../config') 7 | var ora = require('ora') 8 | var webpack = require('webpack') 9 | var webpackConfig = require('./webpack.prod.conf') 10 | 11 | console.log( 12 | ' Tip:\n' + 13 | ' Built files are meant to be served over an HTTP server.\n' + 14 | ' Opening index.html over file:// won\'t work.\n' 15 | ) 16 | 17 | var spinner = ora('building for production...') 18 | spinner.start() 19 | 20 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory) 21 | rm('-rf', assetsPath) 22 | mkdir('-p', assetsPath) 23 | cp('-R', 'static/', assetsPath) 24 | 25 | webpack(webpackConfig, function (err, stats) { 26 | spinner.stop() 27 | if (err) throw err 28 | process.stdout.write(stats.toString({ 29 | colors: true, 30 | modules: false, 31 | children: false, 32 | chunks: false, 33 | chunkModules: false 34 | }) + '\n') 35 | }) 36 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var express = require('express') 3 | var webpack = require('webpack') 4 | var config = require('../config') 5 | var proxyMiddleware = require('http-proxy-middleware') 6 | var webpackConfig = process.env.NODE_ENV === 'testing' 7 | ? require('./webpack.prod.conf') 8 | : require('./webpack.dev.conf') 9 | 10 | // default port where dev server listens for incoming traffic 11 | var port = process.env.PORT || config.dev.port 12 | // Define HTTP proxies to your custom API backend 13 | // https://github.com/chimurai/http-proxy-middleware 14 | var proxyTable = config.dev.proxyTable 15 | 16 | var app = express() 17 | var compiler = webpack(webpackConfig) 18 | 19 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 20 | publicPath: webpackConfig.output.publicPath, 21 | stats: { 22 | colors: true, 23 | chunks: false 24 | } 25 | }) 26 | 27 | var hotMiddleware = require('webpack-hot-middleware')(compiler) 28 | // force page reload when html-webpack-plugin template changes 29 | compiler.plugin('compilation', function (compilation) { 30 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 31 | hotMiddleware.publish({ action: 'reload' }) 32 | cb() 33 | }) 34 | }) 35 | 36 | // proxy api requests 37 | Object.keys(proxyTable).forEach(function (context) { 38 | var options = proxyTable[context] 39 | if (typeof options === 'string') { 40 | options = { target: options } 41 | } 42 | app.use(proxyMiddleware(context, options)) 43 | }) 44 | 45 | // handle fallback for HTML5 history API 46 | app.use(require('connect-history-api-fallback')()) 47 | 48 | // serve webpack bundle output 49 | app.use(devMiddleware) 50 | 51 | // enable hot-reload and state-preserving 52 | // compilation error display 53 | app.use(hotMiddleware) 54 | 55 | // serve pure static assets 56 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 57 | app.use(staticPath, express.static('./static')) 58 | 59 | module.exports = app.listen(port, function (err) { 60 | if (err) { 61 | console.log(err) 62 | return 63 | } 64 | console.log('Listening at http://localhost:' + port + '\n') 65 | }) 66 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | return path.posix.join(config.build.assetsSubDirectory, _path) 7 | } 8 | 9 | exports.cssLoaders = function (options) { 10 | options = options || {} 11 | // generate loader string to be used with extract text plugin 12 | function generateLoaders (loaders) { 13 | var sourceLoader = loaders.map(function (loader) { 14 | var extraParamChar 15 | if (/\?/.test(loader)) { 16 | loader = loader.replace(/\?/, '-loader?') 17 | extraParamChar = '&' 18 | } else { 19 | loader = loader + '-loader' 20 | extraParamChar = '?' 21 | } 22 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 23 | }).join('!') 24 | 25 | if (options.extract) { 26 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) 27 | } else { 28 | return ['vue-style-loader', sourceLoader].join('!') 29 | } 30 | } 31 | 32 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html 33 | return { 34 | css: generateLoaders(['css']), 35 | postcss: generateLoaders(['css']), 36 | less: generateLoaders(['css', 'less']), 37 | sass: generateLoaders(['css', 'sass?indentedSyntax']), 38 | scss: generateLoaders(['css', 'sass']), 39 | stylus: generateLoaders(['css', 'stylus']), 40 | styl: generateLoaders(['css', 'stylus']) 41 | } 42 | } 43 | 44 | // Generate loaders for standalone style files (outside of .vue) 45 | exports.styleLoaders = function (options) { 46 | var output = [] 47 | var loaders = exports.cssLoaders(options) 48 | for (var extension in loaders) { 49 | var loader = loaders[extension] 50 | output.push({ 51 | test: new RegExp('\\.' + extension + '$'), 52 | loader: loader 53 | }) 54 | } 55 | return output 56 | } 57 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | var path = require('path') 3 | var config = require('../config') 4 | var utils = require('./utils') 5 | var projectRoot = path.resolve(__dirname, '../') 6 | 7 | module.exports = { 8 | entry: { 9 | app: './src/main.js' 10 | }, 11 | output: { 12 | path: config.build.assetsRoot, 13 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, 14 | filename: '[name].js' 15 | }, 16 | resolve: { 17 | extensions: ['', '.js', '.vue'], 18 | fallback: [path.join(__dirname, '../node_modules')], 19 | alias: { 20 | 'src': path.resolve(__dirname, '../src'), 21 | 'assets': path.resolve(__dirname, '../src/assets'), 22 | 'components': path.resolve(__dirname, '../src/components'), 23 | // 'jquery': "jquery/dist/jquery.min", 24 | 'semantic': path.resolve(__dirname, '../node_modules/semantic-ui-css/semantic.min.js') 25 | } 26 | }, 27 | resolveLoader: { 28 | fallback: [path.join(__dirname, '../node_modules')] 29 | }, 30 | module: { 31 | loaders: [ 32 | { 33 | test: /\.vue$/, 34 | loader: 'vue' 35 | }, 36 | { 37 | test: /\.js$/, 38 | loader: 'babel', 39 | include: projectRoot, 40 | exclude: /node_modules/ 41 | }, 42 | { 43 | test: /\.json$/, 44 | loader: 'json' 45 | }, 46 | { 47 | test: /\.html$/, 48 | loader: 'vue-html' 49 | }, 50 | { 51 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 52 | loader: 'url', 53 | query: { 54 | limit: 10000, 55 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 56 | } 57 | }, 58 | { 59 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 60 | loader: 'url', 61 | query: { 62 | limit: 10000, 63 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 64 | } 65 | } 66 | ] 67 | }, 68 | plugins:[ 69 | new webpack.ProvidePlugin({ 70 | $: "jquery", 71 | jQuery: "jquery", 72 | "window.jQuery": "jquery", 73 | semantic: 'semantic-ui-css', 74 | Semantic: 'semantic-ui-css', 75 | 'semantic-ui': 'semantic-ui-css' 76 | }) 77 | ], 78 | vue: { 79 | loaders: utils.cssLoaders() 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | var webpack = require('webpack') 3 | var merge = require('webpack-merge') 4 | var utils = require('./utils') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | 8 | // add hot-reload related code to entry chunks 9 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 10 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 11 | }) 12 | 13 | module.exports = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 16 | }, 17 | // eval-source-map is faster for development 18 | devtool: '#eval-source-map', 19 | plugins: [ 20 | new webpack.DefinePlugin({ 21 | 'process.env': config.dev.env 22 | }), 23 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 24 | new webpack.optimize.OccurenceOrderPlugin(), 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }) 33 | ] 34 | }) 35 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = process.env.NODE_ENV === 'testing' 10 | ? require('../config/test.env') 11 | : config.build.env 12 | 13 | var webpackConfig = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) 16 | }, 17 | devtool: config.build.productionSourceMap ? '#source-map' : false, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: utils.assetsPath('js/[name].[chunkhash:6].js'), 21 | chunkFilename: utils.assetsPath('js/[id].[chunkhash:6].js') 22 | }, 23 | vue: { 24 | loaders: utils.cssLoaders({ 25 | sourceMap: config.build.productionSourceMap, 26 | extract: true 27 | }) 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }), 34 | new webpack.optimize.UglifyJsPlugin({ 35 | compress: { 36 | warnings: false 37 | } 38 | }), 39 | new webpack.optimize.OccurenceOrderPlugin(), 40 | // extract css into its own file 41 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), 42 | // generate dist index.html with correct asset hash for caching. 43 | // you can customize output by editing /index.html 44 | // see https://github.com/ampedandwired/html-webpack-plugin 45 | new HtmlWebpackPlugin({ 46 | filename: process.env.NODE_ENV === 'testing' 47 | ? 'index.html' 48 | : config.build.index, 49 | template: 'index.html', 50 | inject: true, 51 | minify: { 52 | removeComments: true, 53 | collapseWhitespace: true, 54 | removeAttributeQuotes: true 55 | // more options: 56 | // https://github.com/kangax/html-minifier#options-quick-reference 57 | }, 58 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 59 | chunksSortMode: 'dependency' 60 | }), 61 | // split vendor js into its own file 62 | new webpack.optimize.CommonsChunkPlugin({ 63 | name: 'vendor', 64 | minChunks: function (module, count) { 65 | // any required modules inside node_modules are extracted to vendor 66 | return ( 67 | module.resource && 68 | /\.js$/.test(module.resource) && 69 | module.resource.indexOf( 70 | path.join(__dirname, '../node_modules') 71 | ) === 0 72 | ) 73 | } 74 | }), 75 | // extract webpack runtime and module manifest to its own file in order to 76 | // prevent vendor hash from being updated whenever app bundle is updated 77 | new webpack.optimize.CommonsChunkPlugin({ 78 | name: 'manifest', 79 | chunks: ['vendor'] 80 | }) 81 | ] 82 | }) 83 | 84 | if (config.build.productionGzip) { 85 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 86 | 87 | webpackConfig.plugins.push( 88 | new CompressionWebpackPlugin({ 89 | asset: '[path].gz[query]', 90 | algorithm: 'gzip', 91 | test: new RegExp( 92 | '\\.(' + 93 | config.build.productionGzipExtensions.join('|') + 94 | ')$' 95 | ), 96 | threshold: 10240, 97 | minRatio: 0.8 98 | }) 99 | ) 100 | } 101 | 102 | module.exports = webpackConfig 103 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vueadmin/vue-admin", 3 | "description": "A background manager scaffolding base Vue.js", 4 | "keywords": ["vue demo", "semantic ui", "vuex demo", "scaffolding base Vue.js"], 5 | "homepage": "https://github.com/rootsli/vueadmin", 6 | "type": "project", 7 | "license": "BSD-3-Clause", 8 | "minimum-stability": "stable", 9 | "require": { 10 | "babel-runtime": "^6.0.0", 11 | "jquery": "^2.2.3", 12 | "react-cookie": "^0.4.7", 13 | "semantic-ui-css": "^2.2.2", 14 | "vue": "^1.0.21", 15 | "vue-resource": "^0.9.3", 16 | "vue-router": "^0.7.13", 17 | "vue-validator": "^2.1.4", 18 | "vuex": "^0.8.2", 19 | "vuex-router-sync": "^1.0.1" 20 | }, 21 | "require-dev": { 22 | "babel-core": "^6.0.0", 23 | "babel-loader": "^6.0.0", 24 | "babel-plugin-transform-runtime": "^6.0.0", 25 | "babel-preset-es2015": "^6.0.0", 26 | "babel-preset-stage-2": "^6.0.0", 27 | "connect-history-api-fallback": "^1.1.0", 28 | "css-loader": "^0.23.0", 29 | "eventsource-polyfill": "^0.9.6", 30 | "express": "^4.13.3", 31 | "extract-text-webpack-plugin": "^1.0.1", 32 | "file-loader": "^0.8.4", 33 | "function-bind": "^1.0.2", 34 | "html-webpack-plugin": "^2.8.1", 35 | "http-proxy-middleware": "^0.12.0", 36 | "json-loader": "^0.5.4", 37 | "karma": "^0.13.15", 38 | "karma-coverage": "^0.5.5", 39 | "karma-mocha": "^0.2.2", 40 | "karma-phantomjs-launcher": "^1.0.0", 41 | "karma-sinon-chai": "^1.2.0", 42 | "karma-sourcemap-loader": "^0.3.7", 43 | "karma-spec-reporter": "0.0.24", 44 | "karma-webpack": "^1.7.0", 45 | "lolex": "^1.4.0", 46 | "mocha": "^2.4.5", 47 | "chai": "^3.5.0", 48 | "sinon": "^1.17.3", 49 | "sinon-chai": "^2.8.0", 50 | "inject-loader": "^2.0.1", 51 | "isparta-loader": "^2.0.0", 52 | "phantomjs-prebuilt": "^2.1.3", 53 | "chromedriver": "^2.21.2", 54 | "cross-spawn": "^2.1.5", 55 | "nightwatch": "^0.8.18", 56 | "selenium-server": "2.53.0", 57 | "ora": "^0.2.0", 58 | "shelljs": "^0.6.0", 59 | "url-loader": "^0.5.7", 60 | "vue-hot-reload-api": "^1.2.0", 61 | "vue-html-loader": "^1.0.0", 62 | "vue-loader": "^8.3.0", 63 | "vue-style-loader": "^1.0.0", 64 | "webpack": "^1.12.2", 65 | "webpack-dev-middleware": "^1.4.0", 66 | "webpack-hot-middleware": "^2.6.0", 67 | "webpack-merge": "^0.8.3" 68 | }, 69 | "config": { 70 | "process-timeout": 1800 71 | }, 72 | "extra": { 73 | "asset-installer-paths": { 74 | "npm-asset-library": "vendor/npm", 75 | "bower-asset-library": "vendor/bower" 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'] 18 | }, 19 | dev: { 20 | env: require('./dev.env'), 21 | port: 8080, 22 | assetsSubDirectory: 'static', 23 | assetsPublicPath: '/', 24 | proxyTable: {}, 25 | // CSS Sourcemaps off by default because relative paths are "buggy" 26 | // with this option, according to the CSS-Loader README 27 | // (https://github.com/webpack/css-loader#sourcemaps) 28 | // In our experience, they generally work as expected, 29 | // just be aware of this issue when enabling this option. 30 | cssSourceMap: false, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /doc/img/basecharts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/basecharts.jpg -------------------------------------------------------------------------------- /doc/img/container-layout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/container-layout.jpg -------------------------------------------------------------------------------- /doc/img/custom1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/custom1.jpg -------------------------------------------------------------------------------- /doc/img/custom2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/custom2.jpg -------------------------------------------------------------------------------- /doc/img/custom3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/custom3.jpg -------------------------------------------------------------------------------- /doc/img/custom4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/custom4.jpg -------------------------------------------------------------------------------- /doc/img/form.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/form.jpg -------------------------------------------------------------------------------- /doc/img/login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/login.jpg -------------------------------------------------------------------------------- /doc/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/logo.png -------------------------------------------------------------------------------- /doc/img/main.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/img/main.jpg -------------------------------------------------------------------------------- /doc/semantic-ui-custom.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/doc/semantic-ui-custom.rar -------------------------------------------------------------------------------- /doc/site.variables: -------------------------------------------------------------------------------- 1 | /******************************* 2 | Site Settings 3 | *******************************/ 4 | 5 | /*------------------- 6 | Fonts 7 | --------------------*/ 8 | 9 | @fontName : 'Microsoft YaHei'; 10 | @fontSmoothing : antialiased; 11 | 12 | @headerFont : @fontName, STXihei, sans-serif; 13 | @pageFont : @fontName, STXihei, sans-serif; 14 | 15 | @googleFontName : @fontName; 16 | @importGoogleFonts : false; 17 | @googleFontSizes : '400,700,400italic,700italic'; 18 | @googleSubset : 'latin'; 19 | 20 | @googleProtocol : 'https://'; 21 | @googleFontRequest : '@{googleFontName}:@{googleFontSizes}&subset=@{googleSubset}'; 22 | 23 | /*------------------- 24 | Base Sizes 25 | --------------------*/ 26 | 27 | /* This is the single variable that controls them all */ 28 | @emSize : 14px; 29 | 30 | /* The size of page text */ 31 | @fontSize : 14px; 32 | 33 | 34 | /*------------------- 35 | Border Radius 36 | --------------------*/ 37 | 38 | /* See Power-user section below 39 | for explanation of @px variables 40 | */ 41 | @relativeBorderRadius: @relative4px; 42 | @absoluteBorderRadius: @4px; 43 | 44 | @defaultBorderRadius: @absoluteBorderRadius; 45 | 46 | /*------------------- 47 | Brand Colors 48 | --------------------*/ 49 | 50 | @primaryColor : @teal; 51 | @secondaryColor : @blue; 52 | 53 | @lightPrimaryColor : @lightTeal; 54 | @lightSecondaryColor : @lightBlue; 55 | 56 | /*-------------- 57 | Page Heading 58 | ---------------*/ 59 | 60 | @headerFontWeight : bold; 61 | @headerLineHeight : 1.2857em; 62 | 63 | @h1 : 2rem; 64 | @h2 : 1.714rem; 65 | @h3 : 1.28rem; 66 | @h4 : 1.071rem; 67 | @h5 : 1rem; 68 | 69 | /*-------------- 70 | Form Input 71 | ---------------*/ 72 | 73 | /* This adjusts the default form input across all elements */ 74 | @inputBackground : @white; 75 | @inputVerticalPadding : @relative11px; 76 | @inputHorizontalPadding : @relative14px; 77 | @inputPadding : @inputVerticalPadding @inputHorizontalPadding; 78 | 79 | /* Input Text Color */ 80 | @inputColor: @textColor; 81 | @inputPlaceholderColor: lighten(@inputColor, 75); 82 | @inputPlaceholderFocusColor: lighten(@inputColor, 45); 83 | 84 | /* Line Height Default For Inputs in Browser */ 85 | @inputLineHeight: 1.2142em; 86 | 87 | /*------------------- 88 | Focused Input 89 | --------------------*/ 90 | 91 | /* Used on inputs, textarea etc */ 92 | @focusedFormBorderColor: #85B7D9; 93 | 94 | /* Used on dropdowns, other larger blocks */ 95 | @focusedFormMutedBorderColor: #96C8DA; 96 | 97 | /*------------------- 98 | Sizes 99 | --------------------*/ 100 | 101 | /* 102 | Sizes are all expressed in terms of 14px/em (default em) 103 | This ensures these "ratios" remain constant despite changes in EM 104 | */ 105 | 106 | @miniSize : (11 / 14); 107 | @tinySize : (12 / 14); 108 | @smallSize : (13 / 14); 109 | @mediumSize : (14 / 14); 110 | @largeSize : (16 / 14); 111 | @bigSize : (18 / 14); 112 | @hugeSize : (20 / 14); 113 | @massiveSize : (24 / 14); 114 | 115 | 116 | /*------------------- 117 | Page 118 | --------------------*/ 119 | 120 | @pageBackground : #e7eaeb; 121 | @pageOverflowX : auto; 122 | 123 | @lineHeight : 1.4285em; 124 | @textColor : #606e75; 125 | 126 | /*------------------- 127 | Paragraph 128 | --------------------*/ 129 | 130 | @paragraphMargin : 0em 0em 1em; 131 | @paragraphLineHeight : @lineHeight; 132 | 133 | /*------------------- 134 | Links 135 | --------------------*/ 136 | 137 | @linkColor : #4183C4; 138 | @linkUnderline : none; 139 | @linkHoverColor : darken(saturate(@linkColor, 20), 15, relative); 140 | @linkHoverUnderline : @linkUnderline; 141 | 142 | /*------------------- 143 | Highlighted Text 144 | --------------------*/ 145 | 146 | @highlightBackground : #CCE2FF; 147 | @highlightColor : @textColor; 148 | 149 | @inputHighlightBackground : rgba(100, 100, 100, 0.4); 150 | @inputHighlightColor : @textColor; 151 | 152 | 153 | /*------------------- 154 | Loader 155 | --------------------*/ 156 | 157 | @loaderSize : @relativeBig; 158 | @loaderSpeed : 0.6s; 159 | @loaderLineWidth : 0.2em; 160 | @loaderFillColor : rgba(0, 0, 0, 0.1); 161 | @loaderLineColor : @grey; 162 | 163 | @invertedLoaderFillColor : rgba(255, 255, 255, 0.15); 164 | @invertedLoaderLineColor : @white; 165 | 166 | /*------------------- 167 | Grid 168 | --------------------*/ 169 | 170 | @columnCount: 16; 171 | 172 | /*------------------- 173 | Transitions 174 | --------------------*/ 175 | 176 | @defaultDuration : 0.1s; 177 | @defaultEasing : ease; 178 | 179 | /*------------------- 180 | Breakpoints 181 | --------------------*/ 182 | 183 | @mobileBreakpoint : 320px; 184 | @tabletBreakpoint : 768px; 185 | @computerBreakpoint : 992px; 186 | @largeMonitorBreakpoint : 1200px; 187 | @widescreenMonitorBreakpoint : 1920px; 188 | 189 | /*------------------- 190 | Site Colors 191 | --------------------*/ 192 | 193 | /*--- Colors ---*/ 194 | @red : #DB2828; 195 | @orange : #F2711C; 196 | @yellow : #FBBD08; 197 | @olive : #B5CC18; 198 | @green : #21BA45; 199 | @teal : #00B5AD; 200 | @blue : #2185D0; 201 | @violet : #6435C9; 202 | @purple : #A333C8; 203 | @pink : #E03997; 204 | @brown : #A5673F; 205 | @grey : #767676; 206 | @black : #1B1C1D; 207 | 208 | /*--- Light Colors ---*/ 209 | @lightRed : #FF695E; 210 | @lightOrange : #FF851B; 211 | @lightYellow : #FFE21F; 212 | @lightOlive : #D9E778; 213 | @lightGreen : #2ECC40; 214 | @lightTeal : #6DFFFF; 215 | @lightBlue : #54C8FF; 216 | @lightViolet : #A291FB; 217 | @lightPurple : #DC73FF; 218 | @lightPink : #FF8EDF; 219 | @lightBrown : #D67C1C; 220 | @lightGrey : #DCDDDE; 221 | @lightBlack : #545454; 222 | 223 | /*--- Neutrals ---*/ 224 | @fullBlack : #000000; 225 | @offWhite : #F9FAFB; 226 | @darkWhite : #F3F4F5; 227 | @midWhite : #DCDDDE; 228 | @white : #FFFFFF; 229 | 230 | /*--- Colored Backgrounds ---*/ 231 | @redBackground : #FFE8E6; 232 | @orangeBackground : #FFEDDE; 233 | @yellowBackground : #FFF8DB; 234 | @oliveBackground : #FBFDEF; 235 | @greenBackground : #E5F9E7; 236 | @tealBackground : #E1F7F7; 237 | @blueBackground : #DFF0FF; 238 | @violetBackground : #EAE7FF; 239 | @purpleBackground : #F6E7FF; 240 | @pinkBackground : #FFE3FB; 241 | @brownBackground : #F1E2D3; 242 | 243 | /*--- Colored Headers ---*/ 244 | @redHeaderColor : darken(@redTextColor, 5); 245 | @oliveHeaderColor : darken(@oliveTextColor, 5); 246 | @greenHeaderColor : darken(@greenTextColor, 5); 247 | @yellowHeaderColor : darken(@yellowTextColor, 5); 248 | @blueHeaderColor : darken(@blueTextColor, 5); 249 | @tealHeaderColor : darken(@tealTextColor, 5); 250 | @pinkHeaderColor : darken(@pinkTextColor, 5); 251 | @violetHeaderColor : darken(@violetTextColor, 5); 252 | @purpleHeaderColor : darken(@purpleTextColor, 5); 253 | @orangeHeaderColor : darken(@orangeTextColor, 5); 254 | @brownHeaderColor : darken(@brownTextColor, 5); 255 | 256 | /*--- Colored Text ---*/ 257 | @redTextColor : @red; 258 | @orangeTextColor : @orange; 259 | @yellowTextColor : #B58105; // Yellow text is difficult to read 260 | @oliveTextColor : #8ABC1E; // Olive is difficult to read 261 | @greenTextColor : #1EBC30; // Green is difficult to read 262 | @tealTextColor : #10A3A3; // Teal text is difficult to read 263 | @blueTextColor : @blue; 264 | @violetTextColor : @violet; 265 | @purpleTextColor : @purple; 266 | @pinkTextColor : @pink; 267 | @brownTextColor : @brown; 268 | 269 | /*--- Colored Border ---*/ 270 | @redBorderColor : @redTextColor; 271 | @orangeBorderColor : @orangeTextColor; 272 | @yellowBorderColor : @yellowTextColor; 273 | @oliveBorderColor : @oliveTextColor; 274 | @greenBorderColor : @greenTextColor; 275 | @tealBorderColor : @tealTextColor; 276 | @blueBorderColor : @blueTextColor; 277 | @violetBorderColor : @violetTextColor; 278 | @purpleBorderColor : @purpleTextColor; 279 | @pinkBorderColor : @pinkTextColor; 280 | @brownBorderColor : @brownTextColor; 281 | 282 | /*------------------- 283 | Alpha Colors 284 | --------------------*/ 285 | 286 | @subtleTransparentBlack : rgba(0, 0, 0, 0.03); 287 | @transparentBlack : rgba(0, 0, 0, 0.05); 288 | @strongTransparentBlack : rgba(0, 0, 0, 0.10); 289 | @veryStrongTransparentBlack : rgba(0, 0, 0, 0.15); 290 | 291 | @subtleTransparentWhite : rgba(255, 255, 255, 0.02); 292 | @transparentWhite : rgba(255, 255, 255, 0.08); 293 | @strongTransparentWhite : rgba(255, 255, 255, 0.15); 294 | 295 | /*------------------- 296 | Accents 297 | --------------------*/ 298 | 299 | /* Differentiating Neutrals */ 300 | @subtleGradient: linear-gradient(transparent, @transparentBlack); 301 | 302 | /* Differentiating Layers */ 303 | @subtleShadow: 304 | 0px 1px 2px 0 @borderColor 305 | ; 306 | @floatingShadow: 307 | 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 308 | 0px 2px 10px 0px rgba(34, 36, 38, 0.15) 309 | ; 310 | 311 | /******************************* 312 | Power-User 313 | *******************************/ 314 | 315 | 316 | /*------------------- 317 | Emotive Colors 318 | --------------------*/ 319 | 320 | /* Positive */ 321 | @positiveColor : @green; 322 | @positiveBackgroundColor : #FCFFF5; 323 | @positiveBorderColor : #A3C293; 324 | @positiveHeaderColor : #1A531B; 325 | @positiveTextColor : #2C662D; 326 | 327 | /* Negative */ 328 | @negativeColor : @red; 329 | @negativeBackgroundColor : #FFF6F6; 330 | @negativeBorderColor : #E0B4B4; 331 | @negativeHeaderColor : #912D2B; 332 | @negativeTextColor : #9F3A38; 333 | 334 | /* Info */ 335 | @infoColor : #31CCEC; 336 | @infoBackgroundColor : #F8FFFF; 337 | @infoBorderColor : #A9D5DE; 338 | @infoHeaderColor : #0E566C; 339 | @infoTextColor : #276F86; 340 | 341 | /* Warning */ 342 | @warningColor : #F2C037; 343 | @warningBorderColor : #C9BA9B; 344 | @warningBackgroundColor : #FFFAF3; 345 | @warningHeaderColor : #794B02; 346 | @warningTextColor : #573A08; 347 | 348 | /*------------------- 349 | Paths 350 | --------------------*/ 351 | 352 | /* For source only. Modified in gulp for dist */ 353 | @imagePath : '../../themes/default/assets/images'; 354 | @fontPath : '../../themes/default/assets/fonts'; 355 | 356 | /*------------------- 357 | Em Sizes 358 | --------------------*/ 359 | 360 | /* 361 | This rounds @size values to the closest pixel then expresses that value in (r)em. 362 | This ensures all size values round to exact pixels 363 | */ 364 | @mini : unit( round(@miniSize * @emSize) / @emSize, rem); 365 | @tiny : unit( round(@tinySize * @emSize) / @emSize, rem); 366 | @small : unit( round(@smallSize * @emSize) / @emSize, rem); 367 | @medium : unit( round(@mediumSize * @emSize) / @emSize, rem); 368 | @large : unit( round(@largeSize * @emSize) / @emSize, rem); 369 | @big : unit( round(@bigSize * @emSize) / @emSize, rem); 370 | @huge : unit( round(@hugeSize * @emSize) / @emSize, rem); 371 | @massive : unit( round(@massiveSize * @emSize) / @emSize, rem); 372 | 373 | /* em */ 374 | @relativeMini : unit( round(@miniSize * @emSize) / @emSize, em); 375 | @relativeTiny : unit( round(@tinySize * @emSize) / @emSize, em); 376 | @relativeSmall : unit( round(@smallSize * @emSize) / @emSize, em); 377 | @relativeMedium : unit( round(@mediumSize * @emSize) / @emSize, em); 378 | @relativeLarge : unit( round(@largeSize * @emSize) / @emSize, em); 379 | @relativeBig : unit( round(@bigSize * @emSize) / @emSize, em); 380 | @relativeHuge : unit( round(@hugeSize * @emSize) / @emSize, em); 381 | @relativeMassive : unit( round(@massiveSize * @emSize) / @emSize, em); 382 | 383 | /* rem */ 384 | @absoluteMini : unit( round(@miniSize * @emSize) / @emSize, rem); 385 | @absoluteTiny : unit( round(@tinySize * @emSize) / @emSize, rem); 386 | @absoluteSmall : unit( round(@smallSize * @emSize) / @emSize, rem); 387 | @absoluteMedium : unit( round(@mediumSize * @emSize) / @emSize, rem); 388 | @absoluteLarge : unit( round(@largeSize * @emSize) / @emSize, rem); 389 | @absoluteBig : unit( round(@bigSize * @emSize) / @emSize, rem); 390 | @absoluteHuge : unit( round(@hugeSize * @emSize) / @emSize, rem); 391 | @absoluteMassive : unit( round(@massiveSize * @emSize) / @emSize, rem); 392 | 393 | /*------------------- 394 | Icons 395 | --------------------*/ 396 | 397 | /* Maximum Glyph Width of Icon */ 398 | @iconWidth : 1.18em; 399 | 400 | /*------------------- 401 | Neutral Text 402 | --------------------*/ 403 | 404 | @darkTextColor : rgba(0, 0, 0, 0.85); 405 | @mutedTextColor : rgba(0, 0, 0, 0.6); 406 | @lightTextColor : rgba(0, 0, 0, 0.4); 407 | 408 | @unselectedTextColor : rgba(0, 0, 0, 0.4); 409 | @hoveredTextColor : rgba(0, 0, 0, 0.8); 410 | @pressedTextColor : rgba(0, 0, 0, 0.9); 411 | @selectedTextColor : rgba(0, 0, 0, 0.95); 412 | @disabledTextColor : rgba(0, 0, 0, 0.2); 413 | 414 | @invertedTextColor : rgba(255, 255, 255, 0.9); 415 | @invertedMutedTextColor : rgba(255, 255, 255, 0.8); 416 | @invertedLightTextColor : rgba(255, 255, 255, 0.7); 417 | @invertedUnselectedTextColor : rgba(255, 255, 255, 0.5); 418 | @invertedHoveredTextColor : rgba(255, 255, 255, 1); 419 | @invertedPressedTextColor : rgba(255, 255, 255, 1); 420 | @invertedSelectedTextColor : rgba(255, 255, 255, 1); 421 | @invertedDisabledTextColor : rgba(255, 255, 255, 0.2); 422 | 423 | /*------------------- 424 | Brand Colors 425 | --------------------*/ 426 | 427 | @facebookColor : #3B5998; 428 | @twitterColor : #0084B4; 429 | @googlePlusColor : #DC4A38; 430 | @linkedInColor : #1F88BE; 431 | @youtubeColor : #CC181E; 432 | @instagramColor : #49769C; 433 | @pinterestColor : #00ACED; 434 | @vkColor : #4D7198; 435 | 436 | /*------------------- 437 | Borders 438 | --------------------*/ 439 | 440 | @circularRadius : 500rem; 441 | 442 | @borderColor : rgba(34, 36, 38, 0.15); 443 | @strongBorderColor : rgba(34, 36, 38, 0.22); 444 | @internalBorderColor : rgba(34, 36, 38, 0.1); 445 | @selectedBorderColor : rgba(34, 36, 38, 0.35); 446 | @strongSelectedBorderColor : rgba(34, 36, 38, 0.5); 447 | @disabledBorderColor : rgba(34, 36, 38, 0.5); 448 | 449 | @solidInternalBorderColor : #FAFAFA; 450 | @solidBorderColor : #D4D4D5; 451 | @solidSelectedBorderColor : #BCBDBD; 452 | 453 | @whiteBorderColor : rgba(255, 255, 255, 0.1); 454 | @selectedWhiteBorderColor : rgba(255, 255, 255, 0.8); 455 | 456 | @solidWhiteBorderColor : #555555; 457 | @selectedSolidWhiteBorderColor : #999999; 458 | 459 | 460 | /*------------------- 461 | Derived Values 462 | --------------------*/ 463 | 464 | /* Loaders Position Offset */ 465 | @loaderOffset : -(@loaderSize / 2); 466 | @loaderMargin : @loaderOffset 0em 0em @loaderOffset; 467 | 468 | /* Rendered Scrollbar Width */ 469 | @scrollbarWidth: 17px; 470 | 471 | /* Maximum Single Character Glyph Width, aka Capital "W" */ 472 | @glyphWidth: 1.1em; 473 | 474 | /* Used to match floats with text */ 475 | @lineHeightOffset : ((@lineHeight - 1em) / 2); 476 | @headerLineHeightOffset : (@headerLineHeight - 1em) / 2; 477 | 478 | /* Header Spacing */ 479 | @headerTopMargin : ~"calc(2rem - "@headerLineHeightOffset~")"; 480 | @headerBottomMargin : 1rem; 481 | @headerMargin : @headerTopMargin 0em @headerBottomMargin; 482 | 483 | /* Minimum Mobile Width */ 484 | @pageMinWidth : 320px; 485 | 486 | /* Positive / Negative Dupes */ 487 | @successBackgroundColor : @positiveBackgroundColor; 488 | @successColor : @positiveColor; 489 | @successBorderColor : @positiveBorderColor; 490 | @successHeaderColor : @positiveHeaderColor; 491 | @successTextColor : @positiveTextColor; 492 | 493 | @errorBackgroundColor : @negativeBackgroundColor; 494 | @errorColor : @negativeColor; 495 | @errorBorderColor : @negativeBorderColor; 496 | @errorHeaderColor : @negativeHeaderColor; 497 | @errorTextColor : @negativeTextColor; 498 | 499 | 500 | /* Responsive */ 501 | @largestMobileScreen : (@tabletBreakpoint - 1px); 502 | @largestTabletScreen : (@computerBreakpoint - 1px); 503 | @largestSmallMonitor : (@largeMonitorBreakpoint - 1px); 504 | @largestLargeMonitor : (@widescreenMonitorBreakpoint - 1px); 505 | 506 | 507 | /*------------------- 508 | Exact Pixel Values 509 | --------------------*/ 510 | /* 511 | These are used to specify exact pixel values in em 512 | for things like borders that remain constantly 513 | sized as emSize adjusts 514 | 515 | Since there are many more sizes than names for sizes, 516 | these are named by their original pixel values. 517 | 518 | */ 519 | 520 | @1px : unit( (1 / @emSize), rem); 521 | @2px : unit( (2 / @emSize), rem); 522 | @3px : unit( (3 / @emSize), rem); 523 | @4px : unit( (4 / @emSize), rem); 524 | @5px : unit( (5 / @emSize), rem); 525 | @6px : unit( (6 / @emSize), rem); 526 | @7px : unit( (7 / @emSize), rem); 527 | @8px : unit( (8 / @emSize), rem); 528 | @9px : unit( (9 / @emSize), rem); 529 | @10px : unit( (10 / @emSize), rem); 530 | @11px : unit( (11 / @emSize), rem); 531 | @12px : unit( (12 / @emSize), rem); 532 | @13px : unit( (13 / @emSize), rem); 533 | @14px : unit( (14 / @emSize), rem); 534 | @15px : unit( (15 / @emSize), rem); 535 | @16px : unit( (16 / @emSize), rem); 536 | @17px : unit( (17 / @emSize), rem); 537 | @18px : unit( (18 / @emSize), rem); 538 | @19px : unit( (19 / @emSize), rem); 539 | @20px : unit( (20 / @emSize), rem); 540 | @21px : unit( (21 / @emSize), rem); 541 | @22px : unit( (22 / @emSize), rem); 542 | @23px : unit( (23 / @emSize), rem); 543 | @24px : unit( (24 / @emSize), rem); 544 | @25px : unit( (25 / @emSize), rem); 545 | @26px : unit( (26 / @emSize), rem); 546 | @27px : unit( (27 / @emSize), rem); 547 | @28px : unit( (28 / @emSize), rem); 548 | @29px : unit( (29 / @emSize), rem); 549 | @30px : unit( (30 / @emSize), rem); 550 | @31px : unit( (31 / @emSize), rem); 551 | @32px : unit( (32 / @emSize), rem); 552 | @33px : unit( (33 / @emSize), rem); 553 | @34px : unit( (34 / @emSize), rem); 554 | @35px : unit( (35 / @emSize), rem); 555 | @36px : unit( (36 / @emSize), rem); 556 | @37px : unit( (37 / @emSize), rem); 557 | @38px : unit( (38 / @emSize), rem); 558 | @39px : unit( (39 / @emSize), rem); 559 | @40px : unit( (40 / @emSize), rem); 560 | @41px : unit( (41 / @emSize), rem); 561 | @42px : unit( (42 / @emSize), rem); 562 | @43px : unit( (43 / @emSize), rem); 563 | @44px : unit( (44 / @emSize), rem); 564 | @45px : unit( (45 / @emSize), rem); 565 | @46px : unit( (46 / @emSize), rem); 566 | @47px : unit( (47 / @emSize), rem); 567 | @48px : unit( (48 / @emSize), rem); 568 | @49px : unit( (49 / @emSize), rem); 569 | @50px : unit( (50 / @emSize), rem); 570 | @51px : unit( (51 / @emSize), rem); 571 | @52px : unit( (52 / @emSize), rem); 572 | @53px : unit( (53 / @emSize), rem); 573 | @54px : unit( (54 / @emSize), rem); 574 | @55px : unit( (55 / @emSize), rem); 575 | @56px : unit( (56 / @emSize), rem); 576 | @57px : unit( (57 / @emSize), rem); 577 | @58px : unit( (58 / @emSize), rem); 578 | @59px : unit( (59 / @emSize), rem); 579 | @60px : unit( (60 / @emSize), rem); 580 | @61px : unit( (61 / @emSize), rem); 581 | @62px : unit( (62 / @emSize), rem); 582 | @63px : unit( (63 / @emSize), rem); 583 | @64px : unit( (64 / @emSize), rem); 584 | 585 | @relative1px : unit( (1 / @emSize), em); 586 | @relative2px : unit( (2 / @emSize), em); 587 | @relative3px : unit( (3 / @emSize), em); 588 | @relative4px : unit( (4 / @emSize), em); 589 | @relative5px : unit( (5 / @emSize), em); 590 | @relative6px : unit( (6 / @emSize), em); 591 | @relative7px : unit( (7 / @emSize), em); 592 | @relative8px : unit( (8 / @emSize), em); 593 | @relative9px : unit( (9 / @emSize), em); 594 | @relative10px : unit( (10 / @emSize), em); 595 | @relative11px : unit( (11 / @emSize), em); 596 | @relative12px : unit( (12 / @emSize), em); 597 | @relative13px : unit( (13 / @emSize), em); 598 | @relative14px : unit( (14 / @emSize), em); 599 | @relative15px : unit( (15 / @emSize), em); 600 | @relative16px : unit( (16 / @emSize), em); 601 | @relative17px : unit( (17 / @emSize), em); 602 | @relative18px : unit( (18 / @emSize), em); 603 | @relative19px : unit( (19 / @emSize), em); 604 | @relative20px : unit( (20 / @emSize), em); 605 | @relative21px : unit( (21 / @emSize), em); 606 | @relative22px : unit( (22 / @emSize), em); 607 | @relative23px : unit( (23 / @emSize), em); 608 | @relative24px : unit( (24 / @emSize), em); 609 | @relative25px : unit( (25 / @emSize), em); 610 | @relative26px : unit( (26 / @emSize), em); 611 | @relative27px : unit( (27 / @emSize), em); 612 | @relative28px : unit( (28 / @emSize), em); 613 | @relative29px : unit( (29 / @emSize), em); 614 | @relative30px : unit( (30 / @emSize), em); 615 | @relative31px : unit( (31 / @emSize), em); 616 | @relative32px : unit( (32 / @emSize), em); 617 | @relative33px : unit( (33 / @emSize), em); 618 | @relative34px : unit( (34 / @emSize), em); 619 | @relative35px : unit( (35 / @emSize), em); 620 | @relative36px : unit( (36 / @emSize), em); 621 | @relative37px : unit( (37 / @emSize), em); 622 | @relative38px : unit( (38 / @emSize), em); 623 | @relative39px : unit( (39 / @emSize), em); 624 | @relative40px : unit( (40 / @emSize), em); 625 | @relative41px : unit( (41 / @emSize), em); 626 | @relative42px : unit( (42 / @emSize), em); 627 | @relative43px : unit( (43 / @emSize), em); 628 | @relative44px : unit( (44 / @emSize), em); 629 | @relative45px : unit( (45 / @emSize), em); 630 | @relative46px : unit( (46 / @emSize), em); 631 | @relative47px : unit( (47 / @emSize), em); 632 | @relative48px : unit( (48 / @emSize), em); 633 | @relative49px : unit( (49 / @emSize), em); 634 | @relative50px : unit( (50 / @emSize), em); 635 | @relative51px : unit( (51 / @emSize), em); 636 | @relative52px : unit( (52 / @emSize), em); 637 | @relative53px : unit( (53 / @emSize), em); 638 | @relative54px : unit( (54 / @emSize), em); 639 | @relative55px : unit( (55 / @emSize), em); 640 | @relative56px : unit( (56 / @emSize), em); 641 | @relative57px : unit( (57 / @emSize), em); 642 | @relative58px : unit( (58 / @emSize), em); 643 | @relative59px : unit( (59 / @emSize), em); 644 | @relative60px : unit( (60 / @emSize), em); 645 | @relative61px : unit( (61 / @emSize), em); 646 | @relative62px : unit( (62 / @emSize), em); 647 | @relative63px : unit( (63 / @emSize), em); 648 | @relative64px : unit( (64 / @emSize), em); 649 | 650 | /* Columns */ 651 | @oneWide : (1 / @columnCount * 100%); 652 | @twoWide : (2 / @columnCount * 100%); 653 | @threeWide : (3 / @columnCount * 100%); 654 | @fourWide : (4 / @columnCount * 100%); 655 | @fiveWide : (5 / @columnCount * 100%); 656 | @sixWide : (6 / @columnCount * 100%); 657 | @sevenWide : (7 / @columnCount * 100%); 658 | @eightWide : (8 / @columnCount * 100%); 659 | @nineWide : (9 / @columnCount * 100%); 660 | @tenWide : (10 / @columnCount * 100%); 661 | @elevenWide : (11 / @columnCount * 100%); 662 | @twelveWide : (12 / @columnCount * 100%); 663 | @thirteenWide : (13 / @columnCount * 100%); 664 | @fourteenWide : (14 / @columnCount * 100%); 665 | @fifteenWide : (15 / @columnCount * 100%); 666 | @sixteenWide : (16 / @columnCount * 100%); 667 | 668 | @oneColumn : (1 / 1 * 100%); 669 | @twoColumn : (1 / 2 * 100%); 670 | @threeColumn : (1 / 3 * 100%); 671 | @fourColumn : (1 / 4 * 100%); 672 | @fiveColumn : (1 / 5 * 100%); 673 | @sixColumn : (1 / 6 * 100%); 674 | @sevenColumn : (1 / 7 * 100%); 675 | @eightColumn : (1 / 8 * 100%); 676 | @nineColumn : (1 / 9 * 100%); 677 | @tenColumn : (1 / 10 * 100%); 678 | @elevenColumn : (1 / 11 * 100%); 679 | @twelveColumn : (1 / 12 * 100%); 680 | @thirteenColumn : (1 / 13 * 100%); 681 | @fourteenColumn : (1 / 14 * 100%); 682 | @fifteenColumn : (1 / 15 * 100%); 683 | @sixteenColumn : (1 / 16 * 100%); 684 | 685 | 686 | /******************************* 687 | States 688 | *******************************/ 689 | 690 | /*------------------- 691 | Disabled 692 | --------------------*/ 693 | 694 | @disabledOpacity: 0.45; 695 | @disabledTextColor: rgba(40, 40, 40, 0.3); 696 | @invertedDisabledTextColor: rgba(225, 225, 225, 0.3); 697 | 698 | /*------------------- 699 | Hover 700 | --------------------*/ 701 | 702 | /*--- Shadows ---*/ 703 | @floatingShadowHover: 704 | 0px 2px 4px 0px rgba(34, 36, 38, 0.15), 705 | 0px 2px 10px 0px rgba(34, 36, 38, 0.25) 706 | ; 707 | 708 | /*--- Colors ---*/ 709 | @primaryColorHover : saturate(darken(@primaryColor, 5), 10, relative); 710 | @secondaryColorHover : saturate(lighten(@secondaryColor, 5), 10, relative); 711 | 712 | @redHover : saturate(darken(@red, 5), 10, relative); 713 | @orangeHover : saturate(darken(@orange, 5), 10, relative); 714 | @yellowHover : saturate(darken(@yellow, 5), 10, relative); 715 | @oliveHover : saturate(darken(@olive, 5), 10, relative); 716 | @greenHover : saturate(darken(@green, 5), 10, relative); 717 | @tealHover : saturate(darken(@teal, 5), 10, relative); 718 | @blueHover : saturate(darken(@blue, 5), 10, relative); 719 | @violetHover : saturate(darken(@violet, 5), 10, relative); 720 | @purpleHover : saturate(darken(@purple, 5), 10, relative); 721 | @pinkHover : saturate(darken(@pink, 5), 10, relative); 722 | @brownHover : saturate(darken(@brown, 5), 10, relative); 723 | 724 | @lightRedHover : saturate(darken(@lightRed, 5), 10, relative); 725 | @lightOrangeHover : saturate(darken(@lightOrange, 5), 10, relative); 726 | @lightYellowHover : saturate(darken(@lightYellow, 5), 10, relative); 727 | @lightOliveHover : saturate(darken(@lightOlive, 5), 10, relative); 728 | @lightGreenHover : saturate(darken(@lightGreen, 5), 10, relative); 729 | @lightTealHover : saturate(darken(@lightTeal, 5), 10, relative); 730 | @lightBlueHover : saturate(darken(@lightBlue, 5), 10, relative); 731 | @lightVioletHover : saturate(darken(@lightViolet, 5), 10, relative); 732 | @lightPurpleHover : saturate(darken(@lightPurple, 5), 10, relative); 733 | @lightPinkHover : saturate(darken(@lightPink, 5), 10, relative); 734 | @lightBrownHover : saturate(darken(@lightBrown, 5), 10, relative); 735 | @lightGreyHover : saturate(darken(@lightGrey, 5), 10, relative); 736 | @lightBlackHover : saturate(darken(@fullBlack, 5), 10, relative); 737 | 738 | /*--- Emotive ---*/ 739 | @positiveColorHover : saturate(darken(@positiveColor, 5), 10, relative); 740 | @negativeColorHover : saturate(darken(@negativeColor, 5), 10, relative); 741 | 742 | /*--- Brand ---*/ 743 | @facebookHoverColor : saturate(darken(@facebookColor, 5), 10, relative); 744 | @twitterHoverColor : saturate(darken(@twitterColor, 5), 10, relative); 745 | @googlePlusHoverColor : saturate(darken(@googlePlusColor, 5), 10, relative); 746 | @linkedInHoverColor : saturate(darken(@linkedInColor, 5), 10, relative); 747 | @youtubeHoverColor : saturate(darken(@youtubeColor, 5), 10, relative); 748 | @instagramHoverColor : saturate(darken(@instagramColor, 5), 10, relative); 749 | @pinterestHoverColor : saturate(darken(@pinterestColor, 5), 10, relative); 750 | @vkHoverColor : saturate(darken(@vkColor, 5), 10, relative); 751 | 752 | /*--- Dark Tones ---*/ 753 | @fullBlackHover : lighten(@fullBlack, 5); 754 | @blackHover : lighten(@black, 5); 755 | @greyHover : lighten(@grey, 5); 756 | 757 | /*--- Light Tones ---*/ 758 | @whiteHover : darken(@white, 5); 759 | @offWhiteHover : darken(@offWhite, 5); 760 | @darkWhiteHover : darken(@darkWhite, 5); 761 | 762 | /*------------------- 763 | Focus 764 | --------------------*/ 765 | 766 | /*--- Colors ---*/ 767 | @primaryColorFocus : saturate(darken(@primaryColor, 8), 20, relative); 768 | @secondaryColorFocus : saturate(lighten(@secondaryColor, 8), 20, relative); 769 | 770 | @redFocus : saturate(darken(@red, 8), 20, relative); 771 | @orangeFocus : saturate(darken(@orange, 8), 20, relative); 772 | @yellowFocus : saturate(darken(@yellow, 8), 20, relative); 773 | @oliveFocus : saturate(darken(@olive, 8), 20, relative); 774 | @greenFocus : saturate(darken(@green, 8), 20, relative); 775 | @tealFocus : saturate(darken(@teal, 8), 20, relative); 776 | @blueFocus : saturate(darken(@blue, 8), 20, relative); 777 | @violetFocus : saturate(darken(@violet, 8), 20, relative); 778 | @purpleFocus : saturate(darken(@purple, 8), 20, relative); 779 | @pinkFocus : saturate(darken(@pink, 8), 20, relative); 780 | @brownFocus : saturate(darken(@brown, 8), 20, relative); 781 | 782 | @lightRedFocus : saturate(darken(@lightRed, 8), 20, relative); 783 | @lightOrangeFocus : saturate(darken(@lightOrange, 8), 20, relative); 784 | @lightYellowFocus : saturate(darken(@lightYellow, 8), 20, relative); 785 | @lightOliveFocus : saturate(darken(@lightOlive, 8), 20, relative); 786 | @lightGreenFocus : saturate(darken(@lightGreen, 8), 20, relative); 787 | @lightTealFocus : saturate(darken(@lightTeal, 8), 20, relative); 788 | @lightBlueFocus : saturate(darken(@lightBlue, 8), 20, relative); 789 | @lightVioletFocus : saturate(darken(@lightViolet, 8), 20, relative); 790 | @lightPurpleFocus : saturate(darken(@lightPurple, 8), 20, relative); 791 | @lightPinkFocus : saturate(darken(@lightPink, 8), 20, relative); 792 | @lightBrownFocus : saturate(darken(@lightBrown, 8), 20, relative); 793 | @lightGreyFocus : saturate(darken(@lightGrey, 8), 20, relative); 794 | @lightBlackFocus : saturate(darken(@fullBlack, 8), 20, relative); 795 | 796 | /*--- Emotive ---*/ 797 | @positiveColorFocus : saturate(darken(@positiveColor, 8), 20, relative); 798 | @negativeColorFocus : saturate(darken(@negativeColor, 8), 20, relative); 799 | 800 | /*--- Brand ---*/ 801 | @facebookFocusColor : saturate(darken(@facebookColor, 8), 20, relative); 802 | @twitterFocusColor : saturate(darken(@twitterColor, 8), 20, relative); 803 | @googlePlusFocusColor : saturate(darken(@googlePlusColor, 8), 20, relative); 804 | @linkedInFocusColor : saturate(darken(@linkedInColor, 8), 20, relative); 805 | @youtubeFocusColor : saturate(darken(@youtubeColor, 8), 20, relative); 806 | @instagramFocusColor : saturate(darken(@instagramColor, 8), 20, relative); 807 | @pinterestFocusColor : saturate(darken(@pinterestColor, 8), 20, relative); 808 | @vkFocusColor : saturate(darken(@vkColor, 8), 20, relative); 809 | 810 | /*--- Dark Tones ---*/ 811 | @fullBlackFocus : lighten(@fullBlack, 8); 812 | @blackFocus : lighten(@black, 8); 813 | @greyFocus : lighten(@grey, 8); 814 | 815 | /*--- Light Tones ---*/ 816 | @whiteFocus : darken(@white, 8); 817 | @offWhiteFocus : darken(@offWhite, 8); 818 | @darkWhiteFocus : darken(@darkWhite, 8); 819 | 820 | 821 | /*------------------- 822 | Down (:active) 823 | --------------------*/ 824 | 825 | /*--- Colors ---*/ 826 | @primaryColorDown : darken(@primaryColor, 10); 827 | @secondaryColorDown : lighten(@secondaryColor, 10); 828 | 829 | @redDown : darken(@red, 10); 830 | @orangeDown : darken(@orange, 10); 831 | @yellowDown : darken(@yellow, 10); 832 | @oliveDown : darken(@olive, 10); 833 | @greenDown : darken(@green, 10); 834 | @tealDown : darken(@teal, 10); 835 | @blueDown : darken(@blue, 10); 836 | @violetDown : darken(@violet, 10); 837 | @purpleDown : darken(@purple, 10); 838 | @pinkDown : darken(@pink, 10); 839 | @brownDown : darken(@brown, 10); 840 | 841 | @lightRedDown : darken(@lightRed, 10); 842 | @lightOrangeDown : darken(@lightOrange, 10); 843 | @lightYellowDown : darken(@lightYellow, 10); 844 | @lightOliveDown : darken(@lightOlive, 10); 845 | @lightGreenDown : darken(@lightGreen, 10); 846 | @lightTealDown : darken(@lightTeal, 10); 847 | @lightBlueDown : darken(@lightBlue, 10); 848 | @lightVioletDown : darken(@lightViolet, 10); 849 | @lightPurpleDown : darken(@lightPurple, 10); 850 | @lightPinkDown : darken(@lightPink, 10); 851 | @lightBrownDown : darken(@lightBrown, 10); 852 | @lightGreyDown : darken(@lightGrey, 10); 853 | @lightBlackDown : darken(@fullBlack, 10); 854 | 855 | /*--- Emotive ---*/ 856 | @positiveColorDown : darken(@positiveColor, 10); 857 | @negativeColorDown : darken(@negativeColor, 10); 858 | 859 | /*--- Brand ---*/ 860 | @facebookDownColor : darken(@facebookColor, 10); 861 | @twitterDownColor : darken(@twitterColor, 10); 862 | @googlePlusDownColor : darken(@googlePlusColor, 10); 863 | @linkedInDownColor : darken(@linkedInColor, 10); 864 | @youtubeDownColor : darken(@youtubeColor, 10); 865 | @instagramDownColor : darken(@instagramColor, 10); 866 | @pinterestDownColor : darken(@pinterestColor, 10); 867 | @vkDownColor : darken(@vkColor, 10); 868 | 869 | /*--- Dark Tones ---*/ 870 | @fullBlackDown : lighten(@fullBlack, 10); 871 | @blackDown : lighten(@black, 10); 872 | @greyDown : lighten(@grey, 10); 873 | 874 | /*--- Light Tones ---*/ 875 | @whiteDown : darken(@white, 10); 876 | @offWhiteDown : darken(@offWhite, 10); 877 | @darkWhiteDown : darken(@darkWhite, 10); 878 | 879 | 880 | /*------------------- 881 | Active 882 | --------------------*/ 883 | 884 | /*--- Colors ---*/ 885 | @primaryColorActive : saturate(darken(@primaryColor, 5), 15, relative); 886 | @secondaryColorActive : saturate(lighten(@secondaryColor, 5), 15, relative); 887 | 888 | @redActive : saturate(darken(@red, 5), 15, relative); 889 | @orangeActive : saturate(darken(@orange, 5), 15, relative); 890 | @yellowActive : saturate(darken(@yellow, 5), 15, relative); 891 | @oliveActive : saturate(darken(@olive, 5), 15, relative); 892 | @greenActive : saturate(darken(@green, 5), 15, relative); 893 | @tealActive : saturate(darken(@teal, 5), 15, relative); 894 | @blueActive : saturate(darken(@blue, 5), 15, relative); 895 | @violetActive : saturate(darken(@violet, 5), 15, relative); 896 | @purpleActive : saturate(darken(@purple, 5), 15, relative); 897 | @pinkActive : saturate(darken(@pink, 5), 15, relative); 898 | @brownActive : saturate(darken(@brown, 5), 15, relative); 899 | 900 | @lightRedActive : saturate(darken(@lightRed, 5), 15, relative); 901 | @lightOrangeActive : saturate(darken(@lightOrange, 5), 15, relative); 902 | @lightYellowActive : saturate(darken(@lightYellow, 5), 15, relative); 903 | @lightOliveActive : saturate(darken(@lightOlive, 5), 15, relative); 904 | @lightGreenActive : saturate(darken(@lightGreen, 5), 15, relative); 905 | @lightTealActive : saturate(darken(@lightTeal, 5), 15, relative); 906 | @lightBlueActive : saturate(darken(@lightBlue, 5), 15, relative); 907 | @lightVioletActive : saturate(darken(@lightViolet, 5), 15, relative); 908 | @lightPurpleActive : saturate(darken(@lightPurple, 5), 15, relative); 909 | @lightPinkActive : saturate(darken(@lightPink, 5), 15, relative); 910 | @lightBrownActive : saturate(darken(@lightBrown, 5), 15, relative); 911 | @lightGreyActive : saturate(darken(@lightGrey, 5), 15, relative); 912 | @lightBlackActive : saturate(darken(@fullBlack, 5), 15, relative); 913 | 914 | /*--- Emotive ---*/ 915 | @positiveColorActive : saturate(darken(@positiveColor, 5), 15, relative); 916 | @negativeColorActive : saturate(darken(@negativeColor, 5), 15, relative); 917 | 918 | /*--- Brand ---*/ 919 | @facebookActiveColor : saturate(darken(@facebookColor, 5), 15, relative); 920 | @twitterActiveColor : saturate(darken(@twitterColor, 5), 15, relative); 921 | @googlePlusActiveColor : saturate(darken(@googlePlusColor, 5), 15, relative); 922 | @linkedInActiveColor : saturate(darken(@linkedInColor, 5), 15, relative); 923 | @youtubeActiveColor : saturate(darken(@youtubeColor, 5), 15, relative); 924 | @instagramActiveColor : saturate(darken(@instagramColor, 5), 15, relative); 925 | @pinterestActiveColor : saturate(darken(@pinterestColor, 5), 15, relative); 926 | @vkActiveColor : saturate(darken(@vkColor, 5), 15, relative); 927 | 928 | /*--- Dark Tones ---*/ 929 | @fullBlackActive : darken(@fullBlack, 5); 930 | @blackActive : darken(@black, 5); 931 | @greyActive : darken(@grey, 5); 932 | 933 | /*--- Light Tones ---*/ 934 | @whiteActive : darken(@white, 5); 935 | @offWhiteActive : darken(@offWhite, 5); 936 | @darkWhiteActive : darken(@darkWhite, 5); 937 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-admin-scaffolding 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-admin-scaffolding", 3 | "version": "1.0.0", 4 | "description": "A Vue.js background manager scaffolding base vue.js + vue-router + vue-loader + webpack + vue-resource(whatwg-fetch) + vue-validator + vue-i18n(vue-localize) + vuex", 5 | "author": "lichbin", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js", 10 | "unit": "karma start test/unit/karma.conf.js --single-run", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e" 13 | }, 14 | "dependencies": { 15 | "babel-runtime": "^6.0.0", 16 | "jquery": "^2.2.3", 17 | "react-cookie": "^0.4.7", 18 | "semantic-ui-css": "^2.2.2", 19 | "vue": "^1.0.21", 20 | "vue-echarts": "^0.1.1", 21 | "vue-resource": "^0.9.3", 22 | "vue-router": "^0.7.13", 23 | "vue-validator": "^2.1.4", 24 | "vuex": "^0.8.2", 25 | "vuex-router-sync": "^1.0.1" 26 | }, 27 | "devDependencies": { 28 | "babel-core": "^6.0.0", 29 | "babel-loader": "^6.0.0", 30 | "babel-plugin-transform-runtime": "^6.0.0", 31 | "babel-preset-es2015": "^6.0.0", 32 | "babel-preset-stage-2": "^6.0.0", 33 | "connect-history-api-fallback": "^1.1.0", 34 | "css-loader": "^0.23.0", 35 | "eventsource-polyfill": "^0.9.6", 36 | "express": "^4.13.3", 37 | "extract-text-webpack-plugin": "^1.0.1", 38 | "file-loader": "^0.8.4", 39 | "function-bind": "^1.0.2", 40 | "html-webpack-plugin": "^2.8.1", 41 | "http-proxy-middleware": "^0.12.0", 42 | "json-loader": "^0.5.4", 43 | "karma": "^0.13.15", 44 | "karma-coverage": "^0.5.5", 45 | "karma-mocha": "^0.2.2", 46 | "karma-phantomjs-launcher": "^1.0.0", 47 | "karma-sinon-chai": "^1.2.0", 48 | "karma-sourcemap-loader": "^0.3.7", 49 | "karma-spec-reporter": "0.0.24", 50 | "karma-webpack": "^1.7.0", 51 | "lolex": "^1.4.0", 52 | "mocha": "^2.4.5", 53 | "chai": "^3.5.0", 54 | "sinon": "^1.17.3", 55 | "sinon-chai": "^2.8.0", 56 | "inject-loader": "^2.0.1", 57 | "isparta-loader": "^2.0.0", 58 | "phantomjs-prebuilt": "^2.1.3", 59 | "chromedriver": "^2.21.2", 60 | "cross-spawn": "^2.1.5", 61 | "nightwatch": "^0.8.18", 62 | "selenium-server": "2.53.0", 63 | "ora": "^0.2.0", 64 | "shelljs": "^0.6.0", 65 | "url-loader": "^0.5.7", 66 | "vue-hot-reload-api": "^1.2.0", 67 | "vue-html-loader": "^1.0.0", 68 | "vue-loader": "^8.3.0", 69 | "vue-style-loader": "^1.0.0", 70 | "webpack": "^1.12.2", 71 | "webpack-dev-middleware": "^1.4.0", 72 | "webpack-hot-middleware": "^2.6.0", 73 | "webpack-merge": "^0.8.3" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 10 | -------------------------------------------------------------------------------- /src/assets/img/avatar_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/src/assets/img/avatar_small.jpg -------------------------------------------------------------------------------- /src/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/src/assets/img/logo.png -------------------------------------------------------------------------------- /src/assets/img/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rootsli/vueadmin/bf1f350d264fcbed681ddb4864f15d9f43813dde/src/assets/img/logo2.png -------------------------------------------------------------------------------- /src/components/Breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 13 | 31 | 42 | -------------------------------------------------------------------------------- /src/components/Form.vue: -------------------------------------------------------------------------------- 1 | 65 | 94 | -------------------------------------------------------------------------------- /src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 32 | 101 | 197 | 207 | -------------------------------------------------------------------------------- /src/components/List.vue: -------------------------------------------------------------------------------- 1 | 69 | 141 | 164 | -------------------------------------------------------------------------------- /src/components/ListForm.vue: -------------------------------------------------------------------------------- 1 | 43 | 71 | 80 | -------------------------------------------------------------------------------- /src/components/Login.vue: -------------------------------------------------------------------------------- 1 | 31 | 66 | 83 | -------------------------------------------------------------------------------- /src/components/Page1.vue: -------------------------------------------------------------------------------- 1 | 19 | 47 | -------------------------------------------------------------------------------- /src/components/Page2.vue: -------------------------------------------------------------------------------- 1 | 9 | 31 | -------------------------------------------------------------------------------- /src/components/Pagination.vue: -------------------------------------------------------------------------------- 1 | 18 | 115 | -------------------------------------------------------------------------------- /src/components/charts/Bar.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | 57 | -------------------------------------------------------------------------------- /src/components/charts/BaseChart.vue: -------------------------------------------------------------------------------- 1 | 36 | 41 | 69 | -------------------------------------------------------------------------------- /src/components/charts/Bubble.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | 98 | -------------------------------------------------------------------------------- /src/components/charts/Meter.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | 54 | -------------------------------------------------------------------------------- /src/components/charts/Polar.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | 62 | -------------------------------------------------------------------------------- /src/components/menu/Menu.vue: -------------------------------------------------------------------------------- 1 | 11 | 38 | 85 | -------------------------------------------------------------------------------- /src/components/menu/menu.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/18. 3 | */ 4 | export default [ 5 | { 6 | name: 'basicEditor', 7 | title: '基本控件', 8 | icon: 'home', 9 | subMenu: [ 10 | { 11 | title: '表格', 12 | path: '/home/list' 13 | }, 14 | { 15 | title: '表单', 16 | path: '/home/form' 17 | } 18 | ] 19 | 20 | }, 21 | { 22 | name: 'chartEditor', 23 | title: '图形报表', 24 | icon: 'block layout', 25 | subMenu: [ 26 | { 27 | title: '基本图形', 28 | path: '/home/baseChart' 29 | }, 30 | { 31 | title: '地图', 32 | path: '/home/map' 33 | } 34 | ] 35 | 36 | }, 37 | { 38 | name: 'other', 39 | title: '页面测试', 40 | icon: 'calendar', 41 | subMenu: [ 42 | { 43 | title: '内容超边界布局示例', 44 | path: '/home/other1' 45 | }, 46 | { 47 | title: '页面跳转示例', 48 | path: '/home/other2' 49 | } 50 | ] 51 | 52 | } 53 | ]; 54 | -------------------------------------------------------------------------------- /src/filters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/18. 3 | * 全局filter 4 | */ 5 | let format = (value) => { 6 | return value >= 10 ? value : '0' + value 7 | } 8 | /** 9 | * 时间格式化 10 | */ 11 | export let dateFilter = (time, type) => { 12 | let date = new Date(time * 1000) 13 | let year = date.getFullYear() 14 | let month = date.getMonth() + 1 15 | let day = date.getDate() 16 | let hours = date.getHours() 17 | let minutes = date.getMinutes() 18 | let second = date.getSeconds() 19 | let result 20 | switch (type) { 21 | case 0: // 01-05 22 | result = `${format(month)}-${format(day)}` 23 | break 24 | case 1: // 11:12 25 | result = `${format(hours)}-${format(minutes)}` 26 | break 27 | case 2: // 2015-01-05 28 | result = `${year}-${format(month)}-${format(day)}` 29 | break 30 | case 3: // 2015-01-05 11:12 31 | result = `${year}-${format(month)}-${format(day)} ${format(hours)}:${format(minutes)}` 32 | break 33 | case 4:// 2015-01-05 11:12:06 34 | result = `${year}-${format(month)}-${format(day)} ${format(hours)}:${format(minutes)}:${format(second)}` 35 | break 36 | } 37 | return result 38 | } -------------------------------------------------------------------------------- /src/http/host.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | export const API_ROOT = (process.env.NODE_ENV === 'production') ? 'http://api.test.com' : 'http://rap.taobao.org/mockjs/6107'; 5 | -------------------------------------------------------------------------------- /src/http/http.interceptors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/22. 3 | */ 4 | import Vue from 'vue' 5 | import VueResource from 'vue-resource' 6 | import {API_ROOT} from './host.config' 7 | 8 | Vue.use(VueResource) 9 | Vue.http.options.crossOrigin = true 10 | Vue.http.options.credentials = true 11 | 12 | Vue.http.options.xhr = {withCredentials: false} 13 | Vue.http.options.root = '/root' 14 | 15 | Vue.http.headers.common['bbb'] = 'bbb' 16 | 17 | Vue.http.interceptors.push((request, next) => { 18 | //这里对请求体进行处理 19 | if (request.method != 'GET') { 20 | request.headers = request.headers || {} 21 | request.headers.Authorization = 'Bearer YXBpOnBhc3N3b3Jk' 22 | } 23 | 24 | // 里可以对响应的结果进行处理 25 | next((response) => { 26 | if (response.status === 404) { 27 | // signOut() 28 | // window.location.pathname = '/login' 29 | console.log('http 404') 30 | } 31 | }); 32 | }); 33 | 34 | //服务接口声明 35 | export const AuthResource = Vue.resource(API_ROOT + '/login') 36 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | //libraries 2 | import Vue from 'vue' 3 | import VueRouter from 'vue-router' 4 | import VueValidator from 'vue-validator' 5 | import {sync} from 'vuex-router-sync' 6 | import store from './vuex/store' 7 | // import jQuery from 'jquery' 8 | import '../node_modules/semantic-ui-css/semantic.min.css' 9 | import semantic from 'semantic' 10 | import routes from './router/routes' 11 | import alias from './router/alias' 12 | import * as filters from './filters' 13 | import App from './App' 14 | import {SET_MENU, SET_PROGRESS} from './vuex/types' 15 | import ECharts from 'vue-echarts/src/components/ECharts.vue' 16 | 17 | //全局注册echarts插件,也可以不在此处注册而直接在组件内部注册。具体请参考vue-echarts插件 18 | Vue.component('chart', ECharts) 19 | 20 | //Validator 21 | Vue.use(VueValidator) 22 | 23 | //Router 24 | Vue.use(VueRouter) 25 | const router = new VueRouter({ 26 | history: false, 27 | linkActiveClass: 'active', 28 | saveScrollPosition: true 29 | }) 30 | router.map(routes) 31 | router.alias(alias) 32 | router.beforeEach(transition => { 33 | if (transition.to.auth && !store.state.auth.token) { 34 | // transition.abort() 35 | transition.redirect('/login') 36 | } else { 37 | transition.next() 38 | } 39 | 40 | //触发进度条 41 | if (transition.to.name != 'login') { 42 | store.dispatch(SET_PROGRESS, {rate: 1}) 43 | } 44 | }) 45 | router.afterEach(transition => { 46 | store.dispatch(SET_MENU, {current: transition.to.parent}) 47 | window.scrollTo(0, 0) 48 | }) 49 | 50 | // Filters 51 | Vue.filter('date', filters.dateFilter) 52 | 53 | //router <-> vuex 54 | sync(store, router) 55 | 56 | router.start(App, 'app') 57 | 58 | -------------------------------------------------------------------------------- /src/router/alias.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/15. 3 | */ 4 | export default { 5 | 'page1': '/home/page1', 6 | 'page2': '/home/page2' 7 | } -------------------------------------------------------------------------------- /src/router/routes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/15. 3 | */ 4 | import Login from '../components/Login' 5 | import Home from '../components/Home' 6 | import List from '../components/List' 7 | import Form from '../components/Form' 8 | import Page1 from '../components/Page1' 9 | import Page2 from '../components/Page2' 10 | import BaseChart from '../components/charts/BaseChart' 11 | 12 | export default { 13 | '/': { 14 | name: 'login', 15 | auth: false, 16 | component: Login 17 | }, 18 | '/home': { 19 | name: 'home', 20 | component: Home, 21 | subRoutes: { 22 | '/list': { 23 | name: 'list', 24 | auth: true, 25 | parent: 'basicEditor', //上一级菜单名 26 | component: List 27 | }, 28 | '/form': { 29 | name: 'form', 30 | auth: true, 31 | parent: 'basicEditor', 32 | component: Form 33 | }, 34 | '/baseChart': { 35 | name: 'baseChart', 36 | auth: true, 37 | parent: 'chartEditor', 38 | component: BaseChart 39 | }, 40 | '/map': { 41 | name: 'map', 42 | auth: true, 43 | parent: 'chartEditor', 44 | component: Page2 45 | }, 46 | '/other1': { 47 | name: 'other1', 48 | auth: true, 49 | parent: 'other', 50 | component: Page1 51 | } 52 | , 53 | '/other2': { 54 | name: 'other2', 55 | auth: true, 56 | parent: 'other', 57 | component: Page2 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/services/auth-service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | import {AuthResource} from '../http/http.interceptors' 5 | 6 | export default { 7 | login: user => { 8 | return AuthResource.get({id: user.password}) 9 | }, 10 | logout: () => { 11 | 12 | }, 13 | getUserInfo: () => { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/vuex/actions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | import cookie from 'react-cookie' 5 | import auth from '../services/auth-service' 6 | import * as types from './types' 7 | 8 | //登录 9 | export const login = (store, user) => { 10 | auth.login(user).then(response => { 11 | cookie.save('token', response.data.token) 12 | store.dispatch(types.LOGIN_SUCCESS, {token: token}) 13 | store.router.go({path: '/home/list'}) 14 | }, error => { //登录失败 15 | user.password = '' 16 | store.dispatch(types.LOGIN_FAILED, {error: '密码错误,请重新输入。'}) 17 | store.router.go({path: '/home/list'}) 18 | }); 19 | } 20 | 21 | //设置进度 22 | export const setProgress = (store, rate) => { 23 | store.dispatch(types.SET_PROGRESS, {rate: rate}) 24 | } 25 | -------------------------------------------------------------------------------- /src/vuex/middlewares.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | import createLogger from 'vuex/logger' 5 | 6 | export default process.env.NODE_ENV !== 'production' ? [createLogger()] : [] 7 | -------------------------------------------------------------------------------- /src/vuex/modules/auth.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | import cookie from 'react-cookie' 5 | import { 6 | LOGIN_SUCCESS, 7 | LOGIN_FAILED, 8 | LOGOUT_USER, 9 | USERINFO_SUCCESS, 10 | USERINFO_FAILURE 11 | } from '../types' 12 | 13 | const state = { 14 | token: cookie.load('token') || 'test_token', 15 | user: null, //存放用户基本信息 16 | errmsg:'请输入密码' //登录错误信息 17 | } 18 | 19 | const mutations = { 20 | [LOGIN_SUCCESS](state, action){ 21 | state.token = action.token 22 | state.errmsg = '请输入密码' 23 | }, 24 | [LOGIN_FAILED](state, action){ 25 | state.errmsg = action.error || '请输入密码' 26 | }, 27 | [LOGOUT_USER](state, action){ 28 | state.token = cookie.load('token') || null 29 | state.user = null 30 | state.token = null 31 | }, 32 | [USERINFO_SUCCESS](state, action){ 33 | state.user = action.user 34 | }, 35 | [USERINFO_FAILURE](state, action){ 36 | state.user = null 37 | } 38 | } 39 | 40 | export default { 41 | state, 42 | mutations 43 | } 44 | -------------------------------------------------------------------------------- /src/vuex/modules/menu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | import {SET_MENU} from '../types' 5 | 6 | const state = { 7 | current: null 8 | } 9 | 10 | const mutations = { 11 | [SET_MENU](state, action){ 12 | state.current = action.current 13 | } 14 | } 15 | 16 | export default { 17 | state, 18 | mutations 19 | } 20 | -------------------------------------------------------------------------------- /src/vuex/modules/progress.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | import {SET_PROGRESS} from '../types' 5 | 6 | const state = { 7 | rate: 0 8 | } 9 | 10 | const mutations = { 11 | [SET_PROGRESS](state, action){ 12 | state.rate = action.rate 13 | } 14 | } 15 | 16 | export default { 17 | state, 18 | mutations 19 | } 20 | -------------------------------------------------------------------------------- /src/vuex/store.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | import Vue from 'vue' 5 | import Vuex from 'vuex' 6 | import middlewares from './middlewares' 7 | import auth from './modules/auth' 8 | import menu from './modules/menu' 9 | import progress from './modules/progress' 10 | 11 | const debug = process.env.NODE_ENV !== 'production' 12 | Vue.use(Vuex) 13 | Vue.config.debug = debug 14 | Vue.config.warnExpressionErrors = false 15 | 16 | export default new Vuex.Store({ 17 | modules: { 18 | auth, 19 | menu, 20 | progress 21 | }, 22 | strict: debug, 23 | middlewares 24 | }) 25 | -------------------------------------------------------------------------------- /src/vuex/types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lichb on 2016/7/25. 3 | */ 4 | 5 | //登录 6 | export const LOGIN_SUCCESS = 'LOGIN_SUCCESS' 7 | export const LOGIN_FAILED = 'LOGIN_FAILED' 8 | export const LOGOUT_USER = 'LOGOUT_USER' 9 | 10 | //获取用户信息 11 | export const USERINFO_SUCCESS = 'USERINFO_SUCCESS' 12 | export const USERINFO_FAILURE = 'USERINFO_FAILURE' 13 | 14 | //设置当前菜单 15 | export const SET_MENU = 'SET_MENU' 16 | 17 | //顶部进度条 18 | export const SET_PROGRESS = 'SET_PROGRESS' 19 | -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | // http://nightwatchjs.org/guide#settings-file 2 | module.exports = { 3 | "src_folders": ["test/e2e/specs"], 4 | "output_folder": "test/e2e/reports", 5 | "custom_assertions_path": ["test/e2e/custom-assertions"], 6 | 7 | "selenium": { 8 | "start_process": true, 9 | "server_path": "node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.0.jar", 10 | "host": "127.0.0.1", 11 | "port": 4444, 12 | "cli_args": { 13 | "webdriver.chrome.driver": require('chromedriver').path, 14 | 'webdriver.firefox.profile': '' 15 | } 16 | }, 17 | 18 | "test_settings": { 19 | "default": { 20 | "selenium_port": 4444, 21 | "selenium_host": "localhost", 22 | "silent": true 23 | }, 24 | 25 | "chrome": { 26 | "desiredCapabilities": { 27 | "browserName": "chrome", 28 | "javascriptEnabled": true, 29 | "acceptSslCerts": true 30 | } 31 | }, 32 | 33 | "firefox": { 34 | "desiredCapabilities": { 35 | "browserName": "firefox", 36 | "javascriptEnabled": true, 37 | "acceptSslCerts": true 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | // process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | browser 7 | .url('http://localhost:8080') 8 | .waitForElementVisible('.ui.middle', 5000) 9 | .assert.elementPresent('.content') 10 | // .assert.containsText('div', '登录') 11 | .assert.elementCount('h2', 1) 12 | .end() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind') 4 | 5 | // require all test files (files that ends with .spec.js) 6 | var testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | var srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var path = require('path') 7 | var merge = require('webpack-merge') 8 | var baseConfig = require('../../build/webpack.base.conf') 9 | var utils = require('../../build/utils') 10 | var webpack = require('webpack') 11 | var projectRoot = path.resolve(__dirname, '../../') 12 | 13 | var webpackConfig = merge(baseConfig, { 14 | // use inline sourcemap for karma-sourcemap-loader 15 | module: { 16 | loaders: utils.styleLoaders() 17 | }, 18 | devtool: '#inline-source-map', 19 | vue: { 20 | loaders: { 21 | js: 'isparta' 22 | } 23 | }, 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | 'process.env': require('../../config/test.env') 27 | }) 28 | ] 29 | }) 30 | 31 | // no need for app entry during tests 32 | delete webpackConfig.entry 33 | 34 | // make sure isparta loader is applied before eslint 35 | webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || [] 36 | webpackConfig.module.preLoaders.unshift({ 37 | test: /\.js$/, 38 | loader: 'isparta', 39 | include: path.resolve(projectRoot, 'src') 40 | }) 41 | 42 | // only apply babel for test files when using isparta 43 | webpackConfig.module.loaders.some(function (loader, i) { 44 | if (loader.loader === 'babel') { 45 | loader.include = path.resolve(projectRoot, 'test/unit') 46 | return true 47 | } 48 | }) 49 | 50 | module.exports = function (config) { 51 | config.set({ 52 | // to run in additional browsers: 53 | // 1. install corresponding karma launcher 54 | // http://karma-runner.github.io/0.13/config/browsers.html 55 | // 2. add it to the `browsers` array below. 56 | browsers: ['PhantomJS'], 57 | frameworks: ['mocha', 'sinon-chai'], 58 | reporters: ['spec', 'coverage'], 59 | files: ['./index.js'], 60 | preprocessors: { 61 | './index.js': ['webpack', 'sourcemap'] 62 | }, 63 | webpack: webpackConfig, 64 | webpackMiddleware: { 65 | noInfo: true 66 | }, 67 | coverageReporter: { 68 | dir: './coverage', 69 | reporters: [ 70 | { type: 'lcov', subdir: '.' }, 71 | { type: 'text-summary' } 72 | ] 73 | } 74 | }) 75 | } 76 | -------------------------------------------------------------------------------- /test/unit/specs/Pagination.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Pagination from 'src/components/Pagination' 3 | 4 | describe('Pagination.vue', () => { 5 | it('should render correct contents', () => { 6 | const vm = new Vue({ 7 | template: '
', 8 | components: { Pagination } 9 | }).$mount() 10 | expect(vm.$el.querySelector('.pagination-info').textContent).to.contain('数据') 11 | }) 12 | }) 13 | --------------------------------------------------------------------------------