Feature/task1.0.0 xg See merge request yanxuan-frontend/shop-pc!41merge-requests/42/head
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"test": {
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"@babel/preset-env",
|
||||||
|
{
|
||||||
|
"targets": {
|
||||||
|
"node": "current"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
# editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
@ -0,0 +1,94 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Node template
|
||||||
|
# Logs
|
||||||
|
/logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Nuxt generate
|
||||||
|
dist
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless
|
||||||
|
|
||||||
|
# IDE / Editor
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Service worker
|
||||||
|
sw.*
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Vim swap files
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
env.js
|
@ -0,0 +1,2 @@
|
|||||||
|
registry=https://registry.npm.taobao.org/
|
||||||
|
sass_binary_site="https://npm.taobao.org/mirrors/node-sass"
|
@ -0,0 +1,12 @@
|
|||||||
|
FROM node:12.13.1
|
||||||
|
WORKDIR /workload
|
||||||
|
|
||||||
|
COPY nuxt.config.js /workload/nuxt.config.js
|
||||||
|
COPY package.json /workload/package.json
|
||||||
|
COPY .nuxt /workload/.nuxt
|
||||||
|
|
||||||
|
RUN npm config set registry https://registry.npm.taobao.org \
|
||||||
|
&& npm install
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD npm run start
|
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 928 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 763 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 752 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 812 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 904 B |
After Width: | Height: | Size: 689 B |
After Width: | Height: | Size: 671 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 728 B |
After Width: | Height: | Size: 369 B |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 928 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 134 B |
After Width: | Height: | Size: 133 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 540 B |
After Width: | Height: | Size: 553 B |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 351 B |
After Width: | Height: | Size: 201 B |
After Width: | Height: | Size: 215 B |
After Width: | Height: | Size: 567 B |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 815 B |
After Width: | Height: | Size: 611 B |
After Width: | Height: | Size: 237 B |
After Width: | Height: | Size: 237 B |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 706 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 710 B |
@ -0,0 +1,7 @@
|
|||||||
|
/* 改变主题色变量 */
|
||||||
|
$--color-primary: #FF512B;
|
||||||
|
|
||||||
|
/* 改变 icon 字体路径变量,必需 */
|
||||||
|
$--font-path: '~element-ui/lib/theme-chalk/fonts';
|
||||||
|
|
||||||
|
@import "~element-ui/packages/theme-chalk/src/index";
|
@ -0,0 +1,118 @@
|
|||||||
|
|
||||||
|
/* ========================================================================
|
||||||
|
Component: Flex
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.flex { display: flex; }
|
||||||
|
.flex-inline { display: inline-flex; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove pseudo elements created by micro clearfix as precaution
|
||||||
|
*/
|
||||||
|
|
||||||
|
.flex::before,
|
||||||
|
.flex::after,
|
||||||
|
.flex-inline::before,
|
||||||
|
.flex-inline::after { display: none; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Alignment
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Align items along the main axis of the current line of the flex container
|
||||||
|
* Row: Horizontal
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Default
|
||||||
|
.flex-left { justify-content: flex-start; }
|
||||||
|
.flex-center { justify-content: center; }
|
||||||
|
.flex-right { justify-content: flex-end; }
|
||||||
|
.flex-between { justify-content: space-between; }
|
||||||
|
.flex-around { justify-content: space-around; }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Align items in the cross axis of the current line of the flex container
|
||||||
|
* Row: Vertical
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Default
|
||||||
|
.flex-stretch { align-items: stretch; }
|
||||||
|
.flex-top { align-items: flex-start; }
|
||||||
|
.flex-middle { align-items: center; }
|
||||||
|
.flex-bottom { align-items: flex-end; }
|
||||||
|
.flex-baseline { align-items: baseline; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Direction
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
// Default
|
||||||
|
.flex-row { flex-direction: row; }
|
||||||
|
.flex-row-reverse { flex-direction: row-reverse; }
|
||||||
|
.flex-column { flex-direction: column; }
|
||||||
|
.flex-column-reverse { flex-direction: column-reverse; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Wrap
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
// Default
|
||||||
|
.flex-nowrap { flex-wrap: nowrap; }
|
||||||
|
.flex-wrap { flex-wrap: wrap; }
|
||||||
|
.flex-wrap-reverse { flex-wrap: wrap-reverse; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Aligns items within the flex container when there is extra space in the cross-axis
|
||||||
|
* Only works if there is more than one line of flex items
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Default
|
||||||
|
.flex-wrap-stretch { align-content: stretch; }
|
||||||
|
.flex-wrap-top { align-content: flex-start; }
|
||||||
|
.flex-wrap-middle { align-content: center; }
|
||||||
|
.flex-wrap-bottom { align-content: flex-end; }
|
||||||
|
.flex-wrap-between { align-content: space-between; }
|
||||||
|
.flex-wrap-around { align-content: space-around; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Item ordering
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default is 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
.flex-first { order: -1;}
|
||||||
|
.flex-last { order: 99;}
|
||||||
|
|
||||||
|
|
||||||
|
/* Item dimensions
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initial: 0 1 auto
|
||||||
|
* Content dimensions, but shrinks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No Flex: 0 0 auto
|
||||||
|
* Content dimensions
|
||||||
|
*/
|
||||||
|
|
||||||
|
.flex-none { flex: none; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Relative Flex: 1 1 auto
|
||||||
|
* Space is allocated considering content
|
||||||
|
*/
|
||||||
|
|
||||||
|
.flex-auto { flex: auto; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Absolute Flex: 1 1 0%
|
||||||
|
* Space is allocated solely based on flex
|
||||||
|
*/
|
||||||
|
|
||||||
|
.flex-1 { flex: 1; }
|
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
@import './flex.scss';
|
||||||
|
@import './util.scss';
|
||||||
|
|
||||||
|
* {
|
||||||
|
-webkit-box-sizing: border-box; box-sizing: border-box;
|
||||||
|
|
||||||
|
-webkit-touch-callout:none; /*系统默认菜单被禁用*/
|
||||||
|
-webkit-user-select:none; /*webkit浏览器*/
|
||||||
|
-khtml-user-select:none; /*早期浏览器*/
|
||||||
|
-moz-user-select:none;/*火狐*/
|
||||||
|
-ms-user-select:none; /*IE10*/
|
||||||
|
user-select:none;
|
||||||
|
&:after, &:before {
|
||||||
|
@extend *;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body, dl, dd, h1, h2, h3, h4, h5, p, figure, form, ul, ol { margin: 0; font-size: 14px;}
|
||||||
|
ul, ol, input, button { padding: 0;}
|
||||||
|
ul, ol, li { list-style: none;list-style-type: none}
|
||||||
|
h1, h2, h3, h4, h5 { font-size: 100%;}
|
||||||
|
input { border: 0; margin: 0;}
|
||||||
|
img { width: 100%;}
|
||||||
|
a, button, input, optgroup, select, textarea, img { outline:none; -webkit-tap-highlight-color: rgba(0,0,0,0); }
|
||||||
|
a, img { -webkit-touch-callout: none; border: 0;}
|
||||||
|
html, body { position: absolute; min-height: 100%; height: 100%; width: 100%;}
|
||||||
|
input, textarea, img, button { vertical-align: middle; outline: none;}
|
||||||
|
body {
|
||||||
|
font-family: PingFang SC, Microsoft YaHei, Helvetica, STHeiTi, sans-serif !important;
|
||||||
|
color: #333; -webkit-font-smoothing: antialiased; font-smoothing: antialiased;
|
||||||
|
overflow-anchor: none}
|
||||||
|
table {border-collapse: collapse; border-spacing: 0;
|
||||||
|
color: #333;}
|
||||||
|
a { text-decoration:none;
|
||||||
|
color: #333;
|
||||||
|
&:hover { text-decoration:none; color: #FF512B;}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 自定义滚动条样式 */
|
||||||
|
.scrollbar-self {
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
background-color: none;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background-color: none;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #dddddd;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
$baseFontSize: 100 !default;
|
||||||
|
/**/
|
||||||
|
|
||||||
|
@mixin adj ($styleName, $value...) {
|
||||||
|
#{$styleName}: $value;
|
||||||
|
-webkit-#{$styleName}: $value;
|
||||||
|
-moz-#{$styleName}: $value;
|
||||||
|
-o-#{$styleName}: $value;
|
||||||
|
-ms-#{$styleName}: $value;
|
||||||
|
}
|
||||||
|
// @mixin transition($value...) {
|
||||||
|
// -webkit-transiton: $value;
|
||||||
|
// -moz-transtion: $value;
|
||||||
|
// -ms-transtion: $value;
|
||||||
|
// transition: $value;
|
||||||
|
// }
|
||||||
|
// @mixin transition-delay($value...) {
|
||||||
|
// transition-delay: $value;
|
||||||
|
// -moz-transition-delay: $value; /* Firefox 4 */
|
||||||
|
// -webkit-transition-delay: $value; /* Safari 和 Chrome */
|
||||||
|
// -o-transition-delay: $value; /* Opera */
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @mixin transform($value...) {
|
||||||
|
// transform: $value;
|
||||||
|
// -webkit-transform: $value;
|
||||||
|
// -moz-transform: $value;
|
||||||
|
// -o-transform: $value;
|
||||||
|
// -ms-transform: $value;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @mixin animation($value...) {
|
||||||
|
// -webkit-animation: $value;
|
||||||
|
// -moz-animation: $value;
|
||||||
|
// -ms-animation: $value;
|
||||||
|
// animation: $value;
|
||||||
|
// }
|
||||||
|
@mixin keyframes($animationName) {
|
||||||
|
@-webkit-keyframes #{$animationName} {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
@-moz-keyframes #{$animationName} {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
@-o-keyframes #{$animationName} {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
@keyframes #{$animationName} {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @mixin filter($value...) {
|
||||||
|
// -webkit-filter: $value;
|
||||||
|
// -moz-filter: $value;
|
||||||
|
// -ms-filter: $value;
|
||||||
|
// filter: $value;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@mixin linear-gradient($value...) {
|
||||||
|
background: -webkit-linear-gradient($value); /* Safari 5.1 - 6.0 */
|
||||||
|
background: -o-linear-gradient($value); /* Opera 11.1 - 12.0 */
|
||||||
|
background: -moz-linear-gradient($value); /* Firefox 3.6 - 15 */
|
||||||
|
background: linear-gradient(t$value); /* 标准的语法 */
|
||||||
|
}
|
||||||
|
|
||||||
|
// @mixin boxShow($value...) {
|
||||||
|
// -webkit-box-shadow: $value;
|
||||||
|
// -moz-box-shadow: $value;
|
||||||
|
// -ms-box-shadow: $value;
|
||||||
|
// box-shadow: $value;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@function torem($value) {
|
||||||
|
@return ($value / $baseFontSize * 1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
%overflow-scrolling {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
overflow-scrolling: touch;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
%els {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*内容居中布局*/
|
||||||
|
@mixin layout-box {
|
||||||
|
width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*单行溢出*/
|
||||||
|
@mixin ellipsis {
|
||||||
|
overflow:hidden;
|
||||||
|
text-overflow:ellipsis;
|
||||||
|
white-space:nowrap
|
||||||
|
}
|
||||||
|
|
||||||
|
/*多行溢出*/
|
||||||
|
@mixin ellipses($line) {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: $line;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*可点击文字hover*/
|
||||||
|
.hover-text:hover {
|
||||||
|
color: #FF875B;
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-08 14:41:42
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-12 14:37:00
|
||||||
|
* @Description: file content
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="ui-goods-info" @click="$router.push(`/goods/detail/${goods.productId}`)">
|
||||||
|
<div class="ui-goods-info--img">
|
||||||
|
<img :src="goods.productImageUrl || goods.productMainPicture"/>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<b>{{goods.productName}}</b>
|
||||||
|
<span>{{goods.skuDescribe}}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props : {
|
||||||
|
goods : {
|
||||||
|
type : Object,
|
||||||
|
default : () => ({})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ui-goods-info{
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
&--img{
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
}
|
||||||
|
p{
|
||||||
|
width: 270px;
|
||||||
|
margin: 7px 0 0 18px;
|
||||||
|
text-align: left;
|
||||||
|
b{
|
||||||
|
display: block;
|
||||||
|
line-height: 22px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow:ellipsis;
|
||||||
|
display:-webkit-box;
|
||||||
|
-webkit-box-orient:vertical;
|
||||||
|
-webkit-line-clamp:2;
|
||||||
|
}
|
||||||
|
span{
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chosen">
|
||||||
|
<div class="chosen-title flex flex-between flex-middle">
|
||||||
|
<h3 class="chosen-title--txt">为你精选</h3>
|
||||||
|
<div class="chosen-title--btn flex" @click="getRecommendedGoodsList()">
|
||||||
|
<img src="@/assets/img/goods/each.png" alt="切换推荐" />
|
||||||
|
<span>换一组</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chosen-list">
|
||||||
|
<UiGoodsItem
|
||||||
|
:item="item"
|
||||||
|
v-for="item in recommendedData"
|
||||||
|
:key="item.id"
|
||||||
|
></UiGoodsItem>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { ApiGetRecommendedGoodsList } from "@/plugins/api/goods";
|
||||||
|
import UiGoodsItem from "@/components/UiGoodsItem.vue";
|
||||||
|
export default {
|
||||||
|
components: { UiGoodsItem },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
recommendedData: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getRecommendedGoodsList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getRecommendedGoodsList() {
|
||||||
|
let vm = this;
|
||||||
|
let res = await ApiGetRecommendedGoodsList();
|
||||||
|
vm.recommendedData = res.result;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.chosen {
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px 0 40px;
|
||||||
|
background: #f8f8f8;
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
@include layout-box;
|
||||||
|
&--txt {
|
||||||
|
font-size: 24px;
|
||||||
|
font-family: Microsoft YaHei-Bold, Microsoft YaHei;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
&--btn {
|
||||||
|
width: 140px;
|
||||||
|
cursor: pointer;
|
||||||
|
img {
|
||||||
|
width: 27px;
|
||||||
|
height: 27px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
font-size: 18px;
|
||||||
|
font-family: Microsoft YaHei-Regular, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-list {
|
||||||
|
@include layout-box;
|
||||||
|
padding-top: 40px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, 232px);
|
||||||
|
justify-content: space-between;
|
||||||
|
grid-row-gap: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
width="16%"
|
||||||
|
center
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
:show-close="false"
|
||||||
|
class="bs-order-ensure"
|
||||||
|
>
|
||||||
|
<div class="dialog-content flex flex-middle">
|
||||||
|
<img src="~/assets/img/common/icon-warning.png" />
|
||||||
|
<span>{{ title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-footer flex flex-between">
|
||||||
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
|
<el-button class="dialog-footer__btn--ensure" @click="onConfirm"
|
||||||
|
>确认</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import UiButton from "./UiButton.vue";
|
||||||
|
export default {
|
||||||
|
components: { UiButton },
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dialogVisible: {
|
||||||
|
get() {
|
||||||
|
return this.visible;
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit("update:visible", val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onConfirm() {
|
||||||
|
this.$emit("confirm");
|
||||||
|
this.dialogVisible = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/deep/.el-dialog {
|
||||||
|
.el-dialog__header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.el-dialog__body {
|
||||||
|
padding: 41px 60px;
|
||||||
|
.dialog-content {
|
||||||
|
color: rgba(0, 0, 0, 0.8);
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 0 2px 42px 2px;
|
||||||
|
img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.dialog-footer {
|
||||||
|
.el-button {
|
||||||
|
width: 90px;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.dialog-footer__btn--ensure {
|
||||||
|
background: #ff875b;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,27 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-09 20:00:57
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-09 20:04:59
|
||||||
|
* @Description: file content
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<el-dialog :visible="visible" @close="close">
|
||||||
|
<slot></slot>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
visible : {
|
||||||
|
type : Boolean,
|
||||||
|
default : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
close(...args){
|
||||||
|
this.$emit('close', args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -0,0 +1,37 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-12 10:30:07
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-12 11:01:57
|
||||||
|
* @Description: file content
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="ui-empty">
|
||||||
|
<img class="ui-empty--icon" :src="icon"/>
|
||||||
|
<p class="ui-empty--desc">{{desc}}</p>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props : {
|
||||||
|
title : String,
|
||||||
|
desc : String,
|
||||||
|
icon : String
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ui-empty{
|
||||||
|
margin-top: 30px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 80px 0;
|
||||||
|
&--icon{
|
||||||
|
width: 228px;
|
||||||
|
}
|
||||||
|
&--desc{
|
||||||
|
margin: 20px 0;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<div class="goods-item" @click="onItem">
|
||||||
|
<img class="goods-item__img" :src="item.mainPicture" alt="商品图片" />
|
||||||
|
<div class="goods-item__title">
|
||||||
|
<span class="goods-item__title-label" v-if="isLabel(item.labelList)">
|
||||||
|
{{ getLabel(item.labelList) }}
|
||||||
|
</span>
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
<div class="goods-item__price">
|
||||||
|
<UiMoney :money="item.startingPrice"></UiMoney>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import UiMoney from "@/components/UiMoney.vue";
|
||||||
|
export default {
|
||||||
|
name: "UiGoodsItem",
|
||||||
|
componetns: { UiMoney },
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isLabel(arr) {
|
||||||
|
return arr.some((item) => item.code);
|
||||||
|
},
|
||||||
|
getLabel(arr) {
|
||||||
|
let str = "";
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i].code != "miaosha") {
|
||||||
|
str = arr[i].text;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
onItem() {
|
||||||
|
this.$router.push({
|
||||||
|
path: "/goods/detail/" + this.item.id,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.goods-item {
|
||||||
|
width: 232px;
|
||||||
|
height: 340px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #ffffff;
|
||||||
|
|
||||||
|
&__img {
|
||||||
|
width: 232px;
|
||||||
|
height: 232px;
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
width: 200px;
|
||||||
|
height: 45px;
|
||||||
|
line-height: 22px;
|
||||||
|
margin: 17px auto 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: Microsoft YaHei-Regular, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #333333;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
&-label {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 8px;
|
||||||
|
background: rgba(255, 135, 91, 0.1);
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: Microsoft YaHei-Regular, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #ff875b;
|
||||||
|
text-align: center;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__price {
|
||||||
|
width: 200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,41 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-07 22:40:55
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-10 13:48:39
|
||||||
|
* @Description: file content
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="ui-line-box">
|
||||||
|
<div class="ui-line-box--head">
|
||||||
|
<slot name="head">
|
||||||
|
<b class="ui-line-box--title">{{title}}</b>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<slot name="body"></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props : {
|
||||||
|
title : {
|
||||||
|
type : String,
|
||||||
|
default : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ui-line-box{
|
||||||
|
border:1px solid #ddd;
|
||||||
|
&--head{
|
||||||
|
height: 42px;
|
||||||
|
line-height: 42px;
|
||||||
|
padding: 0 30px;
|
||||||
|
background: #f8f8f8;
|
||||||
|
}
|
||||||
|
&--title{
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,24 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-12 16:52:52
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-12 17:02:52
|
||||||
|
* @Description: file content
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="loading" >正在查询数据...</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
.loading{
|
||||||
|
height: 300px;
|
||||||
|
line-height: 100px;
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,10 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-07 22:57:24
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-07 22:57:39
|
||||||
|
* @Description: file content
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<el-radio/>
|
||||||
|
</template>
|
@ -0,0 +1,54 @@
|
|||||||
|
kind: Deployment
|
||||||
|
apiVersion: apps/v1
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: $IMAGES
|
||||||
|
name: $IMAGES
|
||||||
|
namespace: yanxuan
|
||||||
|
spec:
|
||||||
|
progressDeadlineSeconds: 600
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: $IMAGES
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 25%
|
||||||
|
maxSurge: 25%
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: $IMAGES
|
||||||
|
spec:
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: aliyun-docker-hub
|
||||||
|
containers:
|
||||||
|
- image: '$REGISTRY/$DOCKERHUB_NAMESPACE/$IMAGES:$BUILD_NUMBER'
|
||||||
|
name: app
|
||||||
|
ports:
|
||||||
|
- containerPort: $JAR_PORD
|
||||||
|
protocol: TCP
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: '0.5'
|
||||||
|
memory: 500Mi
|
||||||
|
terminationMessagePath: /dev/termination-log
|
||||||
|
terminationMessagePolicy: File
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: $IMAGES
|
||||||
|
namespace: yanxuan
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 3000
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 3000
|
||||||
|
selector:
|
||||||
|
app: $IMAGES
|
||||||
|
type: ClusterIP
|
@ -0,0 +1,22 @@
|
|||||||
|
module.exports = {
|
||||||
|
moduleNameMapper: {
|
||||||
|
'^@/(.*)$': '<rootDir>/$1',
|
||||||
|
'^~/(.*)$': '<rootDir>/$1',
|
||||||
|
'^vue$': 'vue/dist/vue.common.js'
|
||||||
|
},
|
||||||
|
moduleFileExtensions: [
|
||||||
|
'js',
|
||||||
|
'vue',
|
||||||
|
'json'
|
||||||
|
],
|
||||||
|
transform: {
|
||||||
|
'^.+\\.js$': 'babel-jest',
|
||||||
|
'.*\\.(vue)$': 'vue-jest'
|
||||||
|
},
|
||||||
|
collectCoverage: true,
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'<rootDir>/components/**/*.vue',
|
||||||
|
'<rootDir>/pages/**/*.vue'
|
||||||
|
],
|
||||||
|
testEnvironment: 'jsdom'
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-04 17:56:39
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-08 15:53:49
|
||||||
|
* @Description: file content
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="layout">
|
||||||
|
<BsLogin :visible.sync="loginVisible" />
|
||||||
|
<Header :is-sticky="isSticky" />
|
||||||
|
<Nuxt />
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import BsLogin from "@/components/BsLogin.vue";
|
||||||
|
import Header from "./module/header/index.vue";
|
||||||
|
import Footer from "./module/footer/index.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Layout",
|
||||||
|
components: { Header, Footer, BsLogin },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isSticky: false,
|
||||||
|
ticking: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
loginVisible: {
|
||||||
|
get() {
|
||||||
|
return this.$store.state.loginVisible;
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$store.commit("setLoginVisible", val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 监听滚动事件
|
||||||
|
window.addEventListener("scroll", this.scrollEventMethod);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
window.removeEventListener("scroll", this.scrollEventMethod);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
scrollEventMethod(e) {
|
||||||
|
const that = this;
|
||||||
|
// 节流
|
||||||
|
if (!that.ticking) {
|
||||||
|
window.requestAnimationFrame(function () {
|
||||||
|
that.ticking = false;
|
||||||
|
that.isSticky = window.scrollY > 300;
|
||||||
|
});
|
||||||
|
that.ticking = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.layout-footer {
|
||||||
|
height: 189px;
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,263 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 购物车 -->
|
||||||
|
<el-popover
|
||||||
|
popper-class="header-cart-popover"
|
||||||
|
trigger="hover"
|
||||||
|
placement="bottom"
|
||||||
|
width="330"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
slot="reference"
|
||||||
|
class="header-cart-popover__refrence flex flex-middle"
|
||||||
|
@click="onJumpCart"
|
||||||
|
>
|
||||||
|
<img src="~/assets/img/layout/icon-shop.png" />
|
||||||
|
<span>购物车</span>
|
||||||
|
<div v-if="cartProducts.length > 0" class="wrap-right-cart__tip">
|
||||||
|
{{ cartProducts.length }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="header-cart-products scrollbar-self">
|
||||||
|
<div
|
||||||
|
v-for="item in products"
|
||||||
|
:key="item.id"
|
||||||
|
@click="onJumpGoodsDetail"
|
||||||
|
class="header-cart-products__wrap flex flex-middle flex-between"
|
||||||
|
>
|
||||||
|
<div class="cart-products-wrap__left flex felx-middle">
|
||||||
|
<div class="products-wrap-left__cover">
|
||||||
|
<img :src="item.productMainPicture" />
|
||||||
|
</div>
|
||||||
|
<div class="products-wrap-left__info">
|
||||||
|
<p class="wrap-left-info__title">{{ item.productName }}</p>
|
||||||
|
<div class="wrap-left-info__detail flex">
|
||||||
|
<span class="left-info-detail__skuname">{{
|
||||||
|
item.productSku.name
|
||||||
|
}}</span>
|
||||||
|
<span class="left-info-detail__count">{{ item.number }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<UiMoney
|
||||||
|
class="cart-products-wrap__right"
|
||||||
|
:float="true"
|
||||||
|
:money="item.product.startingPrice"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- 失效商品 -->
|
||||||
|
<template v-if="failureProducts.length > 0">
|
||||||
|
<div class="header-cart-products__bar">以下商品已失效</div>
|
||||||
|
<div
|
||||||
|
v-for="item in failureProducts"
|
||||||
|
:key="item.id"
|
||||||
|
@click="onJumpGoodsDetail"
|
||||||
|
class="header-cart-products__wrap flex flex-middle flex-between"
|
||||||
|
>
|
||||||
|
<div class="cart-products-wrap__left flex felx-middle">
|
||||||
|
<div class="products-wrap-left__cover">
|
||||||
|
<img :src="item.productMainPicture" />
|
||||||
|
</div>
|
||||||
|
<div class="products-wrap-left__info">
|
||||||
|
<p
|
||||||
|
class="wrap-left-info__title header-cart-products--failure-color"
|
||||||
|
>
|
||||||
|
{{ item.productName }}
|
||||||
|
</p>
|
||||||
|
<div class="wrap-left-info__detail flex">
|
||||||
|
<span class="left-info-detail__skuname">{{
|
||||||
|
item.productSku && item.productSku.name
|
||||||
|
}}</span>
|
||||||
|
<span class="left-info-detail__count">{{ item.number }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<UiMoney
|
||||||
|
class="header-cart-products--failure-color"
|
||||||
|
:float="true"
|
||||||
|
:money="item.product.startingPrice"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="header-cart-bottom flex flex-middle flex-between">
|
||||||
|
<p>共{{ cartProducts.length }}件商品</p>
|
||||||
|
<UiButton type="red_panel" :radius="true" @click="onJumCartPage"
|
||||||
|
>去购物车</UiButton
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { mapState } from "vuex";
|
||||||
|
import UiButton from "@/components/UiButton.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "HeaderCart",
|
||||||
|
components: { UiButton },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
products: [],
|
||||||
|
failureProducts: [], // 失效商品
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(["cartProducts"]),
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
cartProducts: {
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
handler(val) {
|
||||||
|
this.products = [];
|
||||||
|
this.failureProducts = [];
|
||||||
|
val.forEach((item) => {
|
||||||
|
if (item.product.isEnable) {
|
||||||
|
if (item.productSku && item.productSku.stock > 0) {
|
||||||
|
// 商品未失效且有库存
|
||||||
|
this.products.push(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.failureProducts.push(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.failureProducts.push(item);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$store.dispatch("getCartProducts");
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onJumpCart() {
|
||||||
|
if (!this.$isLoginValidate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$router.push("/cart");
|
||||||
|
},
|
||||||
|
onJumpGoodsDetail(id) {
|
||||||
|
this.$router.push(`/goods/detail/${id}`);
|
||||||
|
},
|
||||||
|
onJumCartPage() {
|
||||||
|
this.$router.push("/cart");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.header-cart-popover {
|
||||||
|
padding: 16px 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-cart-popover__refrence {
|
||||||
|
padding: 0 18px;
|
||||||
|
height: 42px;
|
||||||
|
line-height: 42px;
|
||||||
|
color: #999999;
|
||||||
|
border-radius: 8px 8px 8px 8px;
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
cursor: pointer;
|
||||||
|
.wrap-right-cart__tip {
|
||||||
|
min-width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
padding: 0 3px;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 14px;
|
||||||
|
text-align: center;
|
||||||
|
background: #ff512b;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin: 0 4px 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.header-cart-popover {
|
||||||
|
padding: 20px 16px;
|
||||||
|
.header-cart-products {
|
||||||
|
padding: 0 10px 50px 0;
|
||||||
|
max-height: 360px;
|
||||||
|
overflow: auto;
|
||||||
|
&--failure-color {
|
||||||
|
color: #999999 !important;
|
||||||
|
}
|
||||||
|
.header-cart-products__wrap {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
.cart-products-wrap__left {
|
||||||
|
.products-wrap-left__cover {
|
||||||
|
width: 54px;
|
||||||
|
height: 54px;
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 11px;
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.products-wrap-left__info {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999999;
|
||||||
|
.wrap-left-info__title {
|
||||||
|
display: block;
|
||||||
|
width: 120px;
|
||||||
|
@include ellipsis;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.wrap-left-info__detail {
|
||||||
|
.left-info-detail__skuname {
|
||||||
|
display: block;
|
||||||
|
width: 70px;
|
||||||
|
@include ellipsis;
|
||||||
|
}
|
||||||
|
.left-info-detail__count {
|
||||||
|
&::before {
|
||||||
|
content: "X";
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cart-products-wrap__right {
|
||||||
|
color: #ff512b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.header-cart-products__bar {
|
||||||
|
font-size: 14px;
|
||||||
|
width: 298px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
padding: 0 11px;
|
||||||
|
background: #f8f8f8;
|
||||||
|
color: #999999;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.header-cart-bottom {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background: #eeeeee;
|
||||||
|
padding: 0 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666666;
|
||||||
|
/deep/.ui-button {
|
||||||
|
width: 84px;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,219 @@
|
|||||||
|
<template>
|
||||||
|
<div class="header-category">
|
||||||
|
<!-- 热门分类 -->
|
||||||
|
<div
|
||||||
|
v-show="showCategroyTab"
|
||||||
|
class="header-box-tab__category"
|
||||||
|
@mouseenter="handleCategoryChange(true)"
|
||||||
|
@mouseleave="handleCategoryChange(false)"
|
||||||
|
>
|
||||||
|
<div class="tab-category__label flex flex-center flex-middle">
|
||||||
|
<img src="~/assets/img/layout/icon-category.png" />
|
||||||
|
<span>热门分类</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-show="isCategroyOpen || categroyVisible"
|
||||||
|
class="tab-category__menu flex"
|
||||||
|
@mouseenter="handleCategoryTwoChange(true)"
|
||||||
|
@mouseleave="handleCategoryTwoChange(false)"
|
||||||
|
>
|
||||||
|
<!-- 左侧一级分类 -->
|
||||||
|
<div class="tab-category-menu__left">
|
||||||
|
<div
|
||||||
|
v-for="item in categroyData"
|
||||||
|
:key="item.id"
|
||||||
|
@mouseenter="handleCategoryHover(item.id)"
|
||||||
|
@click="onCategoryClick(item.id, CATEGROY_LEVEL.ONE)"
|
||||||
|
class="menu-left__item flex flex-middle"
|
||||||
|
:class="{
|
||||||
|
'menu-left__item--light': item.id === currentCategroyId,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<img />
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧二级分类 -->
|
||||||
|
<div
|
||||||
|
v-show="categroyTwoVisible"
|
||||||
|
class="tab-category-menu__right flex-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="item in categroyData"
|
||||||
|
:key="item.id"
|
||||||
|
@mouseenter="handleCategoryHover(item.id)"
|
||||||
|
class="category-menu-right__wrap"
|
||||||
|
:class="{
|
||||||
|
'category-menu-right__wrap--light': item.id === currentCategroyId,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-for="itemList in item.list"
|
||||||
|
:key="itemList.id"
|
||||||
|
class="menu-right-wrap__item"
|
||||||
|
@click="onCategoryClick(itemList.id, CATEGROY_LEVEL.TWO)"
|
||||||
|
>{{ itemList.name }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
ApiGetCategoryOneList,
|
||||||
|
ApiGetCategoryTwoAndGoods,
|
||||||
|
} from "@/plugins/api/goods";
|
||||||
|
const CATEGROY_HIDE_PAGES = [/\/account/]; // 隐藏热门分类tab的页面
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "HeaderCategory",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
categroyTwoVisible: false, // 是否展示二级分类
|
||||||
|
categroyVisible: false, // 是否展示一级分类
|
||||||
|
currentCategroyId: 0, // 当前鼠标悬停的一级分类id
|
||||||
|
categroyData: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
showCategroyTab() {
|
||||||
|
return !CATEGROY_HIDE_PAGES.some((reg) => {
|
||||||
|
return reg.test(this.$route.path);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 热门分类默认打开
|
||||||
|
isCategroyOpen() {
|
||||||
|
return this.$route.path === "/";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getCategroyData();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取热门分类信息
|
||||||
|
async getCategroyData() {
|
||||||
|
const { result } = await ApiGetCategoryOneList();
|
||||||
|
if (result && result.length > 0) {
|
||||||
|
this.categroyData = await Promise.all(
|
||||||
|
result.map(async (item) => {
|
||||||
|
const { result: resultGoods } = await ApiGetCategoryTwoAndGoods({
|
||||||
|
categoryId: item.id,
|
||||||
|
});
|
||||||
|
if (resultGoods && resultGoods.length > 0) {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
list: resultGoods,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 一级分类鼠标悬停
|
||||||
|
handleCategoryHover(id) {
|
||||||
|
this.currentCategroyId = id;
|
||||||
|
},
|
||||||
|
// 分类点击
|
||||||
|
onCategoryClick(id, levelType) {
|
||||||
|
this.categroyVisible = false;
|
||||||
|
this.categroyTwoVisible = false;
|
||||||
|
this.$router.push({
|
||||||
|
path: "/goods/list",
|
||||||
|
query: {
|
||||||
|
id,
|
||||||
|
levelType,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 一级分类是否可见
|
||||||
|
handleCategoryChange(val) {
|
||||||
|
this.categroyVisible = val;
|
||||||
|
if (!val) {
|
||||||
|
this.currentCategroyId = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 二级分类是否可见
|
||||||
|
handleCategoryTwoChange(val) {
|
||||||
|
this.categroyTwoVisible = val;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-category {
|
||||||
|
height: 100%;
|
||||||
|
.header-box-tab__category {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
.tab-category__label {
|
||||||
|
width: 190px;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(270deg, #ffa25a 0%, #ff7f39 100%);
|
||||||
|
border-radius: 4px 4px 0px 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
cursor: pointer;
|
||||||
|
img {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tab-category__menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 38px;
|
||||||
|
left: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333333;
|
||||||
|
.tab-category-menu__left {
|
||||||
|
width: 190px;
|
||||||
|
padding: 15px 0;
|
||||||
|
background: #ffffff;
|
||||||
|
.menu-left__item {
|
||||||
|
height: 50px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 24px 0 41px;
|
||||||
|
&:hover,
|
||||||
|
&--light {
|
||||||
|
color: #ff875b;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tab-category-menu__right {
|
||||||
|
padding: 15px 26px;
|
||||||
|
box-shadow: 7px 0px 10px 1px rgba(0, 0, 0, 0.1);
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
background: #ffffff;
|
||||||
|
.category-menu-right__wrap {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
padding: 0 16px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999999;
|
||||||
|
white-space: nowrap;
|
||||||
|
&:hover,
|
||||||
|
&--light {
|
||||||
|
background: #f8f8f8;
|
||||||
|
}
|
||||||
|
.menu-right-wrap__item {
|
||||||
|
color: #999999;
|
||||||
|
margin-right: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: #ff875b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,334 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout-header">
|
||||||
|
<!-- 滚动吸顶头部 -->
|
||||||
|
<div v-show="isSticky">
|
||||||
|
<div
|
||||||
|
class="sticky-bar-header"
|
||||||
|
:class="{ 'sticky-bar-header--hide-shadow': hideBarShadow }"
|
||||||
|
>
|
||||||
|
<div class="sticky-bar-header__wrap flex flex-middle flex-between">
|
||||||
|
<div class="flex flex-middle">
|
||||||
|
<img
|
||||||
|
class="bar-header-wrap__logo"
|
||||||
|
src="~/assets/img/layout/logo-sticky.png"
|
||||||
|
/>
|
||||||
|
<el-menu
|
||||||
|
:default-active="tabPath"
|
||||||
|
mode="horizontal"
|
||||||
|
@select="onTabSelect"
|
||||||
|
>
|
||||||
|
<el-menu-item
|
||||||
|
v-for="item in tabList"
|
||||||
|
:key="item.value"
|
||||||
|
:index="item.value"
|
||||||
|
>{{ item.label }}</el-menu-item
|
||||||
|
>
|
||||||
|
</el-menu>
|
||||||
|
</div>
|
||||||
|
<div class="bar-header-wrap__icons flex flex-middle">
|
||||||
|
<img
|
||||||
|
src="~/assets/img/layout/icon-search-sticky.png"
|
||||||
|
@click="$router.push('/goods/list')"
|
||||||
|
/>
|
||||||
|
<div class="header-wrap-icons__shop" @click="$router.push('/cart')">
|
||||||
|
<img src="~/assets/img/layout/icon-shop-sticky.png" />
|
||||||
|
<span v-if="cartCount > 0" class="">{{ cartCount }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="token"
|
||||||
|
class="header-wrap-icons__login"
|
||||||
|
@click="$router.push('/account/home')"
|
||||||
|
>
|
||||||
|
<img :src="userInfo.avatar" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="header-wrap-icons__unlogin"
|
||||||
|
@click="onLoginClick"
|
||||||
|
>
|
||||||
|
登录
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template>
|
||||||
|
<HeaderInfoBar />
|
||||||
|
<div class="default-bar-header">
|
||||||
|
<div class="bar-header-box">
|
||||||
|
<div class="bar-header-box__wrap flex flex-between flex-middle">
|
||||||
|
<img
|
||||||
|
class="header-box-wrap__logo"
|
||||||
|
src="~/assets/img/layout/logo.png"
|
||||||
|
/>
|
||||||
|
<div class="header-box-wrap__right flex flex-middle">
|
||||||
|
<div class="box-wrap-right__search flex">
|
||||||
|
<div class="search-input">
|
||||||
|
<el-input
|
||||||
|
v-model="searchContent"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入商品名称"
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="search-icon flex flex-center flex-middle"
|
||||||
|
@click="onSearch"
|
||||||
|
>
|
||||||
|
<img src="~/assets/img/layout/icon-search.png" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 购物车 -->
|
||||||
|
<HeaderCart />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bar-header-box__tab flex flex-middle">
|
||||||
|
<HeaderCategory />
|
||||||
|
<div
|
||||||
|
v-for="item in tabList"
|
||||||
|
:key="item.value"
|
||||||
|
class="header-box-tab__common flex flex-center flex-middle"
|
||||||
|
:class="{
|
||||||
|
'header-box-tab__common--light':
|
||||||
|
item.value === $nuxt.$route.fullPath,
|
||||||
|
}"
|
||||||
|
@click="onTabSelect(item.value)"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!hideBarLine" class="layout-header-line"></div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { mapState } from "vuex";
|
||||||
|
import { CATEGROY_LEVEL } from "@/constants";
|
||||||
|
import HeaderInfoBar from "./HeaderInfoBar.vue";
|
||||||
|
import HeaderCategory from "./HeaderCategory.vue";
|
||||||
|
import HeaderCart from "./HeaderCart.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DefaultHeader",
|
||||||
|
components: { HeaderInfoBar, HeaderCategory, HeaderCart },
|
||||||
|
props: {
|
||||||
|
// 是否置顶
|
||||||
|
isSticky: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
CATEGROY_LEVEL,
|
||||||
|
searchContent: "",
|
||||||
|
tabPath: "/",
|
||||||
|
cartCount: 0, // 购物车商品数
|
||||||
|
cartProductList: [], // 购物车列表
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(["userInfo", "token", "seckillTabVisible"]),
|
||||||
|
tabList() {
|
||||||
|
const defaultList = [
|
||||||
|
{ label: "首页", value: "/" },
|
||||||
|
{
|
||||||
|
label: "开发书籍",
|
||||||
|
value: `/goods/list?id=6&levelType=${CATEGROY_LEVEL.ONE}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
if (this.seckillTabVisible) {
|
||||||
|
return [...defaultList, { label: "限时秒杀", value: "/seckill" }];
|
||||||
|
}
|
||||||
|
return defaultList;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 是否隐藏吸顶tab底部阴影
|
||||||
|
hideBarShadow() {
|
||||||
|
return ["/seckill"].includes(this.$route.path);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 是否隐藏底部黄色边框
|
||||||
|
hideBarLine() {
|
||||||
|
return ["/", "/seckill"].includes(this.$route.path);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
"$route.path"(val) {
|
||||||
|
if (val !== "/goods/list") {
|
||||||
|
this.searchContent = "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onLoginClick() {
|
||||||
|
this.$isLoginValidate();
|
||||||
|
},
|
||||||
|
onTabSelect(value) {
|
||||||
|
this.tabPath = value;
|
||||||
|
this.searchContent = "";
|
||||||
|
this.$router.push({ path: value });
|
||||||
|
},
|
||||||
|
onSearch() {
|
||||||
|
this.$router.push({
|
||||||
|
path: "/goods/list",
|
||||||
|
query: {
|
||||||
|
keyword: this.searchContent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.layout-header-popover {
|
||||||
|
&__cart-content {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sticky-bar-header {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
z-index: 10;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0px 4px 10px 1px rgba(0, 0, 0, 0.1);
|
||||||
|
&--hide-shadow {
|
||||||
|
box-shadow: none;
|
||||||
|
/deep/.el-menu {
|
||||||
|
.is-active {
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sticky-bar-header__wrap {
|
||||||
|
@include layout-box;
|
||||||
|
height: 100%;
|
||||||
|
.bar-header-wrap__logo {
|
||||||
|
width: 164px;
|
||||||
|
height: 28px;
|
||||||
|
margin-right: 50px;
|
||||||
|
}
|
||||||
|
.bar-header-wrap__icons {
|
||||||
|
cursor: pointer;
|
||||||
|
img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
.header-wrap-icons__shop {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 14px;
|
||||||
|
span {
|
||||||
|
position: absolute;
|
||||||
|
right: -6px;
|
||||||
|
top: -4px;
|
||||||
|
display: block;
|
||||||
|
height: 14px;
|
||||||
|
padding: 0 2px;
|
||||||
|
line-height: 14px;
|
||||||
|
text-align: center;
|
||||||
|
background: #ff512b;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.header-wrap-icons__login {
|
||||||
|
margin-left: 47px;
|
||||||
|
img {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.header-wrap-icons__unlogin {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #909399;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/deep/ .el-menu {
|
||||||
|
height: 50px;
|
||||||
|
color: #666666;
|
||||||
|
.is-active {
|
||||||
|
color: #ff7f39;
|
||||||
|
border-bottom: 3px solid #ff823c;
|
||||||
|
}
|
||||||
|
.el-menu-item:hover {
|
||||||
|
color: #ff7f39;
|
||||||
|
}
|
||||||
|
.el-menu-item {
|
||||||
|
height: 100%;
|
||||||
|
line-height: 50px;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0 30px;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.default-bar-header {
|
||||||
|
padding-top: 32px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
.bar-header-box {
|
||||||
|
@include layout-box;
|
||||||
|
background: #ffffff;
|
||||||
|
.bar-header-box__wrap {
|
||||||
|
height: 42px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 38px;
|
||||||
|
padding-right: 50px;
|
||||||
|
.header-box-wrap__logo {
|
||||||
|
width: 244px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.header-box-wrap__right {
|
||||||
|
.box-wrap-right__search {
|
||||||
|
margin-right: 23px;
|
||||||
|
.search-input {
|
||||||
|
width: 551px;
|
||||||
|
z-index: 1;
|
||||||
|
/deep/.el-input__inner:focus {
|
||||||
|
border-color: #ff512b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.search-icon {
|
||||||
|
width: 77px;
|
||||||
|
margin-left: -2px;
|
||||||
|
background: linear-gradient(270deg, #ffa25a 0%, #ff7f39 100%);
|
||||||
|
border-radius: 0px 8px 8px 0px;
|
||||||
|
z-index: 2;
|
||||||
|
cursor: pointer;
|
||||||
|
img {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bar-header-box__tab {
|
||||||
|
height: 38px;
|
||||||
|
.header-box-tab__common--light {
|
||||||
|
color: #ff7f39 !important;
|
||||||
|
}
|
||||||
|
.header-box-tab__common {
|
||||||
|
width: 160px;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666666;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.layout-header-line {
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background: #ff875b;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* @Author: ch
|
||||||
|
* @Date: 2022-05-03 22:14:16
|
||||||
|
* @LastEditors: ch
|
||||||
|
* @LastEditTime: 2022-05-10 14:18:39
|
||||||
|
* @Description: file content
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
// Global page headers: https://go.nuxtjs.dev/config-head
|
||||||
|
head: {
|
||||||
|
title: 'shop-pc',
|
||||||
|
htmlAttrs: {
|
||||||
|
lang: 'zh'
|
||||||
|
},
|
||||||
|
meta: [
|
||||||
|
{ charset: 'utf-8' },
|
||||||
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||||
|
{ hid: 'description', name: 'description', content: '' },
|
||||||
|
{ name: 'format-detection', content: 'telephone=no' }
|
||||||
|
],
|
||||||
|
link: [
|
||||||
|
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
extendRoutes(routes, resolve) {
|
||||||
|
routes.push({
|
||||||
|
name: 'custom',
|
||||||
|
path: '/',
|
||||||
|
component: resolve(__dirname, 'pages/index/index.vue')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Global CSS: https://go.nuxtjs.dev/config-css
|
||||||
|
css: [
|
||||||
|
'@assets/scss/global.scss',
|
||||||
|
'element-ui/lib/theme-chalk/index.css'
|
||||||
|
],
|
||||||
|
|
||||||
|
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
|
||||||
|
plugins: [
|
||||||
|
'@/plugins/element-ui',
|
||||||
|
'@/plugins/axios',
|
||||||
|
'@plugins/axiosTk.js',
|
||||||
|
'@plugins/vue-inject.js',
|
||||||
|
'@/plugins/v-distpicker',
|
||||||
|
],
|
||||||
|
|
||||||
|
// Auto import components: https://go.nuxtjs.dev/config-components
|
||||||
|
components: true,
|
||||||
|
|
||||||
|
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
|
||||||
|
buildModules: [
|
||||||
|
],
|
||||||
|
|
||||||
|
build: {
|
||||||
|
vendor: ['v-distpicker']
|
||||||
|
},
|
||||||
|
|
||||||
|
styleResources: {
|
||||||
|
scss: '@/assets/scss/global.scss'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Modules: https://go.nuxtjs.dev/config-modules
|
||||||
|
modules: [
|
||||||
|
'@nuxtjs/axios',
|
||||||
|
'cookie-universal-nuxt',
|
||||||
|
'@nuxtjs/style-resources'
|
||||||
|
],
|
||||||
|
|
||||||
|
// Build Configuration: https://go.nuxtjs.dev/config-build
|
||||||
|
build: {
|
||||||
|
transpile: [/^element-ui/],
|
||||||
|
},
|
||||||
|
axios: {
|
||||||
|
// 表示开启代理
|
||||||
|
proxy: true,
|
||||||
|
},
|
||||||
|
proxy: {
|
||||||
|
'/mall/': {
|
||||||
|
// target: 'http://114.55.64.39:3004', // 目标接口域名
|
||||||
|
target: 'https://you-gateway.mashibing.com/', // 目标接口域名
|
||||||
|
pathRewrite: {
|
||||||
|
changeOrigin: true, // 表示是否跨域
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 3000, // default: 3000
|
||||||
|
host: '0.0.0.0' // default: localhost,
|
||||||
|
},
|
||||||
|
}
|