修改搜索和隐藏品牌

master
xcw 2023-11-16 14:19:59 +08:00
parent af23d76c52
commit b6d325a110
183 changed files with 33243 additions and 81 deletions

13
pc - 副本/.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

90
pc - 副本/.gitignore vendored Normal file
View File

@ -0,0 +1,90 @@
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# 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

69
pc - 副本/README.md Normal file
View File

@ -0,0 +1,69 @@
# LikeSopb2b2c
## Build Setup
```bash
# install dependencies
$ npm install
# serve with hot reload at localhost:3000
$ npm run dev
# build for production and launch server
$ npm run build
$ npm run start
# generate static project
$ npm run generate
```
For detailed explanation on how things work, check out the [documentation](https://nuxtjs.org).
## Special Directories
You can create the following extra directories, some of which have special behaviors. Only `pages` is required; you can delete them if you don't want to use their functionality.
### `assets`
The assets directory contains your uncompiled assets such as Stylus or Sass files, images, or fonts.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/assets).
### `components`
The components directory contains your Vue.js components. Components make up the different parts of your page and can be reused and imported into your pages, layouts and even other components.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/components).
### `layouts`
Layouts are a great help when you want to change the look and feel of your Nuxt app, whether you want to include a sidebar or have distinct layouts for mobile and desktop.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/layouts).
### `pages`
This directory contains your application views and routes. Nuxt will read all the `*.vue` files inside this directory and setup Vue Router automatically.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/get-started/routing).
### `plugins`
The plugins directory contains JavaScript plugins that you want to run before instantiating the root Vue.js Application. This is the place to add Vue plugins and to inject functions or constants. Every time you need to use `Vue.use()`, you should create a file in `plugins/` and add its path to plugins in `nuxt.config.js`.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/plugins).
### `static`
This directory contains your static files. Each file inside this directory is mapped to `/`.
Example: `/static/robots.txt` is mapped as `/robots.txt`.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/static).
### `store`
This directory contains your Vuex store files. Creating a file in this directory automatically activates Vuex.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/store).

View File

@ -0,0 +1,223 @@
/** S 背景颜色 **/
.bg-primary { background-color: $--color-primary; }
.bg-white { background-color: $--color-white; }
.bg-body { background-color: $--background-color-base; }
/** E 背景颜色 **/
/** S 字体颜色 **/
.primary { color: $--color-primary; }
.black { color: $--color-black; }
.white { color: $--color-white; }
.normal { color: $--color-text-primary; }
.lighter { color: $--color-text-regular; }
.muted { color: $--color-text-secondary; }
/** E 字体颜色 **/
.border-bottom {
border-bottom: $--border-base;
}
.border-top {
border-top: $--border-base;
}
.border-left {
border-left: $--border-base;
}
.border-right {
border-right: $--border-base;
}
.border {
border: $--border-base;
}
//
@for $i from 100 through 900 {
@if $i % 100 == 0 {
.weight-#{$i} {
font-weight: $i;
}
}
}
/** S 字体大小 **/
.xxl { font-size: 18px; }
.xl { font-size: 17px; }
.lg { font-size: 16px; }
.md { font-size: 15px; }
.nr { font-size: 14px; }
.sm { font-size: 13px; }
.xs { font-size: 12px; }
.xxs { font-size: 11px; }
// [19-40]
@for $i from 19 through 50 {
.font-size-#{$i} {
font-size: $i + px;
}
}
/** E 字体大小 **/
// [1-60]
@for $i from 0 through 60 {
// 5
@if $i % 2 == 0 or $i % 5 == 0 {
// m-30
.m-#{$i} {
margin: $i + px;
}
// p-30
.p-#{$i} {
padding: $i + px;
}
@each $short, $long in l left, t top, r right, b bottom {
// m-l-6
//
.m-#{$short}-#{$i} {
margin-#{$long}: $i + px;
}
// p-l-30
//
.p-#{$short}-#{$i} {
padding-#{$long}: $i + px;
}
}
}
}
//
.inline { display: inline-block; }
//
.block { display: block; }
//
.pointer { cursor: pointer }
/** S 弹性布局 **/
.flex {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
}
.flex-col {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
// flex
@for $i from 0 through 5 {
.flex-#{$i} {
flex: $i;
}
}
.flex-none { flex: none; }
.flex-wrap { flex-wrap: wrap; }
.flex-nowrap { flex-wrap: nowrap; }
.col-baseline { align-items: baseline; }
.col-center { align-items: center; }
.col-top { align-items: flex-start; }
.col-bottom { align-items: flex-end; }
.col-stretch { align-items:stretch; }
.row-center { justify-content: center; }
.row-left { justify-content: flex-start; }
.row-right { justify-content: flex-end; }
.row-between { justify-content: space-between; }
.row-around { justify-content: space-around; }
/** E 弹性布局 **/
/** S 内容排序方式 **/
.text-left { text-align: left; }
.text-center { text-align: center; }
.text-right { text-align: right; }
/** E 内容排序方式 **/
/** S 文本行数限制 **/
.line-1 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.line-2 { -webkit-line-clamp: 2; }
.line-3 { -webkit-line-clamp: 3; }
.line-4 { -webkit-line-clamp: 4; }
.line-5 { -webkit-line-clamp: 5; }
.line-2, .line-3, .line-4, .line-5 {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box; //
-webkit-box-orient: vertical; //
}
/** E 文本行数限制 **/
/* 中划线 */
.line-through {
text-decoration: line-through;
}
.clearfix:after{
content: "";
display: block;
clear: both;
visibility: hidden;
}
.wrapper1180 {
width: 1180px;
margin: 0 auto;
}

View File

@ -0,0 +1,985 @@
/* Transition
-------------------------- */
$--all-transition: all .3s cubic-bezier(.645,.045,.355,1) !default;
$--fade-transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
$--fade-linear-transition: opacity 200ms linear !default;
$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
$--border-transition-base: border-color .2s cubic-bezier(.645,.045,.355,1) !default;
$--color-transition-base: color .2s cubic-bezier(.645,.045,.355,1) !default;
/* Color
-------------------------- */
/// color|1|Brand Color|0
$--color-primary: #FF2C3C !default;
/// color|1|Background Color|4
$--color-white: #FFFFFF !default;
/// color|1|Background Color|4
$--color-black: #333333 !default;
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
/// color|1|Functional Color|1
$--color-success: #67c23a !default;
/// color|1|Functional Color|1
$--color-warning: #FB9400 !default;
/// color|1|Functional Color|1
$--color-danger: #F56C6C !default;
/// color|1|Functional Color|1
$--color-info: #909399 !default;
$--color-success-light: mix($--color-white, $--color-success, 80%) !default;
$--color-warning-light: mix($--color-white, $--color-warning, 80%) !default;
$--color-danger-light: mix($--color-white, $--color-danger, 80%) !default;
$--color-info-light: mix($--color-white, $--color-info, 80%) !default;
$--color-success-lighter: mix($--color-white, $--color-success, 90%) !default;
$--color-warning-lighter: mix($--color-white, $--color-warning, 90%) !default;
$--color-danger-lighter: mix($--color-white, $--color-danger, 90%) !default;
$--color-info-lighter: mix($--color-white, $--color-info, 90%) !default;
/// color|1|Font Color|2
$--color-text-primary: #333333 !default;
/// color|1|Font Color|2
$--color-text-regular: #666666 !default;
/// color|1|Font Color|2
$--color-text-secondary: #999999 !default;
/// color|1|Font Color|2
$--color-text-placeholder: #999999 !default;
/// color|1|Border Color|3
$--border-color-base: #E5E5E5E5 !default;
/// color|1|Border Color|3
$--border-color-light: #f2f2f2f2!default;
/// color|1|Border Color|3
$--border-color-lighter: #f5f5f5 !default;
/// color|1|Border Color|3
$--border-color-extra-light: #f5f5f5 !default;
// Background
/// color|1|Background Color|4
$--background-color-base: #F5F7F9 !default;
/* Link
-------------------------- */
$--link-color: $--color-primary-light-2 !default;
$--link-hover-color: $--color-primary !default;
/* Border
-------------------------- */
$--border-width-base: 1px !default;
$--border-style-base: solid !default;
$--border-color-hover: $--color-primary!default;
$--border-base: $--border-width-base $--border-style-base $--border-color-base !default;
/// borderRadius|1|Radius|0
$--border-radius-base: 4px !default;
/// borderRadius|1|Radius|0
$--border-radius-small: 2px !default;
/// borderRadius|1|Radius|0
$--border-radius-circle: 100% !default;
/// borderRadius|1|Radius|0
$--border-radius-zero: 0 !default;
// Box-shadow
/// boxShadow|1|Shadow|1
$--box-shadow-base: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04) !default;
// boxShadow|1|Shadow|1
$--box-shadow-dark: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12) !default;
/// boxShadow|1|Shadow|1
$--box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !default;
/* Fill
-------------------------- */
$--fill-base: $--color-white !default;
/* Typography
-------------------------- */
$--font-path: 'fonts' !default;
$--font-display: 'auto' !default;
/// fontSize|1|Font Size|0
$--font-size-extra-large: 17px !default;
/// fontSize|1|Font Size|0
$--font-size-large: 16px !default;
/// fontSize|1|Font Size|0
$--font-size-medium: 15px !default;
/// fontSize|1|Font Size|0
$--font-size-base: 14px !default;
/// fontSize|1|Font Size|0
$--font-size-small: 12px !default;
/// fontSize|1|Font Size|0
$--font-size-extra-small: 12px !default;
/// fontWeight|1|Font Weight|1
$--font-weight-primary: 500 !default;
/// fontWeight|1|Font Weight|1
$--font-weight-secondary: 100 !default;
/// fontLineHeight|1|Line Height|2
$--font-line-height-primary: 24px !default;
/// fontLineHeight|1|Line Height|2
$--font-line-height-secondary: 16px !default;
$--font-color-disabled-base: #bbb !default;
/* Size
-------------------------- */
$--size-base: 12px !default;
/* z-index
-------------------------- */
$--index-normal: 1 !default;
$--index-top: 1000 !default;
$--index-popper: 2000 !default;
/* Disable base
-------------------------- */
$--disabled-fill-base: $--background-color-base !default;
$--disabled-color-base: $--color-text-placeholder !default;
$--disabled-border-base: $--border-color-light !default;
/* Icon
-------------------------- */
$--icon-color: #666 !default;
$--icon-color-base: $--color-info !default;
/* Checkbox
-------------------------- */
/// fontSize||Font|1
$--checkbox-font-size: $--font-size-base !default;
/// fontWeight||Font|1
$--checkbox-font-weight: 400 !default;
/// color||Color|0
$--checkbox-font-color: $--color-text-primary !default;
$--checkbox-input-height: 14px !default;
$--checkbox-input-width: 14px !default;
/// borderRadius||Border|2
$--checkbox-border-radius: $--border-radius-small !default;
/// color||Color|0
$--checkbox-background-color: $--color-white !default;
$--checkbox-input-border: $--border-base !default;
/// color||Color|0
$--checkbox-disabled-border-color: $--border-color-base !default;
$--checkbox-disabled-input-fill: #edf2fc !default;
$--checkbox-disabled-icon-color: $--color-text-placeholder !default;
$--checkbox-disabled-checked-input-fill: $--border-color-extra-light !default;
$--checkbox-disabled-checked-input-border-color: $--border-color-base !default;
$--checkbox-disabled-checked-icon-color: $--color-text-placeholder !default;
/// color||Color|0
$--checkbox-checked-font-color: $--color-primary !default;
$--checkbox-checked-input-border-color: $--color-primary !default;
/// color||Color|0
$--checkbox-checked-background-color: $--color-primary !default;
$--checkbox-checked-icon-color: $--fill-base !default;
$--checkbox-input-border-color-hover: $--color-primary !default;
/// height||Other|4
$--checkbox-bordered-height: 40px !default;
/// padding||Spacing|3
$--checkbox-bordered-padding: 9px 20px 9px 10px !default;
/// padding||Spacing|3
$--checkbox-bordered-medium-padding: 7px 20px 7px 10px !default;
/// padding||Spacing|3
$--checkbox-bordered-small-padding: 5px 15px 5px 10px !default;
/// padding||Spacing|3
$--checkbox-bordered-mini-padding: 3px 15px 3px 10px !default;
$--checkbox-bordered-medium-input-height: 14px !default;
$--checkbox-bordered-medium-input-width: 14px !default;
/// height||Other|4
$--checkbox-bordered-medium-height: 36px !default;
$--checkbox-bordered-small-input-height: 12px !default;
$--checkbox-bordered-small-input-width: 12px !default;
/// height||Other|4
$--checkbox-bordered-small-height: 32px !default;
$--checkbox-bordered-mini-input-height: 12px !default;
$--checkbox-bordered-mini-input-width: 12px !default;
/// height||Other|4
$--checkbox-bordered-mini-height: 28px !default;
/// color||Color|0
$--checkbox-button-checked-background-color: $--color-primary !default;
/// color||Color|0
$--checkbox-button-checked-font-color: $--color-white !default;
/// color||Color|0
$--checkbox-button-checked-border-color: $--color-primary !default;
/* Radio
-------------------------- */
/// fontSize||Font|1
$--radio-font-size: $--font-size-base !default;
/// fontWeight||Font|1
$--radio-font-weight: 400 !default;
/// color||Color|0
$--radio-font-color: $--color-text-primary !default;
$--radio-input-height: 14px !default;
$--radio-input-width: 14px !default;
/// borderRadius||Border|2
$--radio-input-border-radius: $--border-radius-circle !default;
/// color||Color|0
$--radio-input-background-color: $--color-white !default;
$--radio-input-border: $--border-base !default;
/// color||Color|0
$--radio-input-border-color: $--border-color-base !default;
/// color||Color|0
$--radio-icon-color: $--color-white !default;
$--radio-disabled-input-border-color: $--disabled-border-base !default;
$--radio-disabled-input-fill: $--disabled-fill-base !default;
$--radio-disabled-icon-color: $--disabled-fill-base !default;
$--radio-disabled-checked-input-border-color: $--disabled-border-base !default;
$--radio-disabled-checked-input-fill: $--disabled-fill-base !default;
$--radio-disabled-checked-icon-color: $--color-text-placeholder !default;
/// color||Color|0
$--radio-checked-font-color: $--color-primary !default;
/// color||Color|0
$--radio-checked-input-border-color: $--color-primary !default;
/// color||Color|0
$--radio-checked-input-background-color: $--color-white !default;
/// color||Color|0
$--radio-checked-icon-color: $--color-primary !default;
$--radio-input-border-color-hover: $--color-primary !default;
$--radio-bordered-height: 40px !default;
$--radio-bordered-padding: 12px 20px 0 10px !default;
$--radio-bordered-medium-padding: 10px 20px 0 10px !default;
$--radio-bordered-small-padding: 8px 15px 0 10px !default;
$--radio-bordered-mini-padding: 6px 15px 0 10px !default;
$--radio-bordered-medium-input-height: 14px !default;
$--radio-bordered-medium-input-width: 14px !default;
$--radio-bordered-medium-height: 36px !default;
$--radio-bordered-small-input-height: 12px !default;
$--radio-bordered-small-input-width: 12px !default;
$--radio-bordered-small-height: 32px !default;
$--radio-bordered-mini-input-height: 12px !default;
$--radio-bordered-mini-input-width: 12px !default;
$--radio-bordered-mini-height: 28px !default;
/// fontSize||Font|1
$--radio-button-font-size: $--font-size-base !default;
/// color||Color|0
$--radio-button-checked-background-color: $--color-primary !default;
/// color||Color|0
$--radio-button-checked-font-color: $--color-white !default;
/// color||Color|0
$--radio-button-checked-border-color: $--color-primary !default;
$--radio-button-disabled-checked-fill: $--border-color-extra-light !default;
/* Select
-------------------------- */
$--select-border-color-hover: $--border-color-hover !default;
$--select-disabled-border: $--disabled-border-base !default;
/// fontSize||Font|1
$--select-font-size: $--font-size-base !default;
$--select-close-hover-color: $--color-text-secondary !default;
$--select-input-color: $--color-text-placeholder !default;
$--select-multiple-input-color: #666 !default;
/// color||Color|0
$--select-input-focus-border-color: $--color-primary !default;
/// fontSize||Font|1
$--select-input-font-size: $--font-size-base !default;
$--select-option-color: $--color-text-regular !default;
$--select-option-disabled-color: $--color-text-placeholder !default;
$--select-option-disabled-background: $--color-white !default;
/// height||Other|4
$--select-option-height: 34px !default;
$--select-option-hover-background: $--background-color-base !default;
/// color||Color|0
$--select-option-selected-font-color: $--color-primary !default;
$--select-option-selected-hover: $--background-color-base !default;
$--select-group-color: $--color-info !default;
$--select-group-height: 30px !default;
$--select-group-font-size: $--font-size-base !default;
$--select-dropdown-background: $--color-white !default;
$--select-dropdown-shadow: $--box-shadow-light !default;
$--select-dropdown-empty-color: #999 !default;
/// height||Other|4
$--select-dropdown-max-height: 274px !default;
$--select-dropdown-padding: 6px 0 !default;
$--select-dropdown-empty-padding: 10px 0 !default;
$--select-dropdown-border: solid 1px $--border-color-light !default;
/* Alert
-------------------------- */
$--alert-padding: 8px 16px !default;
/// borderRadius||Border|2
$--alert-border-radius: $--border-radius-base !default;
/// fontSize||Font|1
$--alert-title-font-size: $--font-size-base !default;
/// fontSize||Font|1
$--alert-description-font-size: $--font-size-base !default;
/// fontSize||Font|1
$--alert-close-font-size: $--font-size-base !default;
/// fontSize||Font|1
$--alert-close-customed-font-size: $--font-size-base !default;
$--alert-success-color: $--color-success-lighter !default;
$--alert-info-color: $--color-info-lighter !default;
$--alert-warning-color: $--color-warning-lighter !default;
$--alert-danger-color: $--color-danger-lighter !default;
/// height||Other|4
$--alert-icon-size: 16px !default;
/// height||Other|4
$--alert-icon-large-size: 28px !default;
/* MessageBox
-------------------------- */
/// color||Color|0
$--messagebox-title-color: $--color-text-primary !default;
$--msgbox-width: 420px !default;
$--msgbox-border-radius: 4px !default;
/// fontSize||Font|1
$--messagebox-font-size: $--font-size-large !default;
/// fontSize||Font|1
$--messagebox-content-font-size: $--font-size-base !default;
/// color||Color|0
$--messagebox-content-color: $--color-text-regular !default;
/// fontSize||Font|1
$--messagebox-error-font-size: 12px !default;
$--msgbox-padding-primary: 15px !default;
/// color||Color|0
$--messagebox-success-color: $--color-success !default;
/// color||Color|0
$--messagebox-info-color: $--color-info !default;
/// color||Color|0
$--messagebox-warning-color: $--color-warning !default;
/// color||Color|0
$--messagebox-danger-color: $--color-danger !default;
/* Message
-------------------------- */
$--message-shadow: $--box-shadow-base !default;
$--message-min-width: 380px !default;
$--message-background-color: #edf2fc !default;
$--message-padding: 15px 15px 15px 20px !default;
/// color||Color|0
$--message-close-icon-color: $--color-text-placeholder !default;
/// height||Other|4
$--message-close-size: 16px !default;
/// color||Color|0
$--message-close-hover-color: $--color-text-secondary !default;
/// color||Color|0
$--message-success-font-color: $--color-success !default;
/// color||Color|0
$--message-info-font-color: $--color-info !default;
/// color||Color|0
$--message-warning-font-color: $--color-warning !default;
/// color||Color|0
$--message-danger-font-color: $--color-danger !default;
/* Notification
-------------------------- */
$--notification-width: 330px !default;
/// padding||Spacing|3
$--notification-padding: 14px 26px 14px 13px !default;
$--notification-radius: 8px !default;
$--notification-shadow: $--box-shadow-light !default;
/// color||Color|0
$--notification-border-color: $--border-color-lighter !default;
$--notification-icon-size: 24px !default;
$--notification-close-font-size: $--message-close-size !default;
$--notification-group-margin-left: 13px !default;
$--notification-group-margin-right: 8px !default;
/// fontSize||Font|1
$--notification-content-font-size: $--font-size-base !default;
/// color||Color|0
$--notification-content-color: $--color-text-regular !default;
/// fontSize||Font|1
$--notification-title-font-size: 16px !default;
/// color||Color|0
$--notification-title-color: $--color-text-primary !default;
/// color||Color|0
$--notification-close-color: $--color-text-secondary !default;
/// color||Color|0
$--notification-close-hover-color: $--color-text-regular !default;
/// color||Color|0
$--notification-success-icon-color: $--color-success !default;
/// color||Color|0
$--notification-info-icon-color: $--color-info !default;
/// color||Color|0
$--notification-warning-icon-color: $--color-warning !default;
/// color||Color|0
$--notification-danger-icon-color: $--color-danger !default;
/* Input
-------------------------- */
$--input-font-size: $--font-size-base !default;
/// color||Color|0
$--input-font-color: $--color-text-regular !default;
/// height||Other|4
$--input-width: 140px !default;
/// height||Other|4
$--input-height: 40px !default;
$--input-border: $--border-base !default;
$--input-border-color: $--border-color-base !default;
/// borderRadius||Border|2
$--input-border-radius: $--border-radius-base !default;
$--input-border-color-hover: $--border-color-hover !default;
/// color||Color|0
$--input-background-color: $--color-white !default;
$--input-fill-disabled: $--disabled-fill-base !default;
$--input-color-disabled: $--font-color-disabled-base !default;
/// color||Color|0
$--input-icon-color: $--color-text-placeholder !default;
/// color||Color|0
$--input-placeholder-color: $--color-text-placeholder !default;
$--input-max-width: 314px !default;
$--input-hover-border: $--border-color-hover !default;
$--input-clear-hover-color: $--color-text-secondary !default;
$--input-focus-border: $--color-primary !default;
$--input-focus-fill: $--color-white !default;
$--input-disabled-fill: $--disabled-fill-base !default;
$--input-disabled-border: $--disabled-border-base !default;
$--input-disabled-color: $--disabled-color-base !default;
$--input-disabled-placeholder-color: $--color-text-placeholder !default;
/// fontSize||Font|1
$--input-medium-font-size: 14px !default;
/// height||Other|4
$--input-medium-height: 36px !default;
/// fontSize||Font|1
$--input-small-font-size: $--font-size-small !default;
/// height||Other|4
$--input-small-height: 32px !default;
/// fontSize||Font|1
$--input-mini-font-size: 12px !default;
/// height||Other|4
$--input-mini-height: 28px !default;
/* Cascader
-------------------------- */
/// color||Color|0
$--cascader-menu-font-color: $--color-text-regular !default;
/// color||Color|0
$--cascader-menu-selected-font-color: $--color-primary !default;
$--cascader-menu-fill: $--fill-base !default;
$--cascader-menu-font-size: $--font-size-base !default;
$--cascader-menu-radius: $--border-radius-base !default;
$--cascader-menu-border: solid 1px $--border-color-light !default;
$--cascader-menu-shadow: $--box-shadow-light !default;
$--cascader-node-background-hover: $--background-color-base !default;
$--cascader-node-color-disabled:$--color-text-placeholder !default;
$--cascader-color-empty:$--color-text-placeholder !default;
$--cascader-tag-background: #f0f2f5;
/* Group
-------------------------- */
$--group-option-flex: 0 0 (1/5) * 100% !default;
$--group-option-offset-bottom: 12px !default;
$--group-option-fill-hover: rgba($--color-black, 0.06) !default;
$--group-title-color: $--color-black !default;
$--group-title-font-size: $--font-size-base !default;
$--group-title-width: 66px !default;
/* Tab
-------------------------- */
$--tab-font-size: $--font-size-medium !default;
$--tab-border-line: 1px solid #e4e4e4 !default;
$--tab-header-color-active: $--color-text-secondary !default;
$--tab-header-color-hover: $--color-text-regular !default;
$--tab-header-color: $--color-text-regular !default;
$--tab-header-fill-active: rgba($--color-black, 0.06) !default;
$--tab-header-fill-hover: rgba($--color-black, 0.06) !default;
$--tab-vertical-header-width: 90px !default;
$--tab-vertical-header-count-color: $--color-white !default;
$--tab-vertical-header-count-fill: $--color-text-secondary !default;
/* Button
-------------------------- */
/// fontSize||Font|1
$--button-font-size: 14px !default;
/// fontWeight||Font|1
$--button-font-weight: 400 !default;
/// borderRadius||Border|2
$--button-border-radius: $--border-radius-base !default;
/// padding||Spacing|3
$--button-padding-vertical: 12px !default;
/// padding||Spacing|3
$--button-padding-horizontal: 20px !default;
/// fontSize||Font|1
$--button-medium-font-size: 13px !default;
/// borderRadius||Border|2
$--button-medium-border-radius: $--border-radius-base !default;
/// padding||Spacing|3
$--button-medium-padding-vertical: 10px !default;
/// padding||Spacing|3
$--button-medium-padding-horizontal: 20px !default;
/// fontSize||Font|1
$--button-small-font-size: 12px !default;
$--button-small-border-radius: #{$--border-radius-base - 1} !default;
/// padding||Spacing|3
$--button-small-padding-vertical: 9px !default;
/// padding||Spacing|3
$--button-small-padding-horizontal: 15px !default;
/// fontSize||Font|1
$--button-mini-font-size: 12px !default;
$--button-mini-border-radius: #{$--border-radius-base - 1} !default;
/// padding||Spacing|3
$--button-mini-padding-vertical: 7px !default;
/// padding||Spacing|3
$--button-mini-padding-horizontal: 12px !default;
/// color||Color|0
$--button-default-font-color: $--color-text-regular !default;
/// color||Color|0
$--button-default-background-color: $--color-white !default;
/// color||Color|0
$--button-default-border-color: $--border-color-base !default;
/// color||Color|0
$--button-disabled-font-color: $--color-text-placeholder !default;
/// color||Color|0
$--button-disabled-background-color: $--color-white !default;
/// color||Color|0
$--button-disabled-border-color: $--border-color-lighter !default;
/// color||Color|0
$--button-primary-border-color: $--color-primary !default;
/// color||Color|0
$--button-primary-font-color: $--color-white !default;
/// color||Color|0
$--button-primary-background-color: $--color-primary !default;
/// color||Color|0
$--button-success-border-color: $--color-success !default;
/// color||Color|0
$--button-success-font-color: $--color-white !default;
/// color||Color|0
$--button-success-background-color: $--color-success !default;
/// color||Color|0
$--button-warning-border-color: $--color-warning !default;
/// color||Color|0
$--button-warning-font-color: $--color-white !default;
/// color||Color|0
$--button-warning-background-color: $--color-warning !default;
/// color||Color|0
$--button-danger-border-color: $--color-danger !default;
/// color||Color|0
$--button-danger-font-color: $--color-white !default;
/// color||Color|0
$--button-danger-background-color: $--color-danger !default;
/// color||Color|0
$--button-info-border-color: $--color-info !default;
/// color||Color|0
$--button-info-font-color: $--color-white !default;
/// color||Color|0
$--button-info-background-color: $--color-info !default;
$--button-hover-tint-percent: 20% !default;
$--button-active-shade-percent: 10% !default;
/* cascader
-------------------------- */
$--cascader-height: 200px !default;
/* Switch
-------------------------- */
/// color||Color|0
$--switch-on-color: $--color-primary !default;
/// color||Color|0
$--switch-off-color: $--border-color-base !default;
/// fontSize||Font|1
$--switch-font-size: $--font-size-base !default;
$--switch-core-border-radius: 10px !default;
// height||Other|4 TODO: width 40px
$--switch-width: 36px !default;
// height||Other|4
$--switch-height: 18px !default;
// height||Other|4
$--switch-button-size: 14px !default;
/* Dialog
-------------------------- */
$--dialog-background-color: $--color-white !default;
$--dialog-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) !default;
/// fontSize||Font|1
$--dialog-title-font-size: $--font-size-large !default;
/// fontSize||Font|1
$--dialog-content-font-size: $--font-size-base !default;
/// fontLineHeight||LineHeight|2
$--dialog-font-line-height: $--font-line-height-primary !default;
/// padding||Spacing|3
$--dialog-padding-primary: 20px !default;
/* Table
-------------------------- */
/// color||Color|0
$--table-border-color: $--border-color-light !default;
$--table-border: 1px solid $--table-border-color !default;
/// color||Color|0
$--table-font-color: $--color-text-primary !default;
/// color||Color|0
$--table-header-font-color: $--color-text-primary !default;
/// color||Color|0
$--table-row-hover-background-color: #F5F8FF !default;
$--table-current-row-background-color: $--color-primary-light-9 !default;
/// color||Color|0
$--table-header-background-color: $--color-white !default;
$--table-fixed-box-shadow: 0 0 10px rgba(0, 0, 0, .12) !default;
/* Pagination
-------------------------- */
/// fontSize||Font|1
$--pagination-font-size: $--font-size-base !default;
/// color||Color|0
$--pagination-background-color: $--color-white !default;
/// color||Color|0
$--pagination-font-color: $--color-text-primary !default;
$--pagination-border-radius: 3px !default;
/// color||Color|0
$--pagination-button-color: $--color-text-primary !default;
/// height||Other|4
$--pagination-button-width: 35.5px !default;
/// height||Other|4
$--pagination-button-height: 28px !default;
/// color||Color|0
$--pagination-button-disabled-color: $--color-text-placeholder !default;
/// color||Color|0
$--pagination-button-disabled-background-color: $--color-white !default;
/// color||Color|0
$--pagination-hover-color: $--color-primary !default;
/* Popup
-------------------------- */
/// color||Color|0
$--popup-modal-background-color: $--color-black !default;
/// opacity||Other|1
$--popup-modal-opacity: 0.5 !default;
/* Popover
-------------------------- */
/// color||Color|0
$--popover-background-color: $--color-white !default;
/// fontSize||Font|1
$--popover-font-size: $--font-size-base !default;
/// color||Color|0
$--popover-border-color: $--border-color-lighter !default;
$--popover-arrow-size: 6px !default;
/// padding||Spacing|3
$--popover-padding: 12px !default;
$--popover-padding-large: 18px 20px !default;
/// fontSize||Font|1
$--popover-title-font-size: $--font-size-medium !default;
/// color||Color|0
$--popover-title-font-color: $--color-text-primary !default;
/* Tooltip
-------------------------- */
/// color|1|Color|0
$--tooltip-fill: $--color-text-primary !default;
/// color|1|Color|0
$--tooltip-color: $--color-white !default;
/// fontSize||Font|1
$--tooltip-font-size: 12px !default;
/// color||Color|0
$--tooltip-border-color: $--color-text-primary !default;
$--tooltip-arrow-size: 6px !default;
/// padding||Spacing|3
$--tooltip-padding: 10px !default;
/* Tag
-------------------------- */
/// color||Color|0
$--tag-info-color: $--color-info !default;
/// color||Color|0
$--tag-primary-color: $--color-primary !default;
/// color||Color|0
$--tag-success-color: $--color-success !default;
/// color||Color|0
$--tag-warning-color: $--color-warning !default;
/// color||Color|0
$--tag-danger-color: $--color-danger !default;
/// fontSize||Font|1
$--tag-font-size: 12px !default;
$--tag-border-radius: 4px !default;
$--tag-padding: 0 10px !default;
/* Tree
-------------------------- */
/// color||Color|0
$--tree-node-hover-background-color: $--background-color-base !default;
/// color||Color|0
$--tree-font-color: $--color-text-regular !default;
/// color||Color|0
$--tree-expand-icon-color: $--color-text-placeholder !default;
/* Dropdown
-------------------------- */
$--dropdown-menu-box-shadow: $--box-shadow-light !default;
$--dropdown-menuItem-hover-fill: $--color-primary-light-9 !default;
$--dropdown-menuItem-hover-color: $--link-color !default;
/* Badge
-------------------------- */
/// color||Color|0
$--badge-background-color: $--color-danger !default;
$--badge-radius: 10px !default;
/// fontSize||Font|1
$--badge-font-size: 12px !default;
/// padding||Spacing|3
$--badge-padding: 6px !default;
/// height||Other|4
$--badge-size: 18px !default;
/* Card
--------------------------*/
/// color||Color|0
$--card-border-color: $--border-color-light !default;
$--card-border-radius: 4px !default;
/// padding||Spacing|3
$--card-padding: 20px !default;
/* Slider
--------------------------*/
/// color||Color|0
$--slider-main-background-color: $--color-primary !default;
/// color||Color|0
$--slider-runway-background-color: $--border-color-light !default;
$--slider-button-hover-color: mix($--color-primary, black, 97%) !default;
$--slider-stop-background-color: $--color-white !default;
$--slider-disable-color: $--color-text-placeholder !default;
$--slider-margin: 16px 0 !default;
$--slider-border-radius: 3px !default;
/// height|1|Other|4
$--slider-height: 6px !default;
/// height||Other|4
$--slider-button-size: 10px !default;
$--slider-button-wrapper-size: 36px !default;
$--slider-button-wrapper-offset: -15px !default;
/* Steps
--------------------------*/
$--steps-border-color: $--disabled-border-base !default;
$--steps-border-radius: 4px !default;
$--steps-padding: 20px !default;
/* Menu
--------------------------*/
/// fontSize||Font|1
$--menu-item-font-size: $--font-size-base !default;
/// color||Color|0
$--menu-item-font-color: $--color-text-primary !default;
/// color||Color|0
$--menu-background-color: $--color-white !default;
$--menu-item-hover-fill: $--color-primary-light-9 !default;
/* Rate
--------------------------*/
$--rate-height: 20px !default;
/// fontSize||Font|1
$--rate-font-size: $--font-size-base !default;
/// height||Other|3
$--rate-icon-size: 18px !default;
/// margin||Spacing|2
$--rate-icon-margin: 6px !default;
$--rate-icon-color: $--color-text-placeholder !default;
/* DatePicker
--------------------------*/
$--datepicker-font-color: $--color-text-regular !default;
/// color|1|Color|0
$--datepicker-off-font-color: $--color-text-placeholder !default;
/// color||Color|0
$--datepicker-header-font-color: $--color-text-regular !default;
$--datepicker-icon-color: $--color-text-primary !default;
$--datepicker-border-color: $--disabled-border-base !default;
$--datepicker-inner-border-color: #e4e4e4 !default;
/// color||Color|0
$--datepicker-inrange-background-color: $--border-color-extra-light !default;
/// color||Color|0
$--datepicker-inrange-hover-background-color: $--border-color-extra-light !default;
/// color||Color|0
$--datepicker-active-color: $--color-primary !default;
/// color||Color|0
$--datepicker-hover-font-color: $--color-primary !default;
$--datepicker-cell-hover-color: #fff !default;
/* Loading
--------------------------*/
/// height||Other|4
$--loading-spinner-size: 42px !default;
/// height||Other|4
$--loading-fullscreen-spinner-size: 50px !default;
/* Scrollbar
--------------------------*/
$--scrollbar-background-color: rgba($--color-text-secondary, .3) !default;
$--scrollbar-hover-background-color: rgba($--color-text-secondary, .5) !default;
/* Carousel
--------------------------*/
/// fontSize||Font|1
$--carousel-arrow-font-size: 12px !default;
$--carousel-arrow-size: 36px !default;
$--carousel-arrow-background: rgba(31, 45, 61, 0.11) !default;
$--carousel-arrow-hover-background: rgba(31, 45, 61, 0.23) !default;
/// width||Other|4
$--carousel-indicator-width: 30px !default;
/// height||Other|4
$--carousel-indicator-height: 2px !default;
$--carousel-indicator-padding-horizontal: 4px !default;
$--carousel-indicator-padding-vertical: 12px !default;
$--carousel-indicator-out-color: $--border-color-hover !default;
/* Collapse
--------------------------*/
/// color||Color|0
$--collapse-border-color: $--border-color-lighter !default;
/// height||Other|4
$--collapse-header-height: 48px !default;
/// color||Color|0
$--collapse-header-background-color: $--color-white !default;
/// color||Color|0
$--collapse-header-font-color: $--color-text-primary !default;
/// fontSize||Font|1
$--collapse-header-font-size: 12px !default;
/// color||Color|0
$--collapse-content-background-color: $--color-white !default;
/// fontSize||Font|1
$--collapse-content-font-size: 12px !default;
/// color||Color|0
$--collapse-content-font-color: $--color-text-primary !default;
/* Transfer
--------------------------*/
$--transfer-border-color: $--border-color-lighter !default;
$--transfer-border-radius: $--border-radius-base !default;
/// height||Other|4
$--transfer-panel-width: 200px !default;
/// height||Other|4
$--transfer-panel-header-height: 40px !default;
/// color||Color|0
$--transfer-panel-header-background-color: $--background-color-base !default;
/// height||Other|4
$--transfer-panel-footer-height: 40px !default;
/// height||Other|4
$--transfer-panel-body-height: 246px !default;
/// height||Other|4
$--transfer-item-height: 30px !default;
/// height||Other|4
$--transfer-filter-height: 32px !default;
/* Header
--------------------------*/
$--header-padding: 0 20px !default;
/* Footer
--------------------------*/
$--footer-padding: 0 20px !default;
/* Main
--------------------------*/
$--main-padding: 20px !default;
/* Timeline
--------------------------*/
$--timeline-node-size-normal: 12px !default;
$--timeline-node-size-large: 14px !default;
$--timeline-node-color: $--border-color-light !default;
/* Backtop
--------------------------*/
/// color||Color|0
$--backtop-background-color: $--color-white !default;
/// color||Color|0
$--backtop-font-color: $--color-primary !default;
/// color||Color|0
$--backtop-hover-background-color: $--border-color-extra-light !default;
/* Link
--------------------------*/
/// fontSize||Font|1
$--link-font-size: $--font-size-base !default;
/// fontWeight||Font|1
$--link-font-weight: $--font-weight-primary !default;
/// color||Color|0
$--link-default-font-color: $--color-text-regular !default;
/// color||Color|0
$--link-default-active-color: $--color-primary !default;
/// color||Color|0
$--link-disabled-font-color: $--color-text-placeholder !default;
/// color||Color|0
$--link-primary-font-color: $--color-primary !default;
/// color||Color|0
$--link-success-font-color: $--color-success !default;
/// color||Color|0
$--link-warning-font-color: $--color-warning !default;
/// color||Color|0
$--link-danger-font-color: $--color-danger !default;
/// color||Color|0
$--link-info-font-color: $--color-info !default;
/* Calendar
--------------------------*/
/// border||Other|4
$--calendar-border: $--table-border !default;
/// color||Other|4
$--calendar-selected-background-color: #F2F8FE !default;
$--calendar-cell-width: 85px !default;
/* Form
-------------------------- */
/// fontSize||Font|1
$--form-label-font-size: $--font-size-base !default;
/* Avatar
--------------------------*/
/// color||Color|0
$--avatar-font-color: #fff !default;
/// color||Color|0
$--avatar-background-color: #C0C4CC !default;
/// fontSize||Font Size|1
$--avatar-text-font-size: 12px !default;
/// fontSize||Font Size|1
$--avatar-icon-font-size: 14px !default;
/// borderRadius||Border|2
$--avatar-border-radius: $--border-radius-base !default;
/// size|1|Avatar Size|3
$--avatar-large-size: 40px !default;
/// size|1|Avatar Size|3
$--avatar-medium-size: 36px !default;
/// size|1|Avatar Size|3
$--avatar-small-size: 28px !default;
/* Empty
-------------------------- */
$--empty-padding: 40px 0 !default;
$--empty-image-width: 160px !default;
$--empty-description-margin-top: 20px !default;
$--empty-bottom-margin-top: 20px !default;
/* Skeleton
--------------------------*/
$--skeleton-color: #f2f2f2 !default;
$--skeleton-to-color: #e6e6e6 !default;
/* Svg
--------------- */
$--svg-monochrome-grey: #DCDDE0 !default;
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";

View File

@ -0,0 +1,45 @@
.el-tabs {
.el-tabs__nav-wrap::after {
height: 1px;
}
.el-tabs__nav-scroll {
padding-left: 20px;
.el-tabs__item {
font-weight: normal;
font-size: 16px;
line-height: 45px;
height: 45px;
}
}
}
.el-message-box__message {
white-space: pre-line;
}
body .el-tabs__content {
overflow: inherit;
}
body .el-popover {
min-width: 80px;
}
.pagination .el-pagination.is-background .btn-prev,
.pagination .el-pagination.is-background .btn-next,
.pagination .el-pagination.is-background .el-pager li {
background: #fff;
padding: 0 10px;
}
.el-carousel {
.el-carousel__arrow {
width: 40 px;
height: 40 px;
background-color: rgba(0, 0, 0, 0.3);
font-size: 22px;
}
}

View File

@ -0,0 +1,47 @@
body {
/* 定义一些主题色及基础样式 */
font-family: PingFang SC, Arial, Hiragino Sans GB, Microsoft YaHei, sans-serif;
margin: 0;
padding: 0;
font-size: 14px;
background-color: $--background-color-base;
font-weight: 400;
color: $--color-text-primary;
line-height: 1.3;
}
*, :after, :before {
box-sizing: border-box;
}
button, input {
font-family: PingFang SC, Arial, Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-size: 14px;
outline: none;
border: none;
}
ul,li,ol {
margin:0;
padding:0;
list-style: none;
}
// numberinput
/* 谷歌 */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
appearance: none;
margin: 0;
}
/* 火狐 */
input{
-moz-appearance:textfield;
}
a {
color: unset;
text-decoration: none;
}

View File

@ -0,0 +1,50 @@
/* Color
-------------------------- */
/// color|1|Brand Color|0
$--color-primary: #FF2C3C !default;
/// color|1|Background Color|4
$--color-white: #FFFFFF !default;
/// color|1|Background Color|4
$--color-black: #333333 !default;
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
/// color|1|Font Color|2
$--color-text-primary: #333333 !default;
/// color|1|Font Color|2
$--color-text-regular: #666666 !default;
/// color|1|Font Color|2
$--color-text-secondary: #999999 !default;
/// color|1|Font Color|2
$--color-text-placeholder: #999999 !default;
/// color|1|Border Color|3
$--border-color-base: #E5E5E5E5 !default;
/// color|1|Border Color|3
$--border-color-light: #f2f2f2f2!default;
/// color|1|Functional Color|1
$--color-success: #67c23a !default;
/// color|1|Functional Color|1
$--color-warning: #FB9400 !default;
/// color|1|Functional Color|1
$--color-danger: #F56C6C !default;
/// color|1|Functional Color|1
$--color-info: #909399 !default;
// Background
/// color|1|Background Color|4
$--background-color-base: #F5F7F9 !default;
/* Border
-------------------------- */
$--border-width-base: 1px !default;
$--border-style-base: solid !default;
$--border-color-hover: $--color-primary!default;
$--border-base: $--border-width-base $--border-style-base $--border-color-base !default;
$--font-size-base: 14px !default;

View File

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke viewBox IE
normalize.css */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,579 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2399990" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe637;</span>
<div class="name">微信</div>
<div class="code-name">&amp;#xe637;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe607;</span>
<div class="name">微信</div>
<div class="code-name">&amp;#xe607;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe785;</span>
<div class="name">YUAN</div>
<div class="code-name">&amp;#xe785;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe8e8;</span>
<div class="name">comment</div>
<div class="code-name">&amp;#xe8e8;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe8bb;</span>
<div class="name">微信</div>
<div class="code-name">&amp;#xe8bb;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64e;</span>
<div class="name">icon_order</div>
<div class="code-name">&amp;#xe64e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64b;</span>
<div class="name">shouhou</div>
<div class="code-name">&amp;#xe64b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64c;</span>
<div class="name">peisong</div>
<div class="code-name">&amp;#xe64c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64d;</span>
<div class="name">fuwu</div>
<div class="code-name">&amp;#xe64d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64a;</span>
<div class="name">自营</div>
<div class="code-name">&amp;#xe64a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe648;</span>
<div class="name">正品</div>
<div class="code-name">&amp;#xe648;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe646;</span>
<div class="name">top</div>
<div class="code-name">&amp;#xe646;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe74a;</span>
<div class="name">coupons</div>
<div class="code-name">&amp;#xe74a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe764;</span>
<div class="name">service</div>
<div class="code-name">&amp;#xe764;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe767;</span>
<div class="name">survey</div>
<div class="code-name">&amp;#xe767;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe79d;</span>
<div class="name">collection</div>
<div class="code-name">&amp;#xe79d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe7b2;</span>
<div class="name">cart-Empty</div>
<div class="code-name">&amp;#xe7b2;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1635478222086') format('woff2'),
url('iconfont.woff?t=1635478222086') format('woff'),
url('iconfont.ttf?t=1635478222086') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-weixin1"></span>
<div class="name">
微信
</div>
<div class="code-name">.icon-weixin1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weixin2"></span>
<div class="name">
微信
</div>
<div class="code-name">.icon-weixin2
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-YUAN"></span>
<div class="name">
YUAN
</div>
<div class="code-name">.icon-YUAN
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-comment"></span>
<div class="name">
comment
</div>
<div class="code-name">.icon-comment
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weixin"></span>
<div class="name">
微信
</div>
<div class="code-name">.icon-weixin
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-icon_order"></span>
<div class="name">
icon_order
</div>
<div class="code-name">.icon-icon_order
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shouhou"></span>
<div class="name">
shouhou
</div>
<div class="code-name">.icon-shouhou
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-peisong"></span>
<div class="name">
peisong
</div>
<div class="code-name">.icon-peisong
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-fuwu"></span>
<div class="name">
fuwu
</div>
<div class="code-name">.icon-fuwu
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-ziying"></span>
<div class="name">
自营
</div>
<div class="code-name">.icon-ziying
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-zhengpin"></span>
<div class="name">
正品
</div>
<div class="code-name">.icon-zhengpin
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-top"></span>
<div class="name">
top
</div>
<div class="code-name">.icon-top
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-coupons"></span>
<div class="name">
coupons
</div>
<div class="code-name">.icon-coupons
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-service"></span>
<div class="name">
service
</div>
<div class="code-name">.icon-service
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-survey"></span>
<div class="name">
survey
</div>
<div class="code-name">.icon-survey
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-collection"></span>
<div class="name">
collection
</div>
<div class="code-name">.icon-collection
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-cart-Empty"></span>
<div class="name">
cart-Empty
</div>
<div class="code-name">.icon-cart-Empty
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weixin1"></use>
</svg>
<div class="name">微信</div>
<div class="code-name">#icon-weixin1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weixin2"></use>
</svg>
<div class="name">微信</div>
<div class="code-name">#icon-weixin2</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-YUAN"></use>
</svg>
<div class="name">YUAN</div>
<div class="code-name">#icon-YUAN</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-comment"></use>
</svg>
<div class="name">comment</div>
<div class="code-name">#icon-comment</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weixin"></use>
</svg>
<div class="name">微信</div>
<div class="code-name">#icon-weixin</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-icon_order"></use>
</svg>
<div class="name">icon_order</div>
<div class="code-name">#icon-icon_order</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shouhou"></use>
</svg>
<div class="name">shouhou</div>
<div class="code-name">#icon-shouhou</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-peisong"></use>
</svg>
<div class="name">peisong</div>
<div class="code-name">#icon-peisong</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-fuwu"></use>
</svg>
<div class="name">fuwu</div>
<div class="code-name">#icon-fuwu</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-ziying"></use>
</svg>
<div class="name">自营</div>
<div class="code-name">#icon-ziying</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-zhengpin"></use>
</svg>
<div class="name">正品</div>
<div class="code-name">#icon-zhengpin</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-top"></use>
</svg>
<div class="name">top</div>
<div class="code-name">#icon-top</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-coupons"></use>
</svg>
<div class="name">coupons</div>
<div class="code-name">#icon-coupons</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-service"></use>
</svg>
<div class="name">service</div>
<div class="code-name">#icon-service</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-survey"></use>
</svg>
<div class="name">survey</div>
<div class="code-name">#icon-survey</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-collection"></use>
</svg>
<div class="name">collection</div>
<div class="code-name">#icon-collection</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-cart-Empty"></use>
</svg>
<div class="name">cart-Empty</div>
<div class="code-name">#icon-cart-Empty</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

View File

@ -0,0 +1,83 @@
@font-face {
font-family: "iconfont"; /* Project id 2399990 */
src: url('iconfont.woff2?t=1635478222086') format('woff2'),
url('iconfont.woff?t=1635478222086') format('woff'),
url('iconfont.ttf?t=1635478222086') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-weixin1:before {
content: "\e637";
}
.icon-weixin2:before {
content: "\e607";
}
.icon-YUAN:before {
content: "\e785";
}
.icon-comment:before {
content: "\e8e8";
}
.icon-weixin:before {
content: "\e8bb";
}
.icon-icon_order:before {
content: "\e64e";
}
.icon-shouhou:before {
content: "\e64b";
}
.icon-peisong:before {
content: "\e64c";
}
.icon-fuwu:before {
content: "\e64d";
}
.icon-ziying:before {
content: "\e64a";
}
.icon-zhengpin:before {
content: "\e648";
}
.icon-top:before {
content: "\e646";
}
.icon-coupons:before {
content: "\e74a";
}
.icon-service:before {
content: "\e764";
}
.icon-survey:before {
content: "\e767";
}
.icon-collection:before {
content: "\e79d";
}
.icon-cart-Empty:before {
content: "\e7b2";
}

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,128 @@
{
"id": "2399990",
"name": "likeshop_pc_shop",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "6684308",
"name": "微信",
"font_class": "weixin1",
"unicode": "e637",
"unicode_decimal": 58935
},
{
"icon_id": "15933094",
"name": "微信",
"font_class": "weixin2",
"unicode": "e607",
"unicode_decimal": 58887
},
{
"icon_id": "4765744",
"name": "YUAN",
"font_class": "YUAN",
"unicode": "e785",
"unicode_decimal": 59269
},
{
"icon_id": "6598316",
"name": "comment",
"font_class": "comment",
"unicode": "e8e8",
"unicode_decimal": 59624
},
{
"icon_id": "11372717",
"name": "微信",
"font_class": "weixin",
"unicode": "e8bb",
"unicode_decimal": 59579
},
{
"icon_id": "20318900",
"name": "icon_order",
"font_class": "icon_order",
"unicode": "e64e",
"unicode_decimal": 58958
},
{
"icon_id": "20215028",
"name": "shouhou",
"font_class": "shouhou",
"unicode": "e64b",
"unicode_decimal": 58955
},
{
"icon_id": "20215029",
"name": "peisong",
"font_class": "peisong",
"unicode": "e64c",
"unicode_decimal": 58956
},
{
"icon_id": "20215030",
"name": "fuwu",
"font_class": "fuwu",
"unicode": "e64d",
"unicode_decimal": 58957
},
{
"icon_id": "20179589",
"name": "自营",
"font_class": "ziying",
"unicode": "e64a",
"unicode_decimal": 58954
},
{
"icon_id": "20179548",
"name": "正品",
"font_class": "zhengpin",
"unicode": "e648",
"unicode_decimal": 58952
},
{
"icon_id": "20179252",
"name": "top",
"font_class": "top",
"unicode": "e646",
"unicode_decimal": 58950
},
{
"icon_id": "11488015",
"name": "coupons",
"font_class": "coupons",
"unicode": "e74a",
"unicode_decimal": 59210
},
{
"icon_id": "11488128",
"name": "service",
"font_class": "service",
"unicode": "e764",
"unicode_decimal": 59236
},
{
"icon_id": "11488143",
"name": "survey",
"font_class": "survey",
"unicode": "e767",
"unicode_decimal": 59239
},
{
"icon_id": "11494511",
"name": "collection",
"font_class": "collection",
"unicode": "e79d",
"unicode_decimal": 59293
},
{
"icon_id": "12011694",
"name": "cart-Empty",
"font_class": "cart-Empty",
"unicode": "e7b2",
"unicode_decimal": 59314
}
]
}

View File

@ -0,0 +1,62 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="icon_order" unicode="&#58958;" d="M810.666667-42.666667H213.333333a85.333333 85.333333 0 0 0-85.333333 85.333334V725.333333a85.333333 85.333333 0 0 0 85.333333 85.333334h597.333334a85.333333 85.333333 0 0 0 85.333333-85.333334v-682.666666a85.333333 85.333333 0 0 0-85.333333-85.333334zM234.666667 746.666667a42.666667 42.666667 0 0 1-42.666667-42.666667v-640a42.666667 42.666667 0 0 1 42.666667-42.666667h554.666666a42.666667 42.666667 0 0 1 42.666667 42.666667v640a42.666667 42.666667 0 0 1-42.666667 42.666667zM298.666667 597.333333h426.666666v-64H298.666667zM298.666667 426.666667h426.666666v-64H298.666667zM298.666667 256h426.666666v-64H298.666667z" horiz-adv-x="1024" />
<glyph glyph-name="shouhou" unicode="&#58955;" d="M511.969692-127.958633a508.733026 508.733026 0 0 0-199.258206 40.220259 509.449782 509.449782 0 0 0-162.703642 109.704646 508.343929 508.343929 0 0 0-109.704646 162.7446A508.180099 508.180099 0 0 0 0.001024 384.010035a507.872918 507.872918 0 0 0 40.281695 199.237726 508.323451 508.323451 0 0 0 109.704646 162.703643 509.449782 509.449782 0 0 0 162.703642 109.704646A508.773983 508.773983 0 0 0 511.969692 895.978702a508.773983 508.773983 0 0 0 199.258205-40.220258 510.698985 510.698985 0 0 0 162.7446-109.704646 509.593133 509.593133 0 0 0 109.704646-162.703643A507.872918 507.872918 0 0 0 1023.938359 384.010035a508.180099 508.180099 0 0 0-40.281695-199.299163 509.695527 509.695527 0 0 0-109.704646-162.7446 510.596591 510.596591 0 0 0-162.7446-109.704646A508.733026 508.733026 0 0 0 511.969692-127.958633z m0 1003.458588a488.356673 488.356673 0 0 1-191.312452-38.622916 490.302154 490.302154 0 0 1-156.273316-105.322194 490.896037 490.896037 0 0 1-105.363152-156.21188A488.766248 488.766248 0 0 1 20.479771 384.010035a488.991514 488.991514 0 0 1 38.602437-191.312452 490.957473 490.957473 0 0 1 105.363152-156.232359 490.322632 490.322632 0 0 1 156.273316-105.342673A488.336194 488.336194 0 0 1 511.969692-107.479886a488.336194 488.336194 0 0 1 191.312451 38.622916 489.54444 489.54444 0 0 1 156.232359 105.342673 490.404547 490.404547 0 0 1 105.322194 156.232359A488.971035 488.971035 0 0 1 1003.459612 384.010035a488.72529 488.72529 0 0 1-38.602437 191.271494 490.404547 490.404547 0 0 1-105.322194 156.21188 490.138324 490.138324 0 0 1-156.232359 105.322194A488.356673 488.356673 0 0 1 511.969692 875.499955zM511.99017 670.671531a291.207778 291.207778 0 1 1 286.702454-291.187299 291.207778 291.207778 0 0 1-286.702454 291.187299z m75.566576-336.035755c13.946027 0 25.188858-7.5157 25.188858-16.813051s-11.263311-16.83353-25.188858-16.83353h-53.244742v-57.34049a17.243105 17.243105 0 1 0-33.667059 0v57.34049H436.403116c-13.925548 0-25.188858 7.556658-25.188858 16.854009s11.263311 16.813051 25.188858 16.813051h64.241829v33.523708H436.403116c-13.925548 0-25.188858 7.5157-25.188858 16.854009s11.263311 16.813051 25.188858 16.813051h64.241829v13.413579a33.912805 33.912805 0 0 0-9.911714 7.003731l-70.201143 70.549283c-9.604532 9.604532-12.123418 22.526621-5.713571 28.956948s19.372894 3.809047 28.875033-5.795486l70.221623-70.549282 0.757713-0.757714a30.431418 30.431418 0 0 0 2.764631 3.051334l62.071081 62.050602c9.788841 9.850277 23.140984 12.512514 29.694183 5.959315s3.952398-19.864384-5.959315-29.714661l-62.050603-62.050603a37.168925 37.168925 0 0 0-7.106125-5.570219 22.669973 22.669973 0 0 0 0.348139-3.952398v-12.594429h53.244741c13.946027 0 25.188858-7.5157 25.188859-16.813051s-11.263311-16.854009-25.188859-16.854009h-53.244741v-33.523708h53.244741z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="peisong" unicode="&#58956;" d="M512.050592-127.958633a508.733026 508.733026 0 0 0-199.258205 40.220259 509.449782 509.449782 0 0 0-162.703643 109.704646 508.343929 508.343929 0 0 0-109.704646 162.7446A508.180099 508.180099 0 0 0 0.081925 384.010035a507.872918 507.872918 0 0 0 40.281695 199.237726 508.323451 508.323451 0 0 0 109.704646 162.703643 509.449782 509.449782 0 0 0 162.703642 109.704646A508.773983 508.773983 0 0 0 512.050592 895.978702a508.773983 508.773983 0 0 0 199.258206-40.220258 510.698985 510.698985 0 0 0 162.7446-109.704646 509.593133 509.593133 0 0 0 109.704646-162.703643A507.872918 507.872918 0 0 0 1024.01926 384.010035a508.180099 508.180099 0 0 0-40.281695-199.299163 509.695527 509.695527 0 0 0-109.704646-162.7446 510.596591 510.596591 0 0 0-162.7446-109.704646A508.733026 508.733026 0 0 0 512.050592-127.958633z m0 1003.458588a488.356673 488.356673 0 0 1-191.312451-38.622916 490.302154 490.302154 0 0 1-156.273316-105.322194 490.896037 490.896037 0 0 1-105.363152-156.21188A488.766248 488.766248 0 0 1 20.560672 384.010035a488.991514 488.991514 0 0 1 38.602437-191.312452 490.957473 490.957473 0 0 1 105.363152-156.232359 490.322632 490.322632 0 0 1 156.273316-105.342673A488.336194 488.336194 0 0 1 512.050592-107.479886a488.336194 488.336194 0 0 1 191.312452 38.622916 489.54444 489.54444 0 0 1 156.232359 105.342673 490.404547 490.404547 0 0 1 105.322194 156.232359A488.971035 488.971035 0 0 1 1003.540513 384.010035a488.72529 488.72529 0 0 1-38.602437 191.271494 490.404547 490.404547 0 0 1-105.322195 156.21188 490.138324 490.138324 0 0 1-156.232358 105.322194A488.356673 488.356673 0 0 1 512.050592 875.499955zM838.481815 392.549672a17.468371 17.468371 0 0 1-2.887503 9.113042l-97.540271 146.382082a17.447892 17.447892 0 0 1-14.335123 7.659051h-131.86265a17.32502 17.32502 0 0 1-17.304541-17.32502v-282.258566a17.345498 17.345498 0 0 1 17.345499-17.325019h35.469189a79.232271 79.232271 0 0 1 158.444063 0h35.407753a17.365977 17.365977 0 0 1 17.32502 17.325019v136.388453z m-184.80021 4.710112V502.909638h66.82215l70.42641-105.649854z m52.814687-198.009002a39.605896 39.605896 0 1 0 39.585418 39.605896 39.646854 39.646854 0 0 0-39.585418-39.605896zM525.054597 608.518535H227.785109A22.997633 22.997633 0 0 1 204.807956 585.520902v-323.666591a22.997633 22.997633 0 0 1 22.977153-23.018112h56.193681a79.232271 79.232271 0 0 1 158.444064 0h82.611264a22.997633 22.997633 0 0 1 22.997632 22.997633V585.541381A22.997633 22.997633 0 0 1 525.034118 608.539013z m-161.782099-409.267753a39.605896 39.605896 0 1 0 39.626375 39.605896 39.646854 39.646854 0 0 0-39.626375-39.605896z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="fuwu" unicode="&#58957;" d="M511.977065-127.958633a508.733026 508.733026 0 0 0-199.258206 40.220259 509.449782 509.449782 0 0 0-162.703642 109.704646 508.343929 508.343929 0 0 0-109.704646 162.7446A508.180099 508.180099 0 0 0 0.008397 384.010035a507.872918 507.872918 0 0 0 40.281695 199.237726 508.323451 508.323451 0 0 0 109.704646 162.703643 509.449782 509.449782 0 0 0 162.703643 109.704646A508.773983 508.773983 0 0 0 511.977065 895.978702a508.773983 508.773983 0 0 0 199.258205-40.220258 510.698985 510.698985 0 0 0 162.7446-109.704646 509.593133 509.593133 0 0 0 109.704646-162.703643A507.872918 507.872918 0 0 0 1023.945732 384.010035a508.180099 508.180099 0 0 0-40.281694-199.299163 509.695527 509.695527 0 0 0-109.704646-162.7446 510.596591 510.596591 0 0 0-162.744601-109.704646A508.733026 508.733026 0 0 0 511.977065-127.958633z m0 1003.458588a488.356673 488.356673 0 0 1-191.312452-38.622916 490.302154 490.302154 0 0 1-156.273316-105.322194 490.896037 490.896037 0 0 1-105.363152-156.21188A488.766248 488.766248 0 0 1 20.487144 384.010035a488.991514 488.991514 0 0 1 38.602438-191.312452 490.957473 490.957473 0 0 1 105.363151-156.232359 490.322632 490.322632 0 0 1 156.273316-105.342673A488.336194 488.336194 0 0 1 511.977065-107.479886a488.336194 488.336194 0 0 1 191.312451 38.622916 489.54444 489.54444 0 0 1 156.232359 105.342673 490.404547 490.404547 0 0 1 105.322194 156.232359A488.971035 488.971035 0 0 1 1003.466986 384.010035a488.72529 488.72529 0 0 1-38.602438 191.271494 490.404547 490.404547 0 0 1-105.322194 156.21188 490.138324 490.138324 0 0 1-156.232359 105.322194A488.356673 488.356673 0 0 1 511.977065 875.499955zM517.649678 98.290561H304.322573c-33.380357 0-39.892599 7.372349-37.721851 41.182759a187.564841 187.564841 0 0 0 163.829973 167.802851 918.267002 918.267002 0 0 0 176.117222 0 187.360054 187.360054 0 0 0 163.461356-171.263759c1.31064-29.919449-5.201602-37.291798-35.551104-37.291798-72.412848-0.860107-144.395643-0.430054-216.788013-0.430053z m150.457352 402.796468a153.5906 153.5906 0 0 0-153.058153-151.747513 150.191128 150.191128 0 0 0-146.545912 153.918261 153.119589 153.119589 0 0 0 159.549916 146.975965 144.272771 144.272771 0 0 0 140.054149-149.146713z m0 0M694.524613 481.816529c2.150268 108.107304-80.358602 196.595968-179.74196 192.868836a173.454985 173.454985 0 0 1-127.459719-63.115497 195.449159 195.449159 0 0 1-44.070263-141.651491 119.104391 119.104391 0 0 0-4.751069-29.776098 103.171926 103.171926 0 0 0-31.53727 7.802403 56.910437 56.910437 0 0 0-7.761445 85.662597 118.776731 118.776731 0 0 1 23.755346 35.284881 205.995713 205.995713 0 0 0 391.000711 2.744152c5.201602-12.819695 17.734595-21.994174 23.775824-34.363337a107.267675 107.267675 0 0 0 18.14417-52.691815 68.439971 68.439971 0 0 0-30.71812-41.694729c-21.175024-13.290707-32.765995-2.744152-31.53727 23.36625 0.430054 5.508783 0.430054 10.546555 0.880586 15.584327z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="ziying" unicode="&#58954;" d="M512.012907-127.958633a508.733026 508.733026 0 0 0-199.258205 40.220259 509.449782 509.449782 0 0 0-162.703643 109.704646 508.343929 508.343929 0 0 0-109.704646 162.7446A508.180099 508.180099 0 0 0 0.044239 384.010035a507.872918 507.872918 0 0 0 40.281695 199.237726 508.323451 508.323451 0 0 0 109.704646 162.703643 509.449782 509.449782 0 0 0 162.703643 109.704646A508.773983 508.773983 0 0 0 512.012907 895.978702a508.773983 508.773983 0 0 0 199.258205-40.220258 510.698985 510.698985 0 0 0 162.7446-109.704646 509.593133 509.593133 0 0 0 109.704646-162.703643A507.872918 507.872918 0 0 0 1023.981574 384.010035a508.180099 508.180099 0 0 0-40.281694-199.299163 509.695527 509.695527 0 0 0-109.704646-162.7446 510.596591 510.596591 0 0 0-162.7446-109.704646A508.733026 508.733026 0 0 0 512.012907-127.958633z m0 1003.458588a488.356673 488.356673 0 0 1-191.312452-38.622916 490.302154 490.302154 0 0 1-156.273316-105.322194 490.896037 490.896037 0 0 1-105.363152-156.21188A488.766248 488.766248 0 0 1 20.522986 384.010035a488.991514 488.991514 0 0 1 38.602438-191.312452 490.957473 490.957473 0 0 1 105.363151-156.232359 490.322632 490.322632 0 0 1 156.273317-105.342673A488.336194 488.336194 0 0 1 512.012907-107.479886a488.336194 488.336194 0 0 1 191.312452 38.622916 489.54444 489.54444 0 0 1 156.232358 105.342673 490.404547 490.404547 0 0 1 105.322195 156.232359A488.971035 488.971035 0 0 1 1003.502828 384.010035a488.72529 488.72529 0 0 1-38.602438 191.271494 490.404547 490.404547 0 0 1-105.322194 156.21188 490.138324 490.138324 0 0 1-156.232359 105.322194A488.356673 488.356673 0 0 1 512.012907 875.499955zM754.174087 471.351889v1.044416a8.191499 8.191499 0 0 1-1.003459 3.297079l-33.400836 115.479652A55.026392 55.026392 0 0 1 665.316805 629.652601H361.227895a52.302719 52.302719 0 0 1-52.405113-37.394191L271.838166 473.993648a24.103485 24.103485 0 0 1-0.511969-2.744152 110.585232 110.585232 0 0 1-5.140165-34.097114c0-40.138344 10.771821-72.597157 44.152177-91.294253a95.656226 95.656226 0 0 1 47.797395-12.102939 98.605165 98.605165 0 0 1 77.553014 38.479565 97.663143 97.663143 0 0 1 77.061524-38.479565 96.680163 96.680163 0 0 1 76.549555 38.479565 98.543729 98.543729 0 0 1 77.553014-38.479565 99.485751 99.485751 0 0 1 48.800853 12.102939c32.909346 19.802948 43.660688 51.688357 43.660688 91.847179a103.663416 103.663416 0 0 1-5.160644 33.564666z m-17.263584-175.523338a19.229543 19.229543 0 0 1-18.738053 19.843906 14.53991 14.53991 0 0 1-5.22208-1.126331 110.585232 110.585232 0 0 0-44.766541-8.191499 108.742145 108.742145 0 0 0-73.928275 27.482478 118.30572 118.30572 0 0 0-77.553014-30.861471 113.923268 113.923268 0 0 0-78.085461 27.564393 117.670879 117.670879 0 0 0-78.638388-29.202693 110.810498 110.810498 0 0 0-44.254571 9.911714c-0.511969 0-1.044416 0.552926-1.576864 0.552926-1.023937 0.532447-2.047875 0.532447-2.6008 1.105852a27.113861 27.113861 0 0 1-4.09575 0.532447 19.229543 19.229543 0 0 1-18.738053-19.823426v-106.366611a49.148992 49.148992 0 0 1 47.797395-50.705377h352.500667a49.558567 49.558567 0 0 1 47.899788 50.684899z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="zhengpin" unicode="&#58952;" d="M512.030111-127.958633a508.733026 508.733026 0 0 0-199.258205 40.220259 509.449782 509.449782 0 0 0-162.703643 109.704646 508.343929 508.343929 0 0 0-109.704646 162.7446A508.180099 508.180099 0 0 0 0.061444 384.010035a507.872918 507.872918 0 0 0 40.281694 199.237726 508.323451 508.323451 0 0 0 109.704647 162.703643 509.449782 509.449782 0 0 0 162.703642 109.704646A508.773983 508.773983 0 0 0 512.030111 895.978702a508.773983 508.773983 0 0 0 199.258206-40.220258 510.698985 510.698985 0 0 0 162.7446-109.704646 509.593133 509.593133 0 0 0 109.704646-162.703643A507.872918 507.872918 0 0 0 1023.998779 384.010035a508.180099 508.180099 0 0 0-40.281695-199.299163 509.695527 509.695527 0 0 0-109.704646-162.7446 510.596591 510.596591 0 0 0-162.7446-109.704646A508.733026 508.733026 0 0 0 512.030111-127.958633z m0 1003.458588a488.356673 488.356673 0 0 1-191.312451-38.622916 490.302154 490.302154 0 0 1-156.273317-105.322194 490.896037 490.896037 0 0 1-105.363151-156.21188A488.766248 488.766248 0 0 1 20.54019 384.010035a488.991514 488.991514 0 0 1 38.602438-191.312452 490.957473 490.957473 0 0 1 105.363152-156.232359 490.322632 490.322632 0 0 1 156.273316-105.342673A488.336194 488.336194 0 0 1 512.030111-107.479886a488.336194 488.336194 0 0 1 191.312452 38.622916 489.54444 489.54444 0 0 1 156.232358 105.342673 490.404547 490.404547 0 0 1 105.322195 156.232359A488.971035 488.971035 0 0 1 1003.520032 384.010035a488.72529 488.72529 0 0 1-38.602438 191.271494 490.404547 490.404547 0 0 1-105.322194 156.21188 490.138324 490.138324 0 0 1-156.232358 105.322194A488.356673 488.356673 0 0 1 512.030111 875.499955zM723.903225 348.45893a219.716473 219.716473 0 0 1 23.284335 98.420857A225.266214 225.266214 0 0 1 520.54927 670.302913a225.020469 225.020469 0 0 1-226.699726-223.423126 220.740411 220.740411 0 0 1 23.284335-98.420857l-91.867658-156.826242s58.405386-11.816237 117.445612-23.939655l78.740782-87.915259 84.63866 144.354685c4.914899 0 9.522617-0.65532 14.335122-0.65532s9.502138 0.32766 14.335123 0.65532l84.63866-144.354685 78.740781 87.915259c59.060705 12.143897 117.445612 23.939655 117.445613 23.939655z m-203.353955-84.311a184.615902 184.615902 0 0 0-184.30872 184.697817 184.615902 184.615902 0 0 0 184.30872 184.697816 184.595423 184.595423 0 0 0 184.30872-184.697816 184.595423 184.595423 0 0 0-184.30872-184.697817z m-147.303625 184.697817a147.446976 147.446976 0 0 1 147.303625-147.610807 147.446976 147.446976 0 0 1 147.303625 147.631285 147.446976 147.446976 0 0 1-147.303625 147.631285 147.446976 147.446976 0 0 1-147.303625-147.631285z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="top" unicode="&#58950;" d="M349.793933-127.947165a52.835251 52.835251 0 0 0-52.835251 52.835251v325.940664H140.196492a52.835251 52.835251 0 0 0-36.984676 90.718126l372.013003 360.811929a52.835251 52.835251 0 0 0 73.388163 0l371.907332-360.811929a52.835251 52.835251 0 0 0-36.984675-90.718126h-156.65652v-325.940664a52.835251 52.835251 0 0 0-52.835251-52.835251zM87.308406 896m52.835251 0l739.693514 0q52.835251 0 52.835251-52.835251l0 0q0-52.835251-52.835251-52.835251l-739.693514 0q-52.835251 0-52.835251 52.835251l0 0q0 52.835251 52.835251 52.835251Z" horiz-adv-x="1024" />
<glyph glyph-name="coupons" unicode="&#59210;" d="M148.010667 290.709333c50.069333 0 90.666667 40.874667 90.666666 91.285334 0 49.962667-39.893333 90.538667-89.344 91.264V618.666667a64 64 0 0 0 64 64h597.333334a64 64 0 0 0 64-64l-0.021334-145.450667-3.050666-0.064c-48.021333-2.304-86.272-42.24-86.272-91.157333 0-49.962667 39.872-90.56 89.322666-91.285334V149.333333a64 64 0 0 0-64-64H213.333333a64 64 0 0 0-64 64v141.397334l-1.322666-0.021334zM213.333333 241.216V149.333333h597.333334v91.861334a155.370667 155.370667 0 0 0-89.344 140.8A154.837333 154.837333 0 0 0 810.666667 522.432V618.666667H213.333333v-95.893334a155.370667 155.370667 0 0 0 89.322667-140.8 155.370667 155.370667 0 0 0-84.266667-138.282666l-5.056-2.496zM384 298.666667h68.010667v-85.333334H384v85.333334z m0 128h68.010667v-85.333334H384v85.333334z m0 128h68.010667v-85.333334H384v85.333334z" horiz-adv-x="1024" />
<glyph glyph-name="service" unicode="&#59236;" d="M673.194667 482.026667h78.72c-14.890667 116.053333-116.629333 205.824-239.914667 205.824-123.306667 0-225.024-89.792-239.914667-205.824h78.72v-264.661334H234.666667a85.333333 85.333333 0 0 0-85.333334 85.333334v93.994666a85.376 85.376 0 0 0 60.693334 81.706667l0.917333 0.256C224.490667 628.842667 354.090667 746.666667 512 746.666667c157.888 0 287.509333-117.802667 301.056-268.010667l0.917333-0.256A85.376 85.376 0 0 0 874.666667 396.693333v-93.994666a85.333333 85.333333 0 0 0-85.333334-85.333334l-55.722666 0.021334v-40.384a106.709333 106.709333 0 0 0-74.368-101.696A78.506667 78.506667 0 0 0 584.704 21.333333h-115.178667a78.421333 78.421333 0 0 0 0 156.821334h115.178667c27.050667 0 50.901333-13.696 64.981333-34.517334a63.744 63.744 0 0 1 23.381334 45.76l0.128 3.754667v288.853333zM584.704 114.133333h-115.178667a14.421333 14.421333 0 0 1 0-28.821333h115.178667a14.421333 14.421333 0 0 1 0 28.821333zM286.805333 418.026667H234.666667a21.333333 21.333333 0 0 1-21.333334-21.333334v-93.994666a21.333333 21.333333 0 0 1 21.333334-21.333334h52.138666v136.661334z m502.528 0h-52.138666v-136.661334H789.333333a21.333333 21.333333 0 0 1 21.333334 21.333334v93.994666a21.333333 21.333333 0 0 1-21.333334 21.333334z" horiz-adv-x="1024" />
<glyph glyph-name="survey" unicode="&#59239;" d="M830.784 406.698667l45.098667-45.397334-322.282667-320-14.656 14.762667 14.741333-14.890667h-45.013333v45.376l-0.149333 0.149334 322.261333 320zM746.666667 725.333333a64 64 0 0 0 64-64v-192l-64-64V661.333333H277.333333v-554.666666h170.666667l-64-64h-106.666667a64 64 0 0 0-64 64V661.333333a64 64 0 0 0 64 64h469.333334z m-198.058667-448v-64h-67.434667l-0.021333 64h67.456z m-3.968 316.330667c43.562667-8.768 95.36-50.304 95.36-110.741333 0-60.437333-49.365333-83.328-67.050667-94.634667-16.426667-10.517333-23.317333-22.506667-24.234666-35.306667l-0.106667-2.965333V320h-67.456v54.592c0 21.248 6.848 36.117333 25.941333 49.28l3.989334 2.624 37.888 25.216c24.170667 16.277333 23.829333 48.917333 8.874666 63.36a67.925333 67.925333 0 0 1-59.434666 15.232c-42.154667-8.277333-46.933333-38.08-47.189334-66.922667v-16.085333H384c0 56.064 6.421333 81.472 36.352 113.578667 33.493333 35.882667 80.704 41.621333 124.288 32.789333z" horiz-adv-x="1024" />
<glyph glyph-name="collection" unicode="&#59293;" d="M490.261333 722.56a49.066667 49.066667 0 0 0 64.064-19.178667l1.664-3.093333 87.850667-177.813333 196.352-28.501334a49.066667 49.066667 0 0 0 29.717333-81.066666l-2.538666-2.645334L725.333333 272l33.536-195.349333a49.066667 49.066667 0 0 0-68.010666-53.269334l-3.157334 1.514667L512 117.141333l-175.701333-92.266666a49.066667 49.066667 0 0 0-71.637334 48.426666l0.469334 3.328L298.666667 271.978667 156.629333 410.24a49.066667 49.066667 0 0 0 23.893334 83.114667l3.285333 0.597333 196.352 28.501333 87.850667 177.813334a49.066667 49.066667 0 0 0 22.250666 22.272z m-67.626666-258.581333l-199.658667-28.992 144.469333-140.650667-34.133333-198.741333L512 189.44l178.688-93.845333-34.133333 198.741333 144.469333 140.650667-199.658667 28.992L512 644.842667l-89.386667-180.864z" horiz-adv-x="1024" />
<glyph glyph-name="cart-Empty" unicode="&#59314;" d="M330.667 128a53.333 53.333 0 1 0 0-106.667 53.333 53.333 0 0 0 0 106.667z m384 0a53.333 53.333 0 1 0 0-106.667 53.333 53.333 0 0 0 0 106.667zM94.763 736h54.741a96 96 0 0 0 92.907-71.787l1.024-4.394 13.205-62.486h0.213L299.733 392l32.491-157.333h402.219l61.653 298.666H313.813l-13.376 64h495.68a64 64 0 0 0 62.678-76.949L797.14 221.717a64 64 0 0 0-62.698-51.05H332.224a64 64 0 0 0-62.677 51.05L208.96 515.136l-0.405-0.085-27.734 131.562a32 32 0 0 1-28.309 25.238l-2.987 0.149H94.741v64h54.742z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,16 @@
#!/bin/bash
# 文件原路径
srcPath="./dist"
# 发布路径文件夹
releasePath="../server/public/pc"
#删除发布目录下的PC文件
rm -r $releasePath
echo "已删除 ==> $releasePath 下的目录文件"
mkdir $releasePath
echo "已新建 ==> $releasePath 目录"
# 复制打包目录内的文件到发布目录
cp -r $srcPath/* $releasePath
echo "已复制 $srcPath/* ==> $releasePath"

View File

@ -0,0 +1,133 @@
<template>
<div class="activity-area m-t-16" v-if="list.length">
<div class="title flex row-between">
<div class="font-size-20">{{ title }}</div>
<nuxt-link :to="url" class="more lighter"
>更多 <i class="el-icon-arrow-right"></i
></nuxt-link>
</div>
<div class="activity-goods m-t-16">
<client-only>
<swiper ref="headerSwiper" :options="swiperOptions">
<swiper-slide
class="swiper-item"
v-for="(item, index) in swiperSize"
:key="index"
>
<div class="goods-list flex row-between">
<nuxt-link
class="goods-item"
:to="`/goods_details/${gitem.id}`"
v-for="(gitem, gindex) in getSwiperList(index)"
:key="gindex"
>
<div class="goods-img">
<el-image
lazy
:src="gitem.image"
fit="cover"
alt=""
></el-image>
</div>
<div class="name line-2 m-t-10">{{ gitem.name }}</div>
<div class="price flex col-baseline m-t-10">
<div class="primary m-r-8">
<price-formate
:price="gitem.min_price"
:first-size="16"
/>
</div>
<div class="muted sm line-through ">
<price-formate
:price="gitem.market_price"
/>
</div>
</div>
<div class="muted xs m-t-10">
{{ gitem.sales_total }}人购买
</div>
</nuxt-link>
</div>
</swiper-slide>
</swiper>
</client-only>
</div>
</div>
</template>
<script>
export default {
components: {},
props: {
url: {
type: String,
default: '',
},
title: {
type: String,
},
list: {
type: Array,
default: () => [],
},
},
data() {
return {
swiperOptions: {
direction: 'vertical',
initialSlide: 0,
height: 280,
autoplay: true,
},
pageSize: 3,
}
},
computed: {
swiperSize() {
return Math.ceil(this.list.length / this.pageSize)
},
getSwiperList() {
return (index) => {
return this.list.slice(
index * this.pageSize,
(index + 1) * this.pageSize
)
}
},
},
}
</script>
<style lang="scss" scoped>
.activity-area {
padding: 16px;
border-radius: 6px;
background-color: #fff;
::v-deep .swiper-container {
width: 100%;
height: 280px;
}
.goods-list {
.goods-item {
width: 31.5%;
.goods-img {
width: 100%;
height: 0;
padding-top: 100%;
position: relative;
.el-image {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
}
.name {
line-height: 20px;
height: 40px;
}
}
}
}
</style>

View File

@ -0,0 +1,45 @@
<template>
<div class="ad-item" @click.stop="goPage(item)">
<el-image :src="item.image" fit="cover" style="width: 100%; height: 100%"></el-image>
</div>
</template>
<script>
import { paramsToStr } from "~/utils/tools";
export default {
components: {},
props: {
item: {
type: Object,
default: () => ({}),
},
},
methods: {
goPage(item) {
let { link_type, link, params } = item;
switch (link_type) {
case 3:
window.open(item.link);
break;
default:
if (["/goods_details"].includes(link)) {
link += `/${params.id}`;
} else {
link += paramsToStr(params);
}
this.$router.push({
path: link,
});
}
},
},
};
</script>
<style lang="scss" scoped>
.ad-item {
width: 100%;
height: 100%;
cursor: pointer;
}
</style>

View File

@ -0,0 +1,181 @@
<template>
<div class="address-add">
<el-dialog :title="aid ? '修改地址' : '添加地址'" top="30vh" :visible.sync="showDialog" width="700px" @closed="onClosed">
<el-form inline ref="form" :model="address" label-width="100px" :rules="rules">
<el-form-item label="收货人:" prop="contact">
<el-input size="small" v-model="address.contact" />
</el-form-item>
<el-form-item label="联系方式:" prop="telephone">
<el-input size="small" v-model="address.telephone" />
</el-form-item>
<el-form-item label="所在地区:" prop="region">
<el-cascader :options="options" v-model="address.region" @change="handleChange" placeholder="请选择省市区"
clearable size="small">
</el-cascader>
</el-form-item>
<el-form-item label="详细地址:" prop="address">
<el-input type="textarea" placeholder="请输入详细地址,如街道、门牌号等" v-model="address.address" :rows="3"
resize="none">
</el-input>
</el-form-item>
<div>
<el-form-item label=" ">
<el-checkbox :true-label="1" :false-label="0" v-model="address.is_default"></el-checkbox>
</el-form-item>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"></el-button>
<el-button @click="showDialog = false">取消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import regionData from "~/utils/area";
// @event success /
// @event change
export default {
components: {},
props: {
value: {
type: Boolean,
default: false,
},
aid: {
type: [Number, String],
},
},
data() {
return {
showDialog: false,
options: regionData,
address: {
is_default: true,
},
rules: {
contact: [
{
required: true,
message: "请输入收货人",
trigger: "change",
},
],
telephone: [
{
required: true,
message: "请输入联系方式",
trigger: "change",
},
],
address: [
{
required: true,
message: "请输入详细地址",
trigger: "change",
},
],
region: [
{
required: true,
validator: (rule, value, callback) => {
if (!value || !value.length > 0) {
return callback(new Error("请选择省市区"));
} else {
callback();
}
},
},
],
},
};
},
methods: {
onClosed() {
this.address = {
region: [],
};
this.$refs.form.resetFields();
},
async getOneAddress() {
const { data, code } = await this.$get("user_address/detail", {
params: { id: this.aid },
});
if (code == 1) {
const { province_id, city_id, district_id, is_default } = data;
data.region = [province_id, city_id, district_id];
data.is_default = Boolean(is_default);
this.address = data;
}
},
handleChange(val) {
console.log(val);
this.address.province_id = val[0];
this.address.city_id = val[1];
this.address.district_id = val[2];
},
submitForm() {
this.$refs.form.validate(async (valid) => {
if (valid) {
let address = JSON.parse(JSON.stringify(this.address));
delete address.region;
const { code, msg } = this.aid
? await this.$post("user_address/update", {
...address,
id: this.aid,
})
: await this.$post("user_address/add", address);
if (code == 1) {
this.$message({
message: msg,
type: "success",
});
this.showDialog = false;
this.$emit("success");
}
} else {
return false;
}
});
},
},
watch: {
value(val) {
this.showDialog = val;
},
showDialog(val) {
if (val) {
if (this.aid) {
this.getOneAddress();
}
}
this.$emit("input", val);
},
aid(val) {
if (val) {
this.getOneAddress();
}
},
},
};
</script>
<style lang="scss" scoped>
.address-add {
.el-cascader {
width: 468px;
}
.el-textarea {
width: 468px;
}
.dialog-footer {
text-align: center;
.el-button {
width: 160px;
}
}
}
</style>

View File

@ -0,0 +1,147 @@
<template>
<div class="address-list">
<el-dialog title="更换地址" :visible.sync="showDialog" width="900px">
<div class="list black">
<div
:class="['item m-b-16', { active: item.id == selectId }]"
v-for="(item, index) in addressList"
:key="index"
@click="selectId = item.id"
>
<div>
<span class="weigth-500">{{ item.contact }}</span>
{{ item.telephone }}
<el-tag
size="mini"
type="warning"
effect="dark"
v-if="item.is_default"
>默认</el-tag
>
</div>
<div class="lighter m-t-8">
{{ item.province }} {{ item.city }} {{ item.district }}
{{ item.address }}
</div>
<div class="oprate lighter flex">
<div
class="m-r-16"
@click.stop="
editId = item.id
showAddressAdd = true
"
>
修改
</div>
<div @click.stop="setDefault(item.id)">设为默认</div>
</div>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="onConfirm"></el-button>
<el-button @click="showDialog = false">取消</el-button>
</div>
</el-dialog>
<address-add
v-model="showAddressAdd"
:aid="editId"
@success="getAddress"
/>
</div>
</template>
<script>
export default {
components: {},
props: {
value: {
type: Boolean,
default: false,
},
},
data() {
return {
showDialog: false,
showAddressAdd: false,
addressList: [],
selectId: 0,
editId: '',
}
},
methods: {
async getAddress() {
const { code, data } = await this.$get('user_address/lists')
if (code == 1) {
this.addressList = data
}
},
async setDefault(id) {
const { code, data, msg } = await this.$post(
'user_address/setDefault',
{
id,
}
)
if (code == 1) {
this.$message({
message: msg,
type: 'success',
})
this.getAddress()
}
},
onConfirm() {
this.$emit('confirm', this.selectId)
this.showDialog = false
},
},
watch: {
value(val) {
this.showDialog = val
if (val == true) {
this.getAddress()
}
},
showDialog(val) {
this.$emit('input', val)
},
},
}
</script>
<style lang="scss" scoped>
.address-list {
::v-deep .el-dialog__body {
height: 460px;
overflow-y: auto;
}
.list {
margin: 0 auto;
width: 800px;
.item {
position: relative;
cursor: pointer;
padding: 16px 20px;
height: 100px;
padding-right: 150px;
border: 1px solid $--border-color-base;
border-radius: 2px;
&.active {
border-color: $--color-primary;
}
.oprate {
position: absolute;
right: 20px;
bottom: 9px;
}
}
}
.dialog-footer {
text-align: center;
.el-button {
width: 160px;
}
}
}
</style>

View File

@ -0,0 +1,160 @@
<template>
<div class="after-sales-list">
<div class="m-b-20" v-for="(items) in lists" :key="items.order_id">
<div class="after-sales-header m-t-30 flex row-between" style="border:0">
<div class="flex row-around">
<div class="lighter sm flex" style="margin-right:100px">
<img style="width:20px;height: 20px" class="m-r-5" :src="items.shop_logo" alt="">
{{items.shop_name}}
</div>
<div class="lighter sm" v-if="type == 'normal'">
申请时间{{items.create_time}}
</div>
<div class="lighter sm" style="margin-left: 110px" v-else>
下单时间{{items.after_sale.status_text}}
</div>
<div class="lighter sm" style="margin-left: 110px" v-if="type == 'normal'">
订单编号{{items.after_sale.sn}}
</div>
<div class="lighter sm" style="margin-left: 110px" v-else>
退款编号{{items.after_sale.sn}}
</div>
</div>
<div class="primary sm" style="margin-right: 12px">
{{items.after_sale.type_text}}
</div>
</div>
<div class="after-sales-content" :class="{shadow: type != 'normal', border: type == 'normal'}">
<div class="goods-item flex row-between" v-for="(item, index) in items.order_goods" :key="index">
<div class="flex">
<el-image style="width: 72px;height: 72px" :src="item.image" />
<div class="goods-info">
<div class="goods-name noraml line1">
{{item.goods_name}}
</div>
<div class="muted sm m-t-8 m-b-8">
{{item.spec_value_str}}
</div>
<price-formate :price="item.goods_price" showSubscript color="#FF2C3C" />
</div>
</div>
<div class="flex row-right" :style="{width: type != 'apply' ? null : '340px'}">
<el-button class="apply-btn row-center mr20 sm"
@click.stop="goPage(items.order_id, item.item_id)" v-if="type == 'normal'" size="small">申请售后
</el-button>
<el-button class="apply-btn row-center mr20 sm" v-if="type != 'normal'" size="small"
@click="goToDetail(items.after_sale.after_sale_id)">查看详情</el-button>
<el-button class="apply-btn row-center mr20 sm" v-if="type == 'apply'" size="small"
@click.stop="cancelApply(items.after_sale.after_sale_id)">撤销申请</el-button>
<el-button class="apply-btn row-center mr20 sm" v-if="items.after_sale.status==2" size="small"
@click.stop="showInput(items.after_sale.after_sale_id)">填写快递单号</el-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { AfterSaleType } from "@/utils/type";
export default {
props: {
type: {
type: String,
default: AfterSaleType.NORMAL,
},
lists: {
type: Array,
default: () => [],
},
},
data() {
return {};
},
methods: {
goToDetail(id) {
switch (this.type) {
case AfterSaleType.NORMAL:
this.$router.push("/goods_details/" + id);
break;
case AfterSaleType.HANDLING:
case AfterSaleType.FINISH:
this.$router.push(
"/user/after_sales/after_sale_details?afterSaleId=" + id
);
break;
}
},
goPage(orderId, itemId) {
this.$router.push(
"/user/after_sales/apply_sale?order_id=" +
orderId +
"&item_id=" +
itemId
);
},
showInput(e) {
this.$emit("show", e);
},
async cancelApply(afterSaleId) {
let res = await this.$post("after_sale/cancel", {
id: afterSaleId,
});
if (res.code == 1) {
this.$message({
message: res.msg,
type: "success",
});
this.$emit("refresh");
}
},
},
};
</script>
<style lang="scss" scoped>
.after-sales-list {
.after-sales-header {
border: 1px solid #e5e5e5;
background-color: #f2f2f2;
padding: 13px 16px;
}
.after-sales-content {
.goods-item {
padding: 10px 20px;
.goods-info {
margin-left: 10px;
width: 500px;
}
.apply-btn {
border: 1px solid #cccccc;
border-radius: 2px;
width: 100px;
height: 32px;
align-self: flex-start;
&:nth-of-type(2n) {
margin-left: 10px;
}
&:nth-of-type(3) {
margin-left: 10px;
}
&:nth-of-type(4) {
}
}
}
}
.shadow {
box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.08);
}
.border {
border-bottom: 1px solid #e5e5e5;
}
}
</style>

View File

@ -0,0 +1,144 @@
<template>
<div class="comment-list">
<div class="comment-con">
<template v-if="commentList.length">
<div
class="item flex"
v-for="(item, index) in commentList"
:key="index"
>
<div class="avatar m-r-8">
<img :src="item.avatar" alt="" />
</div>
<div class="content flex-1">
<div>{{ item.nickname }}</div>
<div class="lighter" style="margin: 5px 0 10px">
<span>{{ item.create_time }}</span>
<span>|</span>
<span>规格{{ item.spec_value_str }}</span>
</div>
<div>
{{ item.comment }}
</div>
<div class="comment-imglist flex">
<div
class="item"
v-for="(img, index) in item.image"
:key="index"
>
<el-image
:preview-src-list="item.image"
:src="img"
style="height: 100%; width: 100%"
fit="contain"
></el-image>
</div>
</div>
<div class="flex reply m-t-16" v-if="item.reply">
<div class="primary flex-none">商家回复</div>
<div class="lighter">
{{ item.reply }}
</div>
</div>
</div>
</div>
<div
class="pagination flex row-center"
style="padding: 38px 0"
v-if="count"
>
<el-pagination
background
hide-on-single-page
layout="prev, pager, next"
:total="count"
:page-size="10"
@current-change="changePage"
>
</el-pagination>
</div>
</template>
<null-data
v-else
:img="require('~/static/images/news_null.png')"
text="暂无评价~"
></null-data>
</div>
</div>
</template>
<script>
export default {
components: {},
props: {
list: {
type: Array,
default: () => [],
},
type: Number,
goodsId: [String, Number],
},
data() {
return {
commentList: [],
count: 0,
page: 1,
}
},
created() {
this.getCommentList()
},
methods: {
async getCommentList() {
const { data, code } = await this.$get('goods_comment/lists', {
params: {
type: this.type,
goods_id: this.goodsId,
page_size: 10,
page_no: this.page,
},
})
if (code == 1) {
this.commentList = data.lists
this.count = data.count
}
},
changePage(current) {
this.page = current
this.getCommentList()
},
},
}
</script>
<style lang="scss" scoped>
.comment-list {
.comment-con {
& > .item {
padding: 20px;
border-bottom: 1px dashed #e5e5e5;
align-items: flex-start;
.avatar {
img {
border-radius: 50%;
width: 44px;
height: 44px;
}
}
.comment-imglist {
margin-top: 10px;
.item {
width: 80px;
height: 80px;
margin-right: 6px;
}
}
.reply {
background-color: #f2f2f2;
align-items: flex-start;
padding: 10px;
}
}
}
}
</style>

View File

@ -0,0 +1,107 @@
<template>
<div v-if="time >= 0">
<client-only>
<slot v-if="isSlot"></slot>
<span v-else>{{ formateTime }}</span>
</client-only>
</div>
</template>
<script>
import { parseTimeData, parseFormat } from '~/utils/parseTime'
export default {
components: {},
props: {
isSlot: {
type: Boolean,
default: false,
},
time: {
type: Number,
default: 0,
},
format: {
type: String,
default: 'hh:mm:ss',
},
autoStart: {
type: Boolean,
default: true,
},
},
watch: {
time: {
immediate: true,
handler(value) {
if (value) {
this.reset()
}
},
},
},
data() {
return {
timeObj: {},
formateTime: 0,
}
},
created() {},
computed: {},
methods: {
createTimer(fn) {
return setTimeout(fn, 100)
},
isSameSecond(time1, time2) {
return Math.floor(time1) === Math.floor(time2)
},
start() {
if (this.counting) {
return
}
this.counting = true
this.endTime = Date.now() + this.remain * 1000
this.setTimer()
},
setTimer() {
this.tid = this.createTimer(() => {
let remain = this.getRemain()
if (!this.isSameSecond(remain, this.remain) || remain === 0) {
this.setRemain(remain)
}
if (this.remain !== 0) {
this.setTimer()
}
})
},
getRemain() {
return Math.max(this.endTime - Date.now(), 0)
},
pause() {
this.counting = false
clearTimeout(this.tid)
},
reset() {
this.pause()
this.remain = this.time
this.setRemain(this.remain)
if (this.autoStart) {
this.start()
}
},
setRemain(remain) {
const { format } = this
this.remain = remain
const timeData = parseTimeData(remain)
this.formateTime = parseFormat(format, timeData)
this.$emit('change', timeData)
if (remain === 0) {
this.pause()
this.$emit('finish')
}
},
},
}
</script>
<style lang="scss">
</style>

View File

@ -0,0 +1,243 @@
<template>
<div class="coupons-list flex">
<template v-for="(item, index) in couponsList">
<div v-show="item.isShow" class="item" :key="index" @click.capture="onHandle(item.id, item.is_get)">
<div :class="[
'info white',
{ gray: type == 2 || type == 1 || item.is_get },
]">
<div class="info-hd flex">
<div>
<price-formate :price="item.money" :first-size="38" :second-size="38" />
</div>
<div class="m-l-8 flex1">
<div class="line1">{{ item.name }}</div>
<div class="xs line1">{{ item.condition_type_desc }}</div>
</div>
</div>
<div class="info-time xs">{{ item.user_time_desc }}</div>
</div>
<div class="tips flex row-between" @click.stop="onShowTips(index)">
<div class="muted xs">{{ item.use_scene_desc }}</div>
<div v-if="item.use_goods_type != 1 && (type == 1 || type == 2 || type == 0)">
<i :class="
showTips[index] ? 'el-icon-arrow-up' : 'el-icon-arrow-down'
"></i>
<div class="tips-con xs lighter" v-if="item.use_scene_desc != '全场通用' && showTips[index]">
{{ item.use_goods_desc }}
</div>
</div>
<div class="primary sm" v-if="type == 3 && !item.is_get">
立即领取
</div>
</div>
<img v-if="item.is_get" class="receice" src="~/static/images/coupons_img_receive.png" alt="" />
<div class="choose xs" v-if="type == 4 && id == item.id"></div>
</div>
</template>
<div class="more muted" v-if="showMore && list.length > 4" @click="changeShow">
{{ isMore ? '收起' : '更多' }}
<i :class="isMore ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
</div>
</div>
</template>
<script>
import {
mapActions
} from "vuex";
export default {
props: {
list: {
type: Array,
default: () => [],
},
type: {
type: Number,
},
showMore: {
type: Boolean,
default: false,
},
},
data() {
return {
showTips: [],
couponsList: [],
id: "",
isMore: false,
};
},
methods: {
...mapActions(["getPublicData"]),
onHandle(id, isGet) {
this.id = id;
const {
type
} = this;
switch (type) {
case 0:
// 使
break;
case 1:
break;
// 使
case 2:
break;
//
case 3:
//
if(!isGet) {
this.getCoupon();
}
break;
case 4:
//使
if (this.selectId == id) {
this.id = "";
}
this.$emit("use", this.id);
this.selectId = this.id;
break;
}
},
async getCoupon() {
const {
msg,
code
} = await this.$post("coupon/getCoupon", {
coupon_id: this.id,
});
if (code == 1) {
this.$message({
message: msg,
type: "success",
});
this.getPublicData();
this.$emit("reflash");
}
},
onShowTips(index) {
const {
showTips
} = this;
this.showTips[index] = showTips[index] ? 0 : 1;
//
this.showTips = Object.assign([], this.showTips);
},
changeShow() {
this.isMore = !this.isMore;
this.list.forEach((item, index) => {
item.isShow = true;
if (!this.isMore && index >= 4) {
item.isShow = false;
}
});
this.couponsList = [...this.list];
},
},
watch: {
list: {
handler: function(val) {
if (val.length) {
//
if (this.type == 4) {
this.id = val[0].id;
this.selectId = this.id;
this.$emit("use", this.id);
}
}
let arr = val.map((item) => {
return 0;
});
this.showTips = arr;
this.list.forEach((item, index) => {
item.isShow = true;
if (this.showMore) {
if (index >= 4) {
item.isShow = false;
}
}
});
this.couponsList = this.list;
},
immediate: true,
deep: true,
},
},
};
</script>
<style lang="scss" scoped>
.coupons-list {
padding: 0 18px;
flex-wrap: wrap;
position: relative;
.item {
margin-bottom: 20px;
margin-right: 16px;
position: relative;
cursor: pointer;
.info {
padding: 0 10px;
background: url("~/static/images/bg_coupon_s.png") no-repeat;
width: 240px;
height: 80px;
background-size: 100%;
&.gray {
background-image: url("~/static/images/bg_coupon.png");
}
.info-hd {
overflow: hidden;
}
}
.tips {
position: relative;
background-color: #f2f2f2;
height: 30px;
padding: 0 8px;
.tips-con {
width: 100%;
left: 0;
background-color: #f2f2f2;
position: absolute;
top: 30px;
padding: 10px;
z-index: 99;
}
}
.receice {
position: absolute;
top: 0;
right: 0;
width: 58px;
height: 45px;
}
.choose {
position: absolute;
top: 0;
right: 0;
background-color: #ffe72c;
color: $--color-primary;
padding: 1px 5px;
}
}
.more {
position: absolute;
bottom: 20px;
cursor: pointer;
right: 30px;
}
}
</style>

View File

@ -0,0 +1,209 @@
<template>
<div class="deliver-search-container">
<el-dialog :visible.sync="showDialog" top="30vh" width="900px" title="物流查询">
<div class="deliver-box">
<div class="deliver-recode-box flex">
<div class="recode-img">
<el-image style="width: 100%; height: 100%" fit="cover" :src="deliverOrder.image" />
<div class="float-count flex row-center">{{deliverOrder.count}}件商品</div>
</div>
<div class="recode-info-container m-l-10">
<div class="flex">
<div class="recode-label">物流状态</div>
<div class="primary lg" style="font-weight: 500">{{deliverOrder.tips}}</div>
</div>
<div class="flex" style="margin: 6px 0;">
<div class="recode-label">快递公司</div>
<div >{{deliverOrder.shipping_name}}</div>
</div>
<div class="flex">
<div class="recode-label">快递单号</div>
<div>{{deliverOrder.invoice_no}}</div>
<div class="copy-btn primary flex row-center" @click="onCopy"></div>
</div>
</div>
</div>
<div class="deliver-flow-box m-t-16">
<el-timeline>
<!-- 收货 -->
<el-timeline-item
v-if="deliverFinish.tips"
>
<div>
<div class="flex lg">
<div class="m-r-8" style="font-weight: 500">
{{deliverTake.contacts}}
</div>
<div style="font-weight: 500">{{deliverTake.mobile}}</div>
</div>
<div class="lighter m-t-8">{{deliverTake.address}}</div>
</div>
</el-timeline-item>
<!-- 交易状态 -->
<el-timeline-item
v-if="deliverFinish.tips"
:timestamp="deliverFinish.time"
>
<div class="time-line-title">{{deliverFinish.title}}</div>
<div>{{deliverFinish.tips}}</div>
</el-timeline-item>
<!-- 跟踪物流 -->
<el-timeline-item
v-if="delivery.traces && delivery.traces.length"
:timestamp="delivery.time"
>
<div class="time-line-title m-b-8">{{delivery.title}}</div>
<el-timeline-item
v-for="(item, index) in delivery.traces"
:key="index"
:timestamp="item[0]"
>
<div class="muted">{{item[1]}}</div>
</el-timeline-item>
</el-timeline-item>
<!-- 完成 -->
<el-timeline-item
v-if="deliverShipment.tips"
:timestamp="deliverShipment.time"
>
<div class="time-line-title">{{deliverShipment.title}}</div>
<div>{{deliverShipment.tips}}</div>
</el-timeline-item>
<!-- 下单 -->
<el-timeline-item
v-if="deliverBuy.tips"
:timestamp="deliverBuy.time"
>
<div class="time-line-title">{{deliverBuy.title}}</div>
<div>{{deliverBuy.tips}}</div>
</el-timeline-item>
</el-timeline>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
props: {
value: {
type: Boolean,
default: false,
},
aid: {
type: Number | String
}
},
data() {
return {
showDialog: false,
deliverBuy: {},
delivery: {},
deliverFinish: {},
deliverOrder: {},
deliverShipment: {},
deliverTake: {},
timeLineArray: []
}
},
watch: {
value(val) {
console.log(val, 'val')
this.showDialog = val;
},
showDialog(val) {
if(val) {
if(this.aid) {
this.timeLineArray = []
this.getDeliverTraces();
}
}
this.$emit("input", val);
},
},
methods: {
async getDeliverTraces() {
let data = {
id: this.aid
}
let res = await this.$get("order/orderTraces", {params: data});
if(res.code == 1) {
let {buy, delivery, finish, order, shipment, take} = res.data
this.deliverBuy = buy;
this.delivery = delivery;
this.deliverFinish = finish;
this.deliverOrder = order;
this.deliverShipment = shipment;
this.deliverTake = take;
this.timeLineArray.push(this.deliverFinish);
this.timeLineArray.push(this.delivery);
this.timeLineArray.push(this.deliverShipment);
this.timeLineArray.push(this.deliverBuy);
console.log(this.timeLineArray)
}
},
onCopy() {
// this.deliverOrder.invoice_no;
let oInput = document.createElement('input');
oInput.value = this.deliverOrder.invoice_no;
document.body.appendChild(oInput);
oInput.select();
document.execCommand("Copy");
this.$message.success("复制成功");
oInput.remove();
}
}
}
</script>
<style lang="scss" scoped>
.deliver-search-container {
.deliver-box {
.deliver-recode-box {
padding: 10px 20px;
background-color: #F2F2F2;
.recode-img {
position: relative;
width: 72px;
height: 72px;
.float-count {
position: absolute;
bottom: 0;
height: 20px;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
color: white;
font-size: 12px;
}
}
.recode-info-container {
flex: 1;
.recode-label {
width: 70px;
}
.copy-btn {
height: 20px;
min-width: 42px;
border: 1px solid $--color-primary;
font-size: 12px;
margin-left: 8px;
border-radius: 60px;
cursor: pointer;
&:hover {
background-color: white;
}
}
}
}
.deliver-flow-box {
padding-left: 15px;
}
.time-line-title {
font-weight: 500px;
font-size: 16px;
margin-bottom: 10px;
}
}
}
</style>

View File

@ -0,0 +1,257 @@
<template>
<div class="evaluation-list">
<div class="list1" v-if="type == 1">
<div class="item flex" v-for="(item, index) in list" :key="index">
<div class="goods">
<!-- 店铺信息 -->
<div class="flex shop-info">
<div class="flex" style="margin-right: 100px;">
<div class="m-r-8" style="width: 16px; height: 16px;">
<el-image :src="item.shop.logo" style="height: 100%; width: 100%" fit="contain">
</el-image>
</div>
<div class="xs">
{{item.shop.name}}
</div>
</div>
<div class="xs muted" style="margin-right: 100px;">
下单时间{{item.create_time}}
</div>
<div class="xs muted">
订单编号{{item.order_sn}}
</div>
</div>
<div class="goods-all">
<div class="goods-item flex" v-for="(zitem, zindex) in item.order_goods_un_comment">
<nuxt-link :to="`/goods_details/${zitem.goods_id}`">
<el-image class="goods-img" :src="zitem.goods_item.image" alt="" />
</nuxt-link>
<div class="goods-info flex-col flex-1">
<div class="goods-name flex row-between" style="align-items: flex-start;">
<div class="line1" style="width: 600px">
{{ zitem.goods_name }}
</div>
<div class="operate flex row-end">
<nuxt-link :to="`/user/evaluation/evaluate?id=${zitem.id}`"
class="btn sm flex row-center white">去评价</nuxt-link>
</div>
</div>
<div class="sm lighter m-b-8">{{zitem.goods_item.spec_value_str}}</div>
<!-- 价格 -->
<div class="primary">
<price-formate :price="zitem.goods_price" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="list2 flex-col" v-if="type == 2">
<div class="item flex" v-for="(item, index) in list" :key="index">
<div class="user">
<el-image :src="userInfo.avatar" style="height: 44px; width: 44px; border-radius: 50%;"></el-image>
</div>
<div class="">
<div class="user_name m-b-5" style="font-size: 14px; color: #101010;">
{{ userInfo.nickname }}
</div>
<div class="muted sm">评价时间{{ item.create_time }}</div>
<!-- 用户评价 -->
<div class="m-t-10">
{{ item.comment }}
</div>
<!-- 用户展示商品图片 -->
<div class="comment-imglist flex">
<div class="item" v-for="(img, index) in item.goods_comment_image_arr" :key="index">
<el-image :preview-src-list="item.goods_comment_image_arr" :src="img"
style="height: 100%; width: 100%" fit="contain">
</el-image>
</div>
</div>
<!-- 商家回复 -->
<div class="flex reply mt16" v-if="item.reply">
<div class="primary">商家回复</div>
<div class="lighter">
{{ item.reply }}
</div>
</div>
<!-- 商品信息 -->
<nuxt-link :to="`/goods_details/${item.goods.id}`">
<div class="goods flex m-t-16">
<el-image class="goods-img" :src="item.goods.image" alt="" />
<div class="goods-info m-l-10">
<div class="flex m-b-8">
<div class="flex" style="width: 451px;">
<div class="xs line-1 m-r-5">{{item.goods.name}}</div>
<div class="xs">{{item.goods_item.spec_value_str}}</div>
</div>
<div class="flex">
<el-image :src="item.shop_logo" style="height: 16px; width: 16px" fit="contain">
</el-image>
<div class="m-l-5 xs">
{{item.shop_name}}
</div>
</div>
</div>
<div class="m-t-8 primary">
<price-formate :price="item.order_goods.total_pay_price" />
</div>
</div>
</div>
</nuxt-link>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: () => [],
},
type: {
type: String,
},
userInfo: {
type: Object,
default: () => {},
}
},
data() {
return {
lists: [{
image: "fdasf",
goods_name: "hsdfsafsa",
id: " ",
spec_value_str: " spec_value_str",
goods_price: '100',
}]
}
}
};
</script>
<style lang="scss" scoped>
.evaluation-list {
padding: 0 10px;
.list1 {
.shop-info {
padding: 10px 16px;
background-color: #F6F6F6;
}
.item {
.item-hd {
height: 40px;
background: #f2f2f2;
padding: 0 20px;
.status {
width: 300px;
text-align: right;
}
}
align-items: stretch;
.goods {
padding-bottom: 16px;
.goods-all {
border: 1px solid #e5e5e5;
padding-top: 16px;
}
.goods-item {
padding: 0 16px 16px 16px;
.goods-img {
margin-right: 10px;
width: 72px;
height: 72px;
}
}
}
.operate {
width: 200px;
.btn {
background-color: $--color-primary;
width: 104px;
height: 32px;
border: 1px solid $--border-base;
border-radius: 2px;
cursor: pointer;
}
}
}
}
.list2 {
.user {
margin-right: 14px;
}
&>.item {
width: 920px;
padding: 15px 0px;
border-bottom: 1px dashed #e5e5e5;
align-items: flex-start;
.avatar {
img {
border-radius: 50%;
width: 44px;
height: 44px;
}
}
.comment-imglist {
margin-top: 10px;
.item {
width: 80px;
height: 80px;
margin-right: 6px;
}
}
.reply {
background-color: #F6F6F6;
align-items: flex-start;
padding: 10px;
}
.goods {
width: 922px;
background-color: #F6F6F6;
padding: 14px;
.goods-img {
width: 72px;
height: 72px;
}
}
}
}
}
</style>

View File

@ -0,0 +1,113 @@
<template>
<div class="goods-list flex flex-wrap">
<nuxt-link :to="`/goods_details/${item.id||item.goods_id}`" class="goods-item bg-white"
:style="{ marginRight: (index + 1) % num == 0 ? 0 : '14px' }" v-for="(item, index) in list" :key="index">
<el-image class="goods-img" lazy :src="item.image||item.goods_image" alt=""></el-image>
<div class="name line-2">{{ item.name||item.goods_name }}</div>
<div class="seckill flex row-between" v-if="type == 'seckill'">
<div class="primary flex">
秒杀价
<price-formate :price="item.seckill_price" :first-size="18" />
</div>
<div :class="['btn bg-primary white', {'not-start' : status == 0, end: status == 2}]">{{getSeckillText}}
</div>
</div>
<div class="flex row-between flex-wrap" v-else>
<div class="price flex col-baseline">
<div class="primary m-r-8">
<price-formate :price="item.min_price || item.price" :first-size="16" />
</div>
<div class="muted sm line-through">
<price-formate :price="item.market_price" />
</div>
</div>
<div class="muted xs">{{ item.sales_total || item.sales_sum || 0}}人购买</div>
</div>
</nuxt-link>
</div>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: () => [],
},
num: {
type: Number,
default: 5,
},
type: {
type: String,
},
status: {
type: Number,
},
},
watch: {
list: {
immediate: true,
handler: function (val) {},
},
},
computed: {
getSeckillText() {
switch (this.status) {
case 0:
return "未开始";
case 1:
return "立即抢购";
case 2:
return "已结束";
}
},
},
};
</script>
<style lang="scss" scoped>
.goods-list {
align-items: stretch;
.goods-item {
display: block;
box-sizing: border-box;
width: 224px;
height: 310px;
margin-bottom: 16px;
padding: 12px 12px 16px;
border-radius: 4px;
transition: all 0.2s;
&:hover {
transform: translateY(-8px);
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1);
}
.goods-img {
width: 200px;
height: 200px;
}
.name {
margin-bottom: 10px;
height: 40px;
line-height: 20px;
}
.seckill {
.btn {
padding: 4px 12px;
border-radius: 4px;
border: 1px solid transparent;
&.not-start {
border-color: $--color-primary;
color: $--color-primary;
background-color: transparent;
}
&.end {
background-color: #e5e5e5;
color: #fff;
}
}
}
}
}
</style>

View File

@ -0,0 +1,197 @@
<template>
<div class="seckill card" v-if="goodsList.length">
<div class="seckill-header flex">
<div class="title font-size-20">限时秒杀</div>
<div class="flex-1 flex">
<i
class="
el-icon-alarm-clock
primary
font-size-24
m-l-20 m-r-10
"
></i>
<count-down
:time="countTime"
:is-slot="true"
@change="onChangeDate"
@finish="refresh"
>
<div class="flex row-center count-down xs">
<div class="item white">{{ timeData.hours }}</div>
<div class="white" style="margin: 0 4px">:</div>
<div class="item white">{{ timeData.minutes }}</div>
<div class="white" style="margin: 0 4px">:</div>
<div class="item white">{{ timeData.seconds }}</div>
</div>
</count-down>
</div>
<nuxt-link to="/seckill" class="more lighter"
>更多 <i class="el-icon-arrow-right"></i
></nuxt-link>
</div>
<div class="seckill-list m-t-16">
<el-carousel :interval="3000" arrow="never" height="320px" indicator-position="outside">
<el-carousel-item
v-for="(item, index) in swiperSize"
:key="index"
>
<div class="goods-list flex">
<nuxt-link
class="goods-item"
:to="`/goods_details/${gitem.goods_id}`"
v-for="(gitem, gindex) in getSwiperList(index)"
:key="gindex"
>
<div class="goods-img">
<el-image
:src="gitem.goods_image"
fit="cover"
alt=""
></el-image>
</div>
<div class="name line-2 m-t-10">
{{ gitem.goods_name }}
</div>
<div class="price flex col-baseline">
<div class="primary m-r-8">
<price-formate
:price="gitem.seckill_price"
:first-size="16"
/>
</div>
<div class="muted sm line-through">
<price-formate
:price="gitem.seckill_total"
/>
</div>
</div>
<div class="muted xs m-t-10">
{{ gitem.seckill_total }}人购买
</div>
</nuxt-link>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
export default {
components: {},
props: {
list: {
type: Array,
default: () => [],
},
},
data() {
return {
active: -1,
goodsList: [],
countTime: 0,
timeData: {},
pageSize: 5,
}
},
methods: {
refresh() {
this.$emit('refreshhome')
},
onChangeDate(e) {
let timeData = {}
for (let prop in e) {
if (prop !== 'milliseconds')
timeData[prop] = ('0' + e[prop]).slice(-2)
}
this.timeData = timeData
},
},
watch: {
list: {
handler(val) {
//
let index = val.findIndex((item) => item.status == 1)
if (index == -1) {
//
index = val.findIndex((item) => item.status == 0)
}
if (index == -1) {
//
index = val.length - 1
}
this.active = index
this.goodsList = val[index].goods
this.countTime = val[index].end_time_int - Date.now() / 1000
},
immediate: true,
},
},
computed: {
swiperSize() {
console.log(Math.ceil(this.goodsList.length / this.pageSize))
return Math.ceil(this.goodsList.length / this.pageSize)
},
getSwiperList() {
return (index) => {
return this.goodsList.slice(
index * this.pageSize,
(index + 1) * this.pageSize
)
}
},
},
}
</script>
<style lang="scss" scoped>
.seckill {
.seckill-header {
.count-down {
.item {
width: 38px;
height: 20px;
background: $--color-primary;
text-align: center;
line-height: 20px;
border-radius: 4px;
}
}
}
::v-deep .el-carousel__indicator {
& .el-carousel__button {
background-color: #E5E5E5;
}
&.is-active .el-carousel__button{
background-color: $--color-primary;
}
}
.goods-list {
.goods-item {
width: 216px;
& ~ .goods-item {
margin-left: 16px;
}
.goods-img {
width: 100%;
height: 0;
padding-top: 100%;
position: relative;
::v-deep .el-image {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
}
.name {
line-height: 20px;
height: 40px;
}
}
}
}
</style>

View File

@ -0,0 +1,120 @@
<template>
<div class="input-express">
<el-dialog title="填写快递单号" :visible.sync="showDialog" width="926px">
<el-form inline ref="inputForm" label-width="100px" :model="form" :rules="rules">
<el-form-item label="物流公司:" prop="business">
<el-input size="small" v-model="form.business" placeholder="请输入物流公司名称" />
</el-form-item>
<el-form-item label="快递单号:" prop="number">
<el-input size="small" v-model="form.number" placeholder="请输入快递单号" />
</el-form-item>
<el-form-item label="备注说明:" prop="desc">
<el-input style="width: 632px" type="textarea" v-model="form.desc" placeholder="请输入详细内容,选填"
resize="none" rows="5" />
</el-form-item>
<el-form-item label="上传凭证:" prop="upload">
<div class="xs muted">请上传快递单号凭证选填</div>
<upload isSlot :file-list="fileList" @success="uploadSuccess" :limit="3">
<div class="column-center" style="height: 100%">
<i class="el-icon-camera xs" style="font-size: 24px" />
</div>
</upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"></el-button>
<el-button @click="showDialog = false">取消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
components: {
},
data() {
return {
showDialog: false,
form: {
//
business: "",
//
number: "",
//
desc: "",
},
rules: {
business: [{ required: true, message: "请输入物流公司" }],
number: [{ required: true, message: "请输入快递单号" }],
},
fileList: [],
};
},
props: {
value: {
type: Boolean,
default: false,
},
aid: {
type: [String, Number],
default: -1,
},
},
methods: {
submitForm() {
console.log(this.$refs);
this.$refs["inputForm"].validate(async (valid) => {
if (valid) {
let fileList = [];
this.fileList.forEach((item) => {
fileList.push(item.response.data);
});
let data = {
id: this.aid,
express_name: this.form.business,
invoice_no: this.form.number,
express_remark: this.form.desc,
express_image:
fileList.length <= 0 ? "" : fileList[0].base_url,
};
let res = await this.$post("after_sale/express", data);
if (res.code == 1) {
this.$message({
message: "提交成功",
type: "success",
});
this.showDialog = false;
this.$emit("success");
}
} else {
return false;
}
});
},
uploadSuccess(e) {
let fileList = Object.assign([], e);
this.fileList = fileList;
},
},
watch: {
value(val) {
this.showDialog = val;
},
showDialog(val) {
this.$emit("input", val);
},
},
};
</script>
<style lang="scss" scoped>
.input-express {
.dialog-footer {
text-align: center;
.el-button {
width: 160px;
}
}
}
</style>

View File

@ -0,0 +1,96 @@
<template>
<aside class="aside-nav bg-white">
<div class="nav">
<div class="title lg">订单中心</div>
<ul>
<li>
<nuxt-link to="/user/order">我的订单</nuxt-link>
</li>
<li>
<nuxt-link to="/user/evaluation">评价中心</nuxt-link>
</li>
<li>
<nuxt-link to="/user/after_sales">退款/售后</nuxt-link>
</li>
</ul>
</div>
<div class="nav">
<div class="title lg">我的资产</div>
<ul>
<li>
<nuxt-link to="/user/coupons"
>优惠券 ({{ publicData.coupon_num }})</nuxt-link
>
</li>
<li>
<nuxt-link to="/user/user_wallet">我的钱包</nuxt-link>
</li>
</ul>
<div class="nav">
<div class="title lg">我的服务</div>
<ul>
<li>
<nuxt-link to="/user/collection">我的收藏</nuxt-link>
</li>
<li>
<nuxt-link to="/user/address">地址管理</nuxt-link>
</li>
<li>
<nuxt-link to="/user/profile">个人资料</nuxt-link>
</li>
</ul>
</div>
</div>
</aside>
</template>
<script>
import { mapState } from 'vuex'
export default {
created() {},
computed: {
...mapState(['publicData']),
},
}
</script>
<style lang="scss" scoped>
.aside-nav {
width: 160px;
min-height: 680px;
padding: 20px 0;
margin-right: 16px;
box-sizing: border-box;
.nav {
.title {
padding: 14px 32px;
font-weight:bold;
}
ul {
li {
a {
display: block;
padding: 10px 32px;
font-weight:bold;
&.nuxt-link-active {
position: relative;
color: $--color-primary;
background-color: #ffeeef;
&::before {
position: absolute;
content: '';
display: block;
width: 2px;
height: 30px;
left: 0;
top: 50%;
transform: translateY(-50%);
background-color: $--color-primary;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,178 @@
<template>
<div class="category" @mouseenter="showCate = true" @mouseleave="leaveCate">
<el-button @click="$router.push('/category')" type="primary" class="title">
<div class="flex lg">
<i class="el-icon-s-fold"></i>
<div class="m-l-8">全部商品分类</div>
</div>
</el-button>
<div class="category-con bg-white" v-show="category.length && showCate">
<ul class="category-one">
<li
v-for="(item, index) in category"
:key="index"
:class="{ active: index === selectIndex }"
@mouseenter="enterCate(index)"
>
<nuxt-link
class="flex row-between"
:to="`/category?id=${item.id}`"
>
<span class="line-1">{{ item.name }}</span>
<i
v-if="item.sons.length"
class="el-icon-arrow-right"
></i
></nuxt-link>
</li>
<div
class="category-float bg-white"
v-show="showCateFloat && cateTwo.length"
>
<div class="float-con">
<div
class="m-t-16"
v-for="(item, index) in cateTwo"
:key="index"
>
<div class="category-two weight-500 m-b-15">
<nuxt-link :to="`/category?id=${item.id}`">{{
item.name
}}</nuxt-link>
</div>
<div class="category-three flex flex-wrap">
<div
class="item"
v-for="(titem, idx) in item.sons"
:key="idx"
>
<nuxt-link
:to="`/category?id=${titem.id}`"
class="flex"
>
<el-image
style="width: 48px; height: 48px;display:none"
:src="titem.image"
fit="contain"
></el-image>
<span class="m-l-8">{{
titem.name
}}</span>
</nuxt-link>
</div>
</div>
</div>
</div>
</div>
</ul>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
cateTwo: [],
showCateFloat: false,
showCate: false,
selectIndex: '',
}
},
created() {
console.log(this.category)
},
methods: {
enterCate(index) {
this.cateTwo = this.category[index].sons
this.showCateFloat = true
this.selectIndex = index
},
leaveCate() {
this.$route.path != '/' && (this.showCate = false)
this.selectIndex = ''
this.showCateFloat = false
},
},
watch: {
$route: {
immediate: true,
handler: function (val) {
this.showCate = val.path == '/' ? true : false
},
},
},
computed: {
...mapState(['category']),
},
}
</script>
<style lang="scss" scoped>
.category {
position: relative;
.title {
padding: 12px 20px;
flex: none;
width: 160px;
box-sizing: border-box;
border-radius: 0;
}
.category-con {
position: absolute;
width: 100%;
z-index: 999;
height: 440px;
padding: 10px 0;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
.category-one {
height: 100%;
overflow-y: auto;
&::-webkit-scrollbar {
display: none; /*隐藏滚动条*/
}
li {
& > a {
height: 42px;
padding: 0 10px;
}
&.active {
background-color: #ffeeef;
a {
color: #ff2c3c;
}
}
}
.category-float {
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
position: absolute;
left: 160px;
top: 0;
width: 880px;
height: 440px;
padding: 0 24px;
overflow-y: auto;
&::-webkit-scrollbar {
display: none; /*隐藏滚动条*/
}
a:hover {
color: #ff2c3c;
}
.float-con {
.category-three {
border-bottom: 1px dashed $--border-color-base;
.item {
width: 20%;
margin-bottom: 20px;
padding-right: 10px;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,144 @@
<template>
<div class="float-nav bg-white flex-col col-center">
<div class="nav-list">
<nuxt-link to="/shop_cart" class="item flex-col col-center lighter">
<el-badge :value="publicData.cart_num" type="primary">
<span class="iconfont icon-cart-Empty"></span>
</el-badge>
<div class="sm">购物车</div>
</nuxt-link>
<nuxt-link
class="item flex-col col-center lighter"
to="/user/coupons"
>
<el-badge :value="publicData.coupon_num" type="primary">
<span class="iconfont icon-coupons"></span>
</el-badge>
<div class="sm">优惠券</div>
</nuxt-link>
<nuxt-link
class="item flex-col col-center lighter"
to="/user/order"
>
<span class="iconfont icon-icon_order"></span>
<div class="sm">订单</div>
</nuxt-link>
<nuxt-link
class="item flex-col col-center lighter"
to="/user/collection"
>
<span class="iconfont icon-collection"></span>
<div class="sm">收藏</div>
</nuxt-link>
<nuxt-link
class="item flex-col col-center lighter"
to="/help_center"
>
<span class="iconfont icon-survey"></span>
<div class="sm">帮助</div>
</nuxt-link>
<el-popover placement="left" width="165" trigger="hover">
<div
style="text-align: center; margin: 0"
class="flex-col col-center"
>
<img
style="width: 100px; height: 100px"
:src="server.image"
alt=""
/>
<div class="sm m-t-8">{{ server.phone }}</div>
<div class="sm m-t-10">
在线时间{{ server.business_time }}
</div>
</div>
<div class="item flex-col col-center lighter" slot="reference">
<span class="iconfont icon-service"></span>
<div class="sm">客服</div>
</div>
</el-popover>
</div>
<div class="back-top">
<span class="iconfont icon-top" @click="scrollTop"></span>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
server: {},
}
},
created() {
this.getService()
},
methods: {
async getService() {
const { data, code } = await this.$get(
'setting/getPlatformCustomerService'
)
if (code == 1) {
this.server = data
}
},
scrollTop() {
cancelAnimationFrame(this.timer)
const self = this
this.timer = requestAnimationFrame(function fn() {
var oTop =
document.body.scrollTop ||
document.documentElement.scrollTop
if (oTop > 0) {
scrollTo(0, oTop - 250)
self.timer = requestAnimationFrame(fn)
} else {
cancelAnimationFrame(self.timer)
}
})
},
},
computed: {
...mapState(['publicData']),
},
}
</script>
<style lang="scss" scoped>
.float-nav {
height: 100vh;
position: fixed;
right: 0;
top: 0;
width: 60px;
z-index: 999;
box-shadow: -3px 1px 2px rgba(0, 0, 0, 0.04);
.nav-list {
position: absolute;
bottom: 120px;
.item {
padding: 10px 4px;
text-align: center;
cursor: pointer;
&:hover {
color: $--color-primary;
}
.iconfont {
font-size: 24px;
}
::v-deep .el-badge__content {
height: 16px;
line-height: 16px;
padding: 0 5px;
}
}
}
.back-top {
position: absolute;
bottom: 20px;
cursor: pointer;
}
}
</style>

View File

@ -0,0 +1,80 @@
<template>
<div class="footer-container">
<div class="footer-box flex row-center">
<div class="server-box flex row-between">
<div class="flex" v-for="(item, index) in lists" :key="index">
<i
:class="`white iconfont ${item.icon}`"
style="font-size: 50px"
/>
<div class="m-l-8 xxl name">{{ item.name }}</div>
</div>
</div>
</div>
<footer class="footer-wrap flex row-center">
<a class="white" target="_blank" :href="config.icp_link"
>{{ config.copyright_info }} {{ config.icp_number }}</a
>
</footer>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
lists: [
{
name: '自营商城',
icon: 'icon-ziying',
},
{
name: '正品保障',
icon: 'icon-zhengpin',
},
{
name: '专属服务',
icon: 'icon-fuwu',
},
{
name: '售后无忧',
icon: 'icon-peisong',
},
{
name: '极速配送',
icon: 'icon-shouhou',
},
],
}
},
computed: {
...mapState(['config']),
},
}
</script>
<style lang="scss" scoped>
.footer-container {
margin-top: 38px;
.footer-box {
height: 120px;
background-color: #222;
min-width: 1180px;
.server-box {
width: 1180px;
padding: 36px 40px;
border-bottom: 1px solid #707070;
.name {
color: #e5e5e5;
}
}
}
.footer-wrap {
min-width: 1180px;
background-color: #222;
height: 60px;
color: #ccc;
}
}
</style>

View File

@ -0,0 +1,368 @@
<template>
<header>
<div class="header-wrap">
<div class="header-con xs">
<div class="wrapper1180 flex row-between">
<div class="flex" style="height: 100%">
<template
v-if="
publicData.article && publicData.article.length
"
>
<img
style="
width: 16px;
height: 16px;
margin-right: 10px;
"
src="~/static/images/header_notice.png"
/>
<client-only>
<swiper
ref="headerSwiper"
:options="swiperOptions"
>
<swiper-slide
class="swiper-item"
v-for="(
item, index
) in publicData.article"
:key="index"
>
<nuxt-link
class="flex-col row-center"
style="height: 100%"
:to="
'/news_list/news_list_detail?id=' +
item.id
"
>
<div class="line1">
{{ item.title }}
</div>
</nuxt-link>
</swiper-slide>
</swiper>
</client-only>
</template>
</div>
<div class="user flex flex-none">
<div v-if="publicData.name">
您好欢迎来到 {{ publicData.name }}
</div>
<ul class="flex flex-none">
<li v-if="publicData.nickname">
<el-popover placement="bottom" trigger="hover">
<div class="user-nav">
<nuxt-link
class="lighter xs item"
to="/user/user_wallet"
>我的钱包</nuxt-link
>
<nuxt-link
class="lighter xs item"
to="/user/coupons"
>优惠券({{
publicData.coupon_num
}})</nuxt-link
>
<nuxt-link
class="lighter xs item"
to="/user/collection"
>我的收藏</nuxt-link
>
<div
class="lighter xs item"
@click="onLogout"
>
退出登录
</div>
</div>
<nuxt-link
slot="reference"
to="/user/profile"
>
{{ publicData.nickname }}
<i class="el-icon-arrow-down"></i>
</nuxt-link>
</el-popover>
</li>
<li v-else>
<nuxt-link to="/account/login">登录</nuxt-link>
<nuxt-link to="/account/register"
>注册</nuxt-link
>
</li>
<li>
<nuxt-link to="/user/order">我的订单</nuxt-link>
</li>
<li>
<nuxt-link to="/user/profile"
>个人中心</nuxt-link
>
</li>
<li>
<nuxt-link to="/help_center"
>帮助中心</nuxt-link
>
</li>
<li>
<nuxt-link to="/store_settled"
>商家入驻</nuxt-link
>
</li>
<li>
<nuxt-link to="/about_us"
>关于我们</nuxt-link
>
</li>
<!-- <li
id="tel-phone-block"
v-if="
publicData.mnp_qr_code ||
publicData.oa_qr_code
"
>
<nuxt-link to="/"
>手机端
<i class="el-icon-arrow-down"></i>
</nuxt-link>
<div class="float-code flex bg-white">
<div
class="flex-col col-center bg-white"
v-if="publicData.mnp_qr_code"
>
<img
style="width: 100px; height: 100px"
:src="publicData.mnp_qr_code"
alt=""
/>
<div class="lighter m-t-10">
官方小程序
</div>
</div>
</div>
</li> -->
<li>
<nuxt-link to="/">返回官网</nuxt-link>
</li>
</ul>
</div>
</div>
</div>
<div class="header-main bg-white">
<div class="wrapper1180">
<div class="search-wrap flex row-between">
<nuxt-link to="/" class="flex row-center">
<img
:src="config.shop_login_logo"
class="logo"
alt="logo"
/>
</nuxt-link>
<div class="flex">
<div class="search flex">
<input
type="text"
v-model="name"
placeholder="请输入要搜索的商品名称"
@keyup.enter="toSearch"
/>
<el-button
class="search-btn"
type="primary"
@click="toSearch"
>
搜索
</el-button>
</div>
<el-button type="primary" plain class="cart">
<nuxt-link to="/shop_cart"
>购物车({{
publicData.cart_num
}})</nuxt-link
>
</el-button>
</div>
</div>
</div>
</div>
</div>
</header>
</template>
<script>
import { directive } from 'vue-awesome-swiper'
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
directives: {
swiper: directive,
},
data() {
return {
name: '',
swiperOptions: {
direction: 'vertical',
// autoHeight: true,
height: 40,
initialSlide: 0,
autoplay: true,
},
}
},
methods: {
...mapMutations(['logout']),
...mapActions(['getPublicData']),
toSearch() {
if (!this.name) return this.$message.error('请输入商品名称')
this.$router.push({
path: '/search_goodsList',
query: {
name: this.name,
},
})
},
onLogout() {
this.logout()
this.$message({
message: '退出成功',
type: 'success',
})
setTimeout(() => location.reload(), 1500)
},
},
watch: {
$route: {
immediate: true,
handler: function (val) {
console.log(val)
if (val.path == '/goods_list') {
this.name = val.query.name
} else {
this.name = ''
}
},
},
},
computed: {
...mapState(['publicData', 'config']),
},
}
</script>
<style lang="scss" scoped>
.header-wrap {
min-width: 1180px;
position: relative;
z-index: 1000;
::v-deep .swiper-container {
margin-left: 0;
margin-right: 0;
height: 100%;
width: 400px;
}
.swiper-item {
color: #ccc;
height: 17px;
}
.header-con {
background-color: #101010;
height: 40px;
color: #f2f2f2;
> div {
height: 100%;
color: #cccccc;
a {
color: #cccccc;
&:hover {
color: #fff;
}
}
ul {
li {
margin-left: 20px;
}
#tel-phone-block {
position: relative;
&:hover .float-code {
display: flex;
box-shadow: 0 2px 8px 0 rgb(0 0 0 / 10%);
}
.float-code {
display: none;
position: absolute;
padding: 22px 16px;
background-color: white;
top: 24px;
right: -20px;
&::after {
content: '';
width: 8px;
box-shadow: 0 2px 8px 0 rgb(0 0 0 / 10%);
transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
right: 35px;
top: -4px;
height: 8px;
background-color: #fff;
position: absolute;
}
}
}
}
}
}
.header-main {
.search-wrap {
height: 80px;
.logo {
height: 48px;
width: auto;
}
.search {
width: 460px;
height: 42px;
overflow: hidden;
input {
flex: 1;
height: 100%;
border-radius: 4px 0 0 4px;
border: 1px solid $--color-primary;
border-right-width: 0;
padding: 0 10px;
}
.search-btn {
width: 82px;
height: 42px;
cursor: pointer;
border-radius: 0 4px 4px 0;
}
}
.cart {
cursor: pointer;
border-radius: 4px;
width: 108px;
height: 42px;
margin-left: 16px;
}
}
}
}
.user-nav {
.item {
text-align: center;
line-height: 34px;
display: block;
cursor: pointer;
&:not(:last-child) {
border-bottom: 1px solid #e5e5e5;
}
&:hover {
color: $--color-primary;
}
}
}
</style>

View File

@ -0,0 +1,82 @@
<template>
<nav>
<div class="header-nav bg-white">
<div class="nav-wrap flex">
<category />
<ul class="nav flex">
<li class="item">
<nuxt-link to="/">首页</nuxt-link>
</li>
<!-- <li class="item">
<nuxt-link to="/demand_list">我的需求</nuxt-link>
</li>
<li class="item">
<nuxt-link to="/seckill">限时秒杀</nuxt-link>
</li> -->
<li class="item">
<nuxt-link to="/goods_list/1">热销榜单</nuxt-link>
</li>
<!-- <li class="item">
<nuxt-link to="/goods_list/2">新品推荐</nuxt-link>
</li>
<li class="item">
<nuxt-link to="/shop_street">店铺街</nuxt-link>
</li>
<li class="item">
<nuxt-link to="/get_coupons">领券中心</nuxt-link>
</li>
<li class="item">
<nuxt-link to="/news_list">商城资讯</nuxt-link>
</li>
<li class="item">
<nuxt-link to="/help_center">帮助中心</nuxt-link>
</li> -->
</ul>
</div>
</div>
</nav>
</template>
<script>
import { mapState } from 'vuex'
import Category from './category'
export default {
components: {
Category,
},
created() {},
computed: {
...mapState(['publicData']),
},
}
</script>
<style lang="scss" scoped>
.header-nav {
border-top: 1px solid $--background-color-base;
.nav-wrap {
width: 1180px;
margin: 0 auto;
}
.nav {
overflow-x: auto;
overflow-y: hidden;
.item {
a {
padding: 12px 15px;
margin: 0 10px;
color: #101010;
font-size: 16px;
white-space: nowrap;
&:hover {
color: $--color-primary;
}
&.nuxt-link-exact-active {
color: $--color-primary;
}
}
}
}
}
</style>

View File

@ -0,0 +1,36 @@
<template>
<div class="bg-white flex-col col-center null-data">
<img :style="imgStyle" class="img-null" :src="img" alt="" />
<div class="muted mt8">{{ text }}</div>
</div>
</template>
<script>
export default {
components: {},
props: {
img: {
type: String,
},
text: {
type: String,
default: '暂无数据',
},
imgStyle: {
type: String,
default: '',
},
},
methods: {},
}
</script>
<style lang="scss" scoped>
.null-data {
padding: 100px;
.img-null {
width: 150px;
height: 150px;
}
}
</style>

View File

@ -0,0 +1,309 @@
<template>
<div class="number-box">
<div
@click.stop.prevent="btnTouchStart('minus')"
:class="{ minus: true, disabled: disabled || inputVal <= min }"
:style="{
background: bgColor,
height: inputHeight + 'px',
color: color,
}"
>
<div :style="{ fontSize: size + 'px' }">-</div>
</div>
<input
:disabled="disabledInput || disabled"
:class="{ 'number-input': true, 'input-disabled': disabled }"
v-model="inputVal"
@blur="onBlur"
@focus="onFocus"
type="text"
:style="{
color: color,
fontSize: size + 'px',
background: bgColor,
height: inputHeight + 'px',
width: inputWidth + 'px',
}"
/>
<div
class="plus"
@click.stop.prevent="btnTouchStart('plus')"
:class="{ disabled: disabled || inputVal >= max }"
:style="{
background: bgColor,
height: inputHeight + 'px',
color: color,
}"
>
<div :style="{ fontSize: size + 'px' }">+</div>
</div>
</div>
</template>
<script>
export default {
components: {},
props: {
//
value: {
type: Number,
default: 1,
},
//
bgColor: {
type: String,
default: ' #F2F3F5',
},
//
min: {
type: Number,
default: 0,
},
//
max: {
type: Number,
default: 99999,
},
//
step: {
type: Number,
default: 1,
},
//
disabled: {
type: Boolean,
default: false,
},
// inputpx
size: {
type: [Number, String],
default: 14,
},
// inputpx
inputWidth: {
type: [Number, String],
default: 64,
},
//
color: {
type: String,
default: '#333',
},
// inputpx
inputHeight: {
type: [Number, String],
default: 32,
},
// index使numberbox使forindex
index: {
type: [Number, String],
default: '',
},
// disabledOR
// disabledfalsedisabledInputtrue
disabledInput: {
type: Boolean,
default: false,
},
// 0()
positiveInteger: {
type: Boolean,
default: true,
},
asyncChange: {
type: Boolean,
default: false,
},
},
watch: {
value(v1, v2) {
if (!this.changeFromInner) {
this.inputVal = v1
this.$nextTick(function () {
this.changeFromInner = false
})
}
},
inputVal(v1, v2) {
if (v1 == '') return
let value = 0
let tmp = /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(v1)
if (tmp && v1 >= this.min && v1 <= this.max) value = v1
else value = v2
if (this.positiveInteger) {
if (v1 < 0 || String(v1).indexOf('.') !== -1) {
value = v2
this.$nextTick(() => {
this.inputVal = v2
})
}
}
if (this.asyncChange) {
return
}
// change
this.handleChange(value, 'change')
},
},
data() {
return {
inputVal: 1, // 使propsvalueprops
timer: null, //
changeFromInner: false, //
innerChangeTimer: null, //
}
},
created() {
this.inputVal = Number(this.value)
},
computed: {},
methods: {
btnTouchStart(callback) {
this[callback]()
},
minus() {
this.computeVal('minus')
},
plus() {
this.computeVal('plus')
},
calcPlus(num1, num2) {
let baseNum, baseNum1, baseNum2
try {
baseNum1 = num1.toString().split('.')[1].length
} catch (e) {
baseNum1 = 0
}
try {
baseNum2 = num2.toString().split('.')[1].length
} catch (e) {
baseNum2 = 0
}
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2))
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2
return ((num1 * baseNum + num2 * baseNum) / baseNum).toFixed(
precision
)
},
calcMinus(num1, num2) {
let baseNum, baseNum1, baseNum2
try {
baseNum1 = num1.toString().split('.')[1].length
} catch (e) {
baseNum1 = 0
}
try {
baseNum2 = num2.toString().split('.')[1].length
} catch (e) {
baseNum2 = 0
}
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2))
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2
return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(
precision
)
},
computeVal(type) {
if (this.disabled) return
let value = 0
//
if (type === 'minus') {
value = this.calcMinus(this.inputVal, this.step)
} else if (type === 'plus') {
value = this.calcPlus(this.inputVal, this.step)
}
//
if (value < this.min || value > this.max) {
return
}
if (this.asyncChange) {
this.$emit('change', value)
} else {
this.inputVal = value
this.handleChange(value, type)
}
},
//
onBlur(event) {
let val = 0
let value = event.target.value
console.log(value)
if (!/(^\d+$)/.test(value)) {
val = this.min
} else {
val = +value
}
if (val > this.max) {
val = this.max
} else if (val < this.min) {
val = this.min
}
this.$nextTick(() => {
this.inputVal = val
})
this.handleChange(val, 'blur')
},
//
onFocus() {
this.$emit('focus')
},
handleChange(value, type) {
if (this.disabled) return
//
if (this.innerChangeTimer) {
clearTimeout(this.innerChangeTimer)
this.innerChangeTimer = null
}
this.changeFromInner = true
this.innerChangeTimer = setTimeout(() => {
this.changeFromInner = false
}, 150)
this.$emit('input', Number(value))
this.$emit(type, {
value: Number(value),
index: this.index,
})
},
},
}
</script>
<style lang="scss" scoped>
.number-box {
display: inline-flex;
align-items: center;
.number-input {
position: relative;
text-align: center;
padding: 0;
margin: 0 6px;
align-items: center;
justify-content: center;
}
.plus,
.minus {
width: 32px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.plus {
border-radius: 0 2px 2px 0;
}
.minus {
border-radius: 2px 0 0 2px;
}
.disabled {
color: #c8c9cc !important;
background: #f7f8fa !important;
}
.input-disabled {
color: #c8c9cc !important;
background-color: #f2f3f5 !important;
}
}
</style>

View File

@ -0,0 +1,366 @@
<template>
<div class="order-list">
<div class="item m-b-16" v-for="item in list" :key="item.id">
<div class="item-hd flex">
<nuxt-link
class="flex-1 lighter sm line-1 m-r-20"
style="min-width: 0"
:to="`/shop_street_detail?id=${item.shop.id}`"
>
{{ item.shop.name }}
</nuxt-link>
<div class="flex-1 lighter sm">
下单时间{{ item.create_time }}
</div>
<div class="flex-1 lighter sm">
订单编号{{ item.order_sn }}
</div>
<div
:class="['status sm', { primary: item.order_status == 0 }]"
>
{{ getOrderStatus(item.order_status) }}
</div>
</div>
<div class="item-con">
<div class="flex" style="align-items: stretch;">
<div class="goods">
<nuxt-link
class="goods-item flex"
:to="`/goods_details/${goods.goods_id}`"
v-for="(goods, index) in item.order_goods"
:key="index"
>
<el-image class="goods-img" :src="goods.image" alt="" />
<div class="goods-info flex-1">
<div class="goods-name m-b-8 flex row-between">
<div class="line1" style="width: 350px">
<el-tag
size="mini"
effect="plain"
v-if="goods.is_seckill"
>秒杀</el-tag
>
{{ goods.goods_name }}
</div>
<div class="num">x{{ goods.goods_num }}</div>
</div>
<div class="sm muted m-b-8">
{{ goods.spec_value }}
</div>
<div class="primary">
<price-formate :price="goods.goods_price" />
</div>
</div>
</nuxt-link>
</div>
<div
class="pay-price flex-col col-center row-center"
style="padding-left: 30px"
>
<div class="lighter">{{ item.goods_count }}件商品</div>
<div class="lighter m-t-8 flex">
付款金额
<span class="primary">
<price-formate
:price="item.order_amount"
:subscript-size="12"
:first-size="16"
:second-size="12"
/>
</span>
</div>
</div>
<div class="operate flex-col col-center row-center sm">
<nuxt-link
:to="`/payment?id=${item.id}&from=order`"
class="btn m-b-16 bg-primary flex row-center white sm"
v-if="item.pay_btn"
>
<span class="m-r-8">去付款</span>
<count-down
v-if="getCancelTime(item.order_cancel_time) > 0"
:time="getCancelTime(item.order_cancel_time)"
format="hh:mm:ss"
@finish="$emit('refresh')"
/>
</nuxt-link>
<div
class="btn m-b-10 primary flex row-center sm plain"
v-if="item.take_btn"
@click="handleOrder(2, item.id)"
>
确认收货
</div>
<div
class="m-b-10 muted flex row-center sm"
v-if="item.delivery_btn"
@click="showDeliverDialog(item.id)"
>
物流查询
</div>
<div
class="m-b-10 muted row-center sm"
v-if="item.cancel_btn"
@click="handleOrder(0, item.id)"
>
取消订单
</div>
<div
class="m-b-10 muted row-center sm"
v-if="item.del_btn"
@click="handleOrder(1, item.id)"
>
删除订单
</div>
<nuxt-link
class="lighter"
:to="`/user/order/detail?id=${item.id}`"
>
<span>查看详情</span>
<!-- <i class="el-icon-arrow-right"></i> -->
</nuxt-link>
<el-upload
class="upload-demo"
:action="action"
:multiple="true"
:limit="10"
:headers="{token: $store.state.token}"
:show-file-list="false"
:on-success="onSuccess"
>
<el-button type="primary" size="mini" class="m-t-10 muted row-center sm uploadBtn"
v-if="item.pay_btn == 0 && item.del_btn != 1" @click="uploadContract(item.id)"
>上传合同</el-button>
</el-upload>
</div>
</div>
</div>
</div>
<deliver-search v-model="showDeliver" :aid="aid" />
</div>
</template>
<script>
import config from "~/config/app";
export default {
props: {
list: {
type: Array,
default: () => [],
},
},
data() {
return {
showDeliver: false,
aid: -1,
action: config.baseUrl + "/api/file/formimage",
baseUrl:config.baseUrl + '/',
uploadId:'',//id
}
},
created() {
console.log(this.list)
},
methods: {
handleOrder(type, id) {
this.type = type
this.orderId = id
this.$confirm(this.getTipsText(type), {
title: '温馨提示',
center: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
callback: (action) => {
if (action == 'confirm') {
this.postOrder()
}
},
})
},
async postOrder() {
const { type, orderId } = this
let url = ''
switch (type) {
case 0:
url = 'order/cancel'
break
case 1:
url = 'order/del'
break
case 2:
url = 'order/confirm'
break
}
let { code, data, msg } = await this.$post(url, { id: orderId })
if (code == 1) {
this.$message({
message: msg,
type: 'success',
})
this.$emit('refresh')
}
},
getTipsText(type) {
switch (type) {
case 0:
return '确认取消订单吗?'
case 1:
return '确认删除订单吗?'
case 2:
return '确认收货吗?'
}
},
showDeliverDialog(id) {
console.log('showDeliverDialog')
this.aid = id
this.showDeliver = true
},
// id
uploadContract(id) {
this.uploadId = id;
console.log(this.uploadId)
},
async onSuccess(response, file, fileList) {
console.log(response, file, fileList)
let that = this;
if(fileList) {
let result = fileList.map(item => item.response.data.base_uri).join(',');
let params = {
order_id:that.uploadId,
path:result
}
let respond = await that.$post("order/contractUpload", params);
if (respond.code == 1) {
this.$message({
message: '上传成功,可进入详情查看',
type: "success",
});
}
}
},
},
computed: {
getOrderStatus() {
return (status) => {
let text = ''
switch (status) {
case 0:
text = '待支付'
break
case 1:
text = '待发货'
break
case 2:
text = '待收货'
break
case 3:
text = '已完成'
break
case 4:
text = '订单已关闭'
break
}
return text
}
},
getCancelTime() {
return (time) => time - Date.now() / 1000
},
},
}
</script>
<style lang="scss">
.order-list {
padding: 0 16px;
.item {
margin-bottom: 20px;
.item-hd {
height: 40px;
border: 1px solid #e5e5e5;
background: #f2f2f2;
padding: 0 20px;
.status {
width: 100px;
text-align: right;
}
}
.item-con {
box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.08);
align-items: stretch;
.goods {
padding: 17px 0;
width: 560px;
.goods-item {
padding: 10px 20px;
.goods-img {
flex: none;
margin-right: 10px;
width: 72px;
height: 72px;
}
.goods-name {
width: 100%;
.num {
padding: 0 42px;
}
}
}
}
.pay-price {
width: 200px;
border-left: 1px solid #e5e5e5;
border-right: 1px solid #e5e5e5;
}
.operate {
width: 185px;
& > div {
cursor: pointer;
}
.btn {
width: 120px;
height: 32px;
border-radius: 2px;
&.plain {
border: 1px solid $--color-primary;
}
}
}
}
}
}
.uploadBtn {
color: #fff;
}
.pre-box {
display: flex;
align-items: center;
flex-wrap: wrap;
border-top: 1px solid #e5e5e5;
padding: 20px;
}
.pre-item {
width: 120rpx;
border-radius: 6rpx;
height: 120rpx;
overflow: hidden;
position: relative;
margin-bottom: 20rpx;
margin-right: 20rpx;
}
.pre-item-image {
width: 100%;
height: 120rpx;
}
// .item-con .el-upload-list {
// display: none;
// }
</style>

View File

@ -0,0 +1,94 @@
<template>
<span
:style="{ color, 'font-weight': weight }"
:class="(lineThrough ? 'line-through' : '') + 'price-format'"
>
<span
v-if="showSubscript"
:style="{
'font-size': subscriptSize + 'px',
'margin-right': '1px',
}"
>¥</span
>
<span
:style="{ 'font-size': firstSize + 'px', 'margin-right': '1px' }"
>{{ priceSlice.first }}</span
>
<span
v-if="priceSlice.second"
:style="{ 'font-size': secondSize + 'px' }"
>.{{ priceSlice.second }}</span
>
</span>
</template>
<script>
export default {
data() {
return {
priceSlice: {},
}
},
components: {},
props: {
firstSize: {
type: Number,
default: 14,
},
secondSize: {
type: Number,
default: 14,
},
color: {
type: String,
},
weight: {
type: [String, Number],
default: 400,
},
price: {
type: [String, Number],
default: '',
},
showSubscript: {
type: Boolean,
default: true,
},
subscriptSize: {
type: Number,
default: 14,
},
lineThrough: {
type: Boolean,
default: false,
},
},
created() {
this.priceFormat()
},
watch: {
price(val) {
this.priceFormat()
},
},
methods: {
priceFormat() {
let { price } = this
let priceSlice = {}
if (price !== null) {
price = String(price).split('.')
priceSlice.first = price[0]
priceSlice.second = price[1]
this.priceSlice = priceSlice
}
},
},
}
</script>
<style>
.price-format {
display: flex;
align-items: baseline;
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<nuxt-link
class="shop-item flex-col row-right"
:style="{
'background-image': `url(${cover})`,
}"
:to="`/shop_street_detail?id=${shopId}`"
>
<div class="bg-white shop-info text-center">
<el-image class="logo" :src="logo"></el-image>
<div class="m-t-12 line-1 lg">
<el-tag size="mini" v-if="type == 1"></el-tag> {{ name }}
</div>
<span class="xs muted sales"
>{{ sales }}件商品</span
>
</div>
</nuxt-link>
</template>
<script>
export default {
components: {},
props: {
cover: {
type: String,
},
shopId: {
type: [String, Number],
},
logo: {
type: String,
},
type: {
type: [String, Number],
},
name: {
type: String,
},
sales: {
type: [String, Number],
}
},
methods: {},
}
</script>
<style lang="scss" scoped>
.shop-item {
width: 270px;
height: 400px;
background-size: cover;
background-position: center;
padding: 10px;
border-radius: 6px;
.shop-info {
border-radius: 6px;
padding: 18px 15px;
.logo {
width: 70px;
height: 70px;
border-radius: 16px;
margin-top: -45px;
}
.sales {
display: inline-block;
padding: 4px 10px;
background-color: #f2f2f2;
margin-top: 6px;
border-radius: 4px;
}
}
}
</style>

View File

@ -0,0 +1,108 @@
<template>
<div class="v-upload">
<el-upload
list-type="picture-card"
:action="url + '/api/file/formimage'"
:limit="limit"
:on-success="success"
:on-error="error"
:on-remove="remove"
:on-change="onChange"
:headers="{ token: $store.state.token }"
:auto-upload="autoUpload"
accept="image/jpg,image/jpeg,image/png"
:before-upload="beforeAvatarUpload"
>
<slot v-if="isSlot"></slot>
<div v-else>
<div class="muted xs">上传图片</div>
</div>
</el-upload>
</div>
</template>
<script>
import config from '~/config/app'
export default {
components: {},
props: {
limit: {
type: Number,
default: 1,
},
isSlot: {
type: Boolean,
default: false,
},
autoUpload: {
type: Boolean,
default: true,
},
onChange: {
type: Function,
default: () => {},
},
},
watch: {},
data() {
return {
url: config.baseUrl,
}
},
created() {},
computed: {},
methods: {
success(res, file, fileList) {
if (!this.autoUpload) {
return
}
this.$message({
message: '上传成功',
type: 'success',
})
this.$emit('success', fileList)
},
remove(file, fileList) {
this.$emit('remove', fileList)
},
error(res) {
this.$message({
message: '上传失败,请重新上传',
type: 'error',
})
},
beforeAvatarUpload(file) {
var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
console.log('fdsadsf')
const extension = testmsg === 'jpg'
const extension2 = testmsg === 'png'
const extension4 = testmsg === 'jpeg'
if (!extension && !extension2) {
this.$message({
message: '上传文件只能是 jpg, jpeg, png格式!',
type: 'warning'
})
return false
}
return extension || extension2 || extension4
},
},
}
</script>
<style lang="scss" scoped>
.v-upload {
.el-upload--picture-card {
width: 76px;
height: 76px;
line-height: 76px;
}
.el-upload-list--picture-card {
.el-upload-list__item {
width: 76px;
height: 76px;
}
}
}
</style>

11
pc - 副本/config/app.js Normal file
View File

@ -0,0 +1,11 @@
// 本地访问域名
// const testUrl = "https://glh.dev.scdxtc.cn"
const testUrl = "https://www.gonglehui.com"
//线上域名
const productUrl = 'https://www.gonglehui.com'
const config = {
baseUrl: process.env.NODE_ENV == 'production' ? productUrl : testUrl
}
export default config

View File

@ -0,0 +1,30 @@
<template>
<div class="default-layout flex-col">
<ls-header></ls-header>
<main-nav />
<main class="content-container wrapper1180 flex-1">
<nuxt />
</main>
<ls-footer></ls-footer>
<float-nav></float-nav>
</div>
</template>
<script>
import LsHeader from '~/components/layout/header'
import LsFooter from '~/components/layout/footer'
import FloatNav from '~/components/layout/float-nav'
import MainNav from '~/components/layout/main-nav'
export default {
components: {
LsHeader,
LsFooter,
FloatNav,
MainNav,
},
}
</script>
<style scoped>
.default-layout {
min-height: 100vh;
}
</style>

View File

@ -0,0 +1,25 @@
<template>
<div class="error flex-col col-center">
<h1 class="mb16">抱歉您访问的页面出错了</h1>
<div class="muted">您可能输错了网址或该网页已被删除不存在等</div>
</div>
</template>
<script>
export default {
components: {
},
data() {
return {
};
},
methods: {
}
};
</script>
<style lang="scss" scoped>
.error {
padding-top: 200px;
}
</style>

View File

@ -0,0 +1,56 @@
<template>
<div class="default-layout flex-col">
<div class="default-header">
<div class="haeder-con">
<nuxt-link to="/" v-if="config.shop_login_logo">
<img class="header-logo" :src="config.shop_login_logo" />
</nuxt-link>
</div>
</div>
<div class="default-main flex-1">
<nuxt />
</div>
<ls-footer></ls-footer>
</div>
</template>
<script>
import LsFooter from '~/components/layout/footer'
import { mapState } from 'vuex'
export default {
components: {
LsFooter,
},
data() {
return {}
},
created() {},
computed: {
...mapState(['config']),
},
methods: {},
}
</script>
<style lang="scss" scoped>
.default-layout {
min-height: 100vh;
.default-header {
padding: 22px 0;
background-color: white;
min-width: 1180px;
border-bottom: 1px solid #e5e5e5;
.haeder-con {
width: 1180px;
margin: 0 auto;
}
.header-logo {
height: 56px;
}
}
.default-main {
display: flex;
flex-direction: column;
}
}
</style>

View File

@ -0,0 +1,29 @@
<template>
<div class="default-layout flex-col">
<ls-header></ls-header>
<main class="content-container">
<nuxt />
</main>
<ls-footer></ls-footer>
<float-nav></float-nav>
</div>
</template>
<script>
import LsHeader from '~/components/layout/header'
import LsFooter from '~/components/layout/footer'
import FloatNav from '~/components/layout/float-nav'
import MainNav from '~/components/layout/main-nav'
export default {
components: {
LsHeader,
LsFooter,
FloatNav,
MainNav,
},
}
</script>
<style scoped>
.default-layout {
min-height: 100vh;
}
</style>

View File

@ -0,0 +1,42 @@
<template>
<div class="default-layout flex-col">
<ls-header></ls-header>
<main-nav />
<main class="content-container wrapper1180 flex flex-1">
<aslide-nav />
<div class="content bg-white flex-1">
<nuxt />
</div>
</main>
<ls-footer></ls-footer>
<float-nav></float-nav>
</div>
</template>
<script>
import LsHeader from "~/components/layout/header";
import LsFooter from "~/components/layout/footer";
import AslideNav from "~/components/layout/aslide-nav";
import MainNav from '~/components/layout/main-nav'
import FloatNav from "~/components/layout/float-nav";
export default {
components: {
LsHeader,
LsFooter,
AslideNav,
FloatNav,
MainNav
},
};
</script>
<style scoped>
.default-layout {
min-height: 100vh;
}
.content-container {
padding: 24px 0;
align-items: flex-start;
}
.content-container > .content {
min-height: 680px;
}
</style>

View File

@ -0,0 +1,12 @@
import Cookies from 'js-cookie'
const account = ['login', 'register', 'forget_pwd', "error"]
export default function({route, app, store}) {
const { fullPath } = route
const isAccount = account.some((item) => fullPath.includes(item))
const {isLogin} = store.getters
if(!isAccount && !isLogin) {
process.server ? app.$cookies.set('back_url', fullPath) : Cookies.set('back_url', fullPath)
}
}

View File

@ -0,0 +1,69 @@
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: '',
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'}
]
},
ssr: false,
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
'@/assets/css/element-variables.scss',
'@/assets/css/common.scss',
'@/assets/css/reset.scss',
'swiper/css/swiper.css',
'@/assets/css/element.scss',
'@/assets/fonts/iconfont.css'
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
'@/plugins/element-ui',
{src: '@/plugins/vue-awesome-swiper', mode: 'client'},
'@/plugins/axios',
'@/plugins/init',
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
'@nuxtjs/style-resources',
['cookie-universal-nuxt', { parseJSON: true }]
],
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
transpile: [/^element-ui/],
},
router: {
middleware: 'route', // 即每次路由跳转会调用该中间件
base: '/'
//多个中间件写法
// middleware: ['route']
},
styleResources: {
scss: "./assets/css/variables.scss"
},
}

14958
pc - 副本/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

34
pc - 副本/package.json Normal file
View File

@ -0,0 +1,34 @@
{
"name": "LikeSopb2b2c",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"dependencies": {
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/style-resources": "^1.0.0",
"cookie-universal-nuxt": "^2.1.4",
"cookieparser": "^0.1.0",
"core-js": "^3.15.1",
"element-ui": "^2.15.2",
"js-cookie": "^2.2.1",
"nuxt": "latest",
"swiper": "^5.2.0",
"vue-awesome-swiper": "^4.1.1"
},
"devDependencies": {
"@nuxtjs/proxy": "^2.1.0",
"sass": "~1.32.8",
"sass-loader": "10"
},
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": 8000
}
}
}

View File

@ -0,0 +1,140 @@
<template>
<div class="news-details-container mt16">
<div class="nav-container flex">
<div class="nr" style="width: 70px">当前位置</div>
<el-breadcrumb style="flex: 1;" separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item class="line1">关于我们</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="content-box">
<div class="news-detail-box">
<div class="content-header bg-white">
<div class="news-detail-title">
关于我们
</div>
</div>
<div class="content-html-box bg-white">
<div v-html="detailsObj.content"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
$get,
$post,
query
}) {
let detailsObj = {};
let res = await $get("policy/aboutUs", {});
if (res.code == 1) {
detailsObj = res.data;
}
return {
detailsObj,
};
},
data() {
return {
}
},
mounted() {
console.log('route', this.$route)
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.news-details-container {
.nav-container {
padding: 15px 16px;
}
.content-box {
display: flex;
flex-direction: row;
.news-detail-box {
background-color: #FFFFFF;
width: 100%;
.content-header {
margin: 0px 20px;
padding: 20px 0px;
border-bottom: 1px solid #e5e5e5;
.news-detail-title {
color: #222;
font-size: 24px;
font-weight: 500;
}
}
.content-html-box {
padding: 24px 20px;
&>div {
width: 100%;
overflow: hidden;
::v-deep img {
width: 100%;
}
}
}
}
.recommend-box {
width: 264px;
.recommend-box-header {
padding: 15px 10px;
border-bottom: 1px solid #e5e5e5;
.primary-line {
margin-right: 10px;
background-color: $--color-primary;
width: 4px;
height: 20px;
}
}
.recommend-box-content {
.recommend-list-container {
.recommend-list-item {
padding: 10px;
cursor: pointer;
.goods-info {
margin-top: 8px;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,209 @@
<template>
<div class="forget-pwd-container flex-col row-center col-center">
<div class="forget-pwd-box flex-col col-center bg-white">
<div class="forget-pwd-title">忘记密码</div>
<el-form class="form-box flex-col">
<div class="forget-form-item">
<el-input
class="form-input"
v-model="telephone"
placeholder="请输入手机号码"
>
<i
class="el-icon-user"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
</div>
<div class="forget-form-item flex">
<el-input
v-model="smsCode"
class="form-input"
placeholder="短信验证码"
style="width: 264px"
>
<i
class="el-icon-lock"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
<el-button class="sms-btn" @click="sendSMSCode">
<div v-if="canSend"></div>
<count-down
v-else
:time="60"
format="ss秒"
autoStart
@finish="canSend = true"
/>
</el-button>
</div>
<div class="forget-form-item">
<el-input
v-model="password"
placeholder="请输入密码 (数字与字母自由组合)"
show-password
>
<i
class="el-icon-more-outline"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
</div>
<div class="forget-form-item">
<el-input
v-model="againPwd"
placeholder="再次输入密码"
show-password
>
<i
class="el-icon-key"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
</div>
<div class="flex-col" style="margin-top: 46px">
<el-button type="primary" @click="forgetFun"
>确定</el-button
>
</div>
</el-form>
</div>
</div>
</template>
<script>
import { SMSType, client } from '@/utils/type'
import CountDown from '~/components/count-down'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
layout: 'main',
components: {
CountDown,
},
data() {
return {
telephone: '',
smsCode: '',
canSend: true,
password: '',
againPwd: '',
}
},
methods: {
async forgetFun() {
if (!this.telephone) {
this.$message({
message: '请输入手机号码',
type: 'error',
})
return
} else if (!this.smsCode) {
this.$message({
message: '请输入验证码',
type: 'error',
})
return
} else if (!this.password) {
this.$message({
message: '请输入密码信息',
type: 'error',
})
return
} else if (this.password != this.againPwd) {
this.$message({
message: '两次输入密码不一致',
type: 'error',
})
return
}
let res = await this.$post('login_password/forget', {
mobile: this.telephone,
code: this.smsCode,
password: this.password,
repassword: this.againPwd,
client: client,
})
if (res.code == 1) {
this.$message({
message: '修改成功',
type: 'success',
})
let time = setTimeout(() => {
this.$router.replace('/account/login')
clearTimeout(time)
}, 1000)
}
},
async sendSMSCode() {
if (!this.telephone) {
this.$message({
message: '请输入手机号码',
type: 'error',
})
return
}
let res = await this.$post('sms/send', {
mobile: this.telephone,
key: SMSType.FINDPWD,
})
if (res.code == 1) {
this.canSend = false
this.$message({
message: '发送成功',
type: 'success',
})
}
},
},
}
</script>
<style lang="scss" scoped>
.forget-pwd-container {
flex: 1;
.forget-pwd-box {
padding-top: 40px;
padding-bottom: 55px;
width: 880px;
border: 1px solid #e5e5e5;
.forget-pwd-title {
font-size: 24px;
}
.form-box {
.forget-form-item {
margin-top: 24px;
}
.form-input {
width: 400px;
}
.verify-code-img {
width: 100px;
height: 40px;
margin-left: 26px;
background-color: red;
}
.sms-btn {
margin-left: 16px;
height: 40px;
width: 120px;
}
}
}
}
</style>

View File

@ -0,0 +1,448 @@
<template>
<div class="login flex col-center">
<div class="login-container flex col-stretch">
<div class="login-banner">
<!-- <el-image-->
<!-- fit="cover"-->
<!-- style="width: 100%; height: 100%"-->
<!-- :src="config.pc_login_logo"-->
<!-- ></el-image>-->
<img :src="config.pc_login_logo" height="100%" />
</div>
<div class="login-float-form-wrap">
<div class="login-box">
<div class="login-header-box">
<div class="header-tabs flex row-center">
<div
class="header-tab xxl"
:class="{ 'active-tab': loginStatus == 0 }"
@click="changeLoginType(0)"
>验证码登录</div>
<div
class="header-tab xxl"
:class="{ 'active-tab': loginStatus == 1 }"
@click="changeLoginType(1)"
>账号密码登录</div>
</div>
<div v-show="loginStatus == 0" @keyup.enter="smsLogin">
<div class="login-form-box">
<div class="login-form-item">
<el-input
placeholder="请输入手机号码"
v-model="telephone"
class="input-phone-num"
>
<el-select
style="width: 100px"
v-model="selectNumberType"
slot="prepend"
placeholder="请选择"
>
<el-option label="中国+86" value="1"></el-option>
</el-select>
</el-input>
</div>
<div class="login-form-item flex">
<el-input
v-model="smsCode"
placeholder="短信验证码"
style="width: 210px"
/>
<el-button class="sms-btn" @click="sendSMSCode">
<div v-if="canSend"></div>
<count-down
v-else
:time="60"
format="ss秒"
:autoStart="true"
@finish="canSend = true"
/>
</el-button>
</div>
</div>
<div class="option-box flex-col">
<el-checkbox v-model="isRemember" class="muted"></el-checkbox>
<div class="m-t-20 flex-col">
<el-button type="primary" @click="smsLogin"></el-button>
</div>
</div>
</div>
<div v-show="loginStatus == 1" @keyup.enter="accountLogin">
<div class="login-form-box">
<div class="login-form-item">
<el-input
placeholder="请输入账号/手机号码"
v-model="account"
class="input-phone-num"
>
<i
class="el-icon-user"
style="font-size: 18px"
slot="prepend"
></i>
</el-input>
</div>
<div class="login-form-item flex">
<el-input v-model="password" placeholder="请输入密码" show-password>
<i
class="el-icon-more-outline"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
</div>
</div>
<div class="option-box flex-col">
<div class="flex row-between">
<el-checkbox v-model="isRemember" class="muted"></el-checkbox>
<nuxt-link class="muted" to="/account/forget_pwd">忘记密码</nuxt-link>
</div>
<div class="m-t-20 flex-col">
<el-button type="primary" @click="accountLogin"></el-button>
</div>
</div>
</div>
</div>
<div class="login-footer-box flex row-between">
<!-- <div class="flex">
<div class="flex login__other-item" @click="goWechatLogin">
<i class="iconfont icon-weixin1 login__weixin-icon"></i>
<div class="m-l-4 muted">微信</div>
</div>
</div> -->
<div></div>
<nuxt-link class="primary" to="/account/register">注册账号</nuxt-link>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { loginType, client, SMSType } from '@/utils/type'
import Cookies from 'js-cookie'
import { mapMutations, mapActions, mapState } from 'vuex'
import CountDown from '@/components/count-down'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
layout: 'main',
components: {
CountDown,
},
data() {
return {
//
selectNumberType: '中国+86',
//
account: '',
//
password: '',
//
telephone: '',
//
verifyCode: '',
//
smsCode: '',
isRemember: true,
// 0 == 1 ==
loginStatus: loginType.SMS,
canSend: true,
}
},
computed: {
...mapState(['config']),
},
methods: {
...mapMutations(['setToken']),
...mapActions(['getPublicData']),
changeLoginType(type) {
this.loginStatus = type
this.telephone = ''
this.verifyCode = ''
this.smsCode = ''
let jsonPaser = JSON.parse(localStorage.getItem('ACCOUNT'))
let telJson = JSON.parse(localStorage.getItem('TEL'))
if (jsonPaser && jsonPaser.account) {
this.account = jsonPaser.account
}
if (telJson && telJson.telephone) {
this.telephone = telJson.telephone
}
},
//
goWechatLogin() {
this.$get('account/scanCode')
.then(({ code, msg, data }) => {
if (code !== 1) throw new Error(msg)
window.open(data.url, '_self')
})
.catch((err) => {
this.$message.error(err.message)
})
},
//
handleWechatLogin(params) {
this.$post('account/scanLogin', params)
.then(({ code, msg, data }) => {
if (code !== 1) throw new Error(msg)
Cookies.set('token', data.token, { expires: 60 })
this.setToken(data.token)
this.$router.replace({
path: Cookies.get('back_url') || '/',
})
Cookies.remove('back_url')
this.getPublicData()
})
.catch((err) => {
this.$message.error(err.message)
})
},
async sendSMSCode() {
if (!this.canSend) {
return
}
let res = await this.$post('sms/send', {
mobile: this.telephone,
key: SMSType.LOGIN,
client,
})
if (res.code == 1) {
this.$message({
message: res.msg,
type: 'success',
})
this.canSend = false
}
},
async smsLogin() {
let res = await this.$post('account/smsLogin', {
mobile: this.telephone,
code: this.smsCode,
client,
})
if (res.code == 1) {
const token = res.data.token
Cookies.set('token', token, { expires: 60 })
this.setToken(token)
this.$router.replace({
path: Cookies.get('back_url') || '/',
})
Cookies.remove('back_url')
this.getPublicData()
if (this.isRemember) {
localStorage.setItem(
'TEL',
JSON.stringify({
telephone: this.telephone,
})
)
} else {
localStorage.setItem(
'TEL',
JSON.stringify({
telephone: '',
})
)
}
}
},
async accountLogin() {
let res = await this.$post('account/login', {
mobile: this.account,
password: this.password,
client,
})
if (res.code == 1) {
const token = res.data.token
Cookies.set('token', token, { expires: 60 })
this.setToken(token)
this.$router.replace({
path: Cookies.get('back_url') || '/',
})
Cookies.remove('back_url')
this.getPublicData()
if (this.isRemember) {
localStorage.setItem(
'ACCOUNT',
JSON.stringify({
account: this.account,
})
)
} else {
localStorage.setItem(
'ACCOUNT',
JSON.stringify({
account: '',
})
)
}
}
},
},
created() {
try {
// URL Query
const query = this.$route.query
// codestate
query.code &&
query.state &&
this.handleWechatLogin({ code: query.code, state: query.state })
//
const jsonPaser = JSON.parse(localStorage.getItem('ACCOUNT')) ?? {}
const telJson = JSON.parse(localStorage.getItem('TEL')) ?? {}
//
this.account = jsonPaser?.account ?? ''
this.telephone = telJson?.telephone ?? ''
} catch (error) {
}
},
}
</script>
<style lang="scss" scoped>
.login {
flex: 1;
background-size: cover;
background-repeat: no-repeat;
background-position: 50%;
min-width: 1180px;
.login-container {
margin: 0 auto;
width: 1180px;
height: 100%;
position: relative;
.login-banner {
display: flex;
align-items: center;
justify-content: center;
width: 750px;
margin-right: 30px;
height: 440px;
overflow: hidden;
animation: loadimg 2s infinite;
transition: background-color 2s;
}
@keyframes loadimg {
0% {
background-color: #e4e4e4;
}
50% {
background-color: #f0f0f0;
}
100% {
background-color: #e4e4e4;
}
}
.login-float-form-wrap {
width: 400px;
height: 440px;
.login-box {
background-color: white;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
.login-header-box {
padding-top: 20px;
.header-tabs {
.header-tab {
width: 160px;
height: 35px;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
}
.active-tab {
color: $--color-primary;
text-align: center;
&::after {
content: "";
height: 2px;
width: 72px;
margin-top: 8px;
background-color: $--color-primary;
}
}
}
.login-form-box {
padding: 0 30px;
.login-form-item {
margin-top: 24px;
.input-phone-num {
width: 340px;
}
.verify-code-img {
width: 100px;
height: 40px;
margin-left: 20px;
background-color: red;
}
.sms-btn {
margin-left: 20px;
height: 40px;
}
}
}
.option-box {
padding: 0 30px;
margin-top: 60px;
::v-deep .el-checkbox {
color: #888;
}
}
}
.login-footer-box {
height: 50px;
padding: 15px;
.login__other-item {
cursor: pointer;
}
.login__weixin-icon {
width: 1.5em;
height: 1.5em;
text-align: center;
line-height: 1.5em;
border-radius: 50%;
background-color: #0abd5d;
color: #ffffff;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,212 @@
<template>
<div class="register-container flex-col row-center col-center">
<div class="register-box flex-col col-center bg-white">
<div class="register-title">注册账号</div>
<el-form class="form-box flex-col">
<div class="register-form-item">
<el-input
class="form-input"
v-model="telephone"
placeholder="请输入手机号码"
>
<i
class="el-icon-user"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
</div>
<div class="register-form-item flex" v-if="registerSetting">
<el-input
v-model="smsCode"
class="form-input"
placeholder="短信验证码"
style="width: 264px"
>
<i
class="el-icon-lock"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
<el-button class="sms-btn" @click="sendSMSCode">
<div v-if="canSend"></div>
<count-down
v-else
:time="60"
format="ss秒"
autoStart
@finish="canSend = true"
/>
</el-button>
</div>
<div class="register-form-item">
<el-input
v-model="password"
placeholder="请输入密码 (数字与字母自由组合)"
show-password
>
<i
class="el-icon-more-outline"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
</div>
<div class="register-form-item">
<el-input
v-model="againPwd"
placeholder="再次输入密码"
show-password
>
<i
class="el-icon-key"
style="font-size: 18px"
slot="prepend"
/>
</el-input>
</div>
<div class="flex row-between" style="margin-top: 36px">
<nuxt-link to="/account/login">已有账号去登录</nuxt-link>
</div>
<div class="m-t-20 flex-col">
<el-button type="primary" @click="registerFun"
>立即注册</el-button
>
</div>
</el-form>
</div>
</div>
</template>
<script>
import { client, SMSType } from '@/utils/type'
import CountDown from '@/components/count-down'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
layout: 'main',
components: {
CountDown,
},
data() {
return {
telephone: '',
smsCode: '',
password: '',
againPwd: '',
canSend: true,
}
},
computed: {
registerSetting() {
return this.$store.state.config.register_setting
},
},
methods: {
async sendSMSCode() {
if (!this.canSend) {
return
}
let res = await this.$post('sms/send', {
mobile: this.telephone,
key: SMSType.REGISTER,
})
if (res.code == 1) {
this.$message({
message: res.msg,
type: 'success',
})
this.canSend = false
}
},
async registerFun() {
if (!this.telephone) {
this.$message({
message: '请输入手机号',
type: 'error',
})
return
}
if (this.registerSetting && !this.smsCode) {
this.$message({
message: '请输入短信验证码',
type: 'error',
})
return
}
if (!this.password) {
this.$message({
message: '请输入密码',
type: 'error',
})
return
}
if (this.password != this.againPwd) {
this.$message({
message: '两次密码输入不一致',
type: 'error',
})
return
}
let res = await this.$post('account/register', {
mobile: this.telephone,
password: this.password,
code: this.smsCode,
client: client,
})
if (res.code == 1) {
this.$message({
message: '注册成功',
type: 'success',
})
this.$router.replace('/account/login')
}
},
},
}
</script>
<style lang="scss" scoped>
.register-container {
flex: 1;
.register-box {
padding-top: 40px;
padding-bottom: 55px;
width: 880px;
border: 1px solid #e5e5e5;
.register-title {
font-size: 24px;
}
.form-box {
.register-form-item {
margin-top: 24px;
.form-input {
width: 400px;
}
.verify-code-img {
width: 100px;
height: 40px;
margin-left: 26px;
background-color: red;
}
.sms-btn {
margin-left: 16px;
height: 40px;
width: 120px;
}
}
}
}
}
</style>

View File

@ -0,0 +1,437 @@
<template>
<div class="category">
<div class="category-hd bg-white">
<div class="category-wrap">
<div class="category-con flex">
<div class="name muted">一级分类</div>
<div class="category-list flex flex-wrap lighter">
<div
:class="[
'item line1',
{ active: oneIndex == index },
]"
v-for="(item, index) in categoryOne"
:key="index"
@click="changeData(item.id)"
>
{{ item.name }}
</div>
</div>
</div>
<div class="category-con flex">
<div class="name muted">二级分类</div>
<div class="category-list flex flex-wrap lighter">
<div
:class="['item line1', { active: twoIndex === '' }]"
@click="clickAllTwo"
>
全部
</div>
<div
:class="[
'item line1',
{ active: twoIndex === index },
]"
v-for="(item, index) in categoryTwo"
:key="index"
@click="changeData(item.id)"
>
{{ item.name }}
</div>
</div>
</div>
<div class="category-con flex">
<div class="name muted">三级分类</div>
<div class="category-list flex flex-wrap lighter">
<div
:class="[
'item line1',
{ active: threeIndex === '' },
]"
@click="clickAll"
>
全部
</div>
<div
:class="[
'item line1',
{ active: threeIndex === index },
]"
v-for="(item, index) in categoryThree"
:key="index"
@click="changeData(item.id)"
>
{{ item.name }}
</div>
</div>
</div>
</div>
<div class="sort flex bg-white">
<div class="title muted">排序方式</div>
<div class="sort-name m-l-16 flex lighter">
<div
:class="['item', { active: sortType == '' }]"
@click="changeSortType('')"
>
综合
</div>
<div
:class="['item', { active: sortType == 'price' }]"
@click="changeSortType('price')"
>
价格
<i
v-show="priceSort == 'desc'"
class="el-icon-arrow-down"
></i>
<i
v-show="priceSort == 'asc'"
class="el-icon-arrow-up"
></i>
</div>
<div
:class="['item', { active: sortType == 'sales_sum' }]"
@click="changeSortType('sales_sum')"
>
销量
<i
v-show="saleSort == 'desc'"
class="el-icon-arrow-down"
></i>
<i
v-show="saleSort == 'asc'"
class="el-icon-arrow-up"
></i>
</div>
<div
:class="['item', { active: sortType == 'brand' && brandList.length}]"
@click="changeSortType('brand')"
>
品牌
</div>
</div>
</div>
<!-- 品牌 -->
<div class="sort flex bg-white" v-show="sortType == 'brand' && brandList.length > 0">
<div class="category-con flex" style="padding-top: 0;">
<div class="name muted">品牌</div>
<div class="category-list flex flex-wrap lighter">
<div
:class="['item', { active: brandIndex == index }]"
@click="getBrandGoods(index)" v-for="(item,index) in brandList" :key="index"
>
{{ item.name }}
</div>
</div>
</div>
</div>
</div>
<div v-if="isHasGoods" class="goods-list">
<goods-list :list="goodsList" />
<div
class="pagination flex row-center"
style="padding-bottom: 38px"
v-if="count"
>
<el-pagination
background
hide-on-single-page
layout="prev, pager, next"
:total="count"
prev-text="上一页"
next-text="下一页"
:page-size="20"
@current-change="changePage"
>
</el-pagination>
</div>
</div>
<null-data
v-else
:img="require('@/static/images/goods_null.png')"
text="暂无商品~"
></null-data>
</div>
</template>
<script>
import { trottle } from '~/utils/tools'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
watchQuery: true,
async asyncData({ query, $get }) {
let { data } = await $get('pc/category')
return {
categoryList: data,
}
},
data() {
return {
count: 0,
oneIndex: 0,
twoIndex: '',
threeIndex: '',
brandIndex:-1,
categoryOne: [],
categoryTwo: [],
categoryThree: [],
sortType: '',
saleSort: 'desc',
priceSort: 'desc',
brandSort:'desc',
page: '',
goodsList: [],
cateId: 0,
isHasGoods: true,
brandList:[],//
}
},
created() {
this.changeSortType = trottle(this.changeSortType, 500, this)
},
methods: {
changeData(id) {
const { categoryList } = this
this.setIndex(id)
this.categoryOne = categoryList
this.categoryTwo = categoryList[this.oneIndex]
? categoryList[this.oneIndex].sons
: []
this.categoryThree = this.categoryTwo[this.twoIndex]
? this.categoryTwo[this.twoIndex].sons
: []
this.setCateId(id);
this.getGoods();
this.brandIndex = '-1';
this.sortType = '';
this.brandList = [];
},
setCateId(id) {
if (
this.twoIndex == '' &&
this.threeIndex == '' &&
this.oneIndex !== ''
) {
this.cateId = this.categoryOne[this.oneIndex].id
}
if (this.threeIndex == '' && this.twoIndex !== '') {
this.cateId = this.categoryTwo[this.twoIndex].id
}
if (id) {
this.cateId = id
}
},
setIndex(id) {
const { categoryList } = this
categoryList.some((oitem, oindex) => {
if (oitem.id === id) {
this.oneIndex = oindex
this.twoIndex = ''
this.threeIndex = ''
return true
}
return (
oitem.sons &&
oitem.sons.some((witem, windex) => {
if (witem.id === id) {
this.oneIndex = oindex
this.twoIndex = windex
this.threeIndex = ''
return true
}
return (
witem.sons &&
witem.sons.some((titem, tindex) => {
if (titem.id === id) {
this.oneIndex = oindex
this.twoIndex = windex
this.threeIndex = tindex
return true
}
})
)
})
)
})
},
clickAllTwo() {
this.twoIndex = ''
this.threeIndex = ''
this.changeData()
},
clickAll() {
this.threeIndex = ''
this.changeData()
},
changeSortType(type) {
this.sortType = type
switch (type) {
case 'price':
if (this.priceSort == 'asc') {
this.priceSort = 'desc'
} else if (this.priceSort == 'desc') {
this.priceSort = 'asc'
}
break
case 'sales_sum':
if (this.saleSort == 'asc') {
this.saleSort = 'desc'
} else if (this.saleSort == 'desc') {
this.saleSort = 'asc'
}
break
case 'brand':
if (this.brandSort == 'asc') {
this.brandSort = 'desc'
} else if (this.brandSort == 'desc') {
this.brandSort = 'asc'
}
break
default:
}
if(this.sortType == 'brand') {
this.getBrand() //
}else {
this.getGoods()
}
},
changePage(current) {
this.page = current
this.getGoods()
},
async getGoods() {
const { priceSort, sortType, saleSort } = this
const params = {
page_size: 20,
page_no: this.page,
platform_cate_id: this.cateId,
}
switch (sortType) {
case 'price':
params.sort_by_price = priceSort
break
case 'sales_sum':
params.sort_by_sales = saleSort
break
}
if(this.brandIndex >= 0) {
params.brand_id = this.brandList[this.brandIndex].brand_id;
}
const {
data: { lists, count },
} = await this.$get('goods/getGoodsList', {
params,
})
this.goodsList = lists
if (!lists.length) {
this.isHasGoods = false
} else {
this.isHasGoods = true
}
this.count = count
},
//
async getBrand() {
const params = {
page_size: 20,
page_no: this.page,
cate_id: this.cateId,
}
const {
data
} = await this.$get('goods/getBrandListByCateId', {
params,
})
this.brandList = data
},
//
getBrandGoods(index) {
this.brandIndex = index;
this.getGoods();
},
},
watch: {
categoryList: {
immediate: true,
handler(value) {
const { id } = this.$route.query
this.changeData(Number(id))
},
},
},
}
</script>
<style lang="scss" scoped>
.category {
padding: 16px 0;
.category-hd {
.category-wrap {
padding: 0 16px;
}
.category-con {
border-bottom: 1px dashed #e5e5e5;
align-items: flex-start;
padding-top: 16px;
word-wrap: break-word;
.name {
flex: none;
}
.item {
margin-bottom: 16px;
width: 140px;
margin-left: 14px;
cursor: pointer;
&.active {
color: $--color-primary;
}
&:hover {
color: $--color-primary;
}
}
}
.sort {
padding: 15px 16px;
.sort-name {
.item {
margin-right: 30px;
cursor: pointer;
&.active {
color: $--color-primary;
}
}
}
}
}
.brand-list {
border-top: 1px dashed #e5e5e5;
}
}
.goods-list {
margin-top: 20px;
}
</style>

View File

@ -0,0 +1,486 @@
<template>
<div class="confirm-order">
<!-- 配送方式 -->
<div class="order-hd bg-white m-b-16">
<!-- 快递配送 -->
<div>
<div class="title lg">收货地址</div>
<div class="address flex row-between">
<div class="address-con" v-show="address.contact">
<div>
<span class="weight-500">{{ address.contact }}</span>
{{ address.telephone }}
<el-tag size="mini" type="warning" effect="dark" v-if="address.is_default"></el-tag>
</div>
<div class="lighter m-t-8">
{{ address.province }} {{ address.city }}
{{ address.district }}
{{ address.address }}
</div>
<div class="oprate primary flex">
<div class="m-r-16" @click="editAddress(address.id)">
修改
</div>
<div @click="showAddress = true">更换地址</div>
</div>
</div>
<div class="address-add flex row-center" @click="editAddress('')">
+ 添加地址
</div>
</div>
</div>
</div>
<div class="order-con bg-white">
<div class="goods m-b-16">
<div class="title lg">商品明细</div>
<div class="goods-hd flex lighter">
<div class="info text-center">商品信息</div>
<div class="price text-center">商品价格</div>
<div class="num text-center">数量</div>
<div class="money text-center">合计</div>
</div>
<div class="shop">
<div class="shop-item flex-col flex-1" v-for="(item, index) in orderInfo.shop" :key="index">
<div class="shop-name p-l-10 m-b-10 flex flex-1" style="width: 1140px;">
{{ item.shop_name }}
</div>
<div class="goods-list flex flex-wrap flex-1" style="width: 1140px;">
<div :class="['flex', 'item']" v-for="(gitem, gindex) in item.goods" :key="gindex">
<div class="info flex">
<div class="pictrue flex-none">
<el-image :src="gitem.image"></el-image>
</div>
<div>
<div class="name line-2">
{{ gitem.name }}
</div>
<div class="muted m-t-10 xs">
{{ gitem.spec_value }}
</div>
</div>
</div>
<div class="price" style="padding-left: 70px;">
<price-formate :price="gitem.price" />
<div class="flex m-t-6" v-if="gitem.member_amount">
<span class="xs primary">会员价:</span>
<price-formate :price="gitem.member_amount" color="#FF0808" />
</div>
</div>
<div class="num text-center">
{{ gitem.num }}
</div>
<div class="money flex row-center">
<price-formate :price="gitem.sum_price" />
</div>
</div>
</div>
<div class="flex flex-1 col-top m-t-20 row-between" style="width: 1140px;">
<div class="flex flex-1">
<div class="remark flex flex-1 m-r-40">
<div style="width: 70px;">买家备注</div>
<div class="textarea" style="width: 280px">
<el-input size="small" v-model="userRemark[index].remark"
placeholder="选填给商家备注留言100字以内" resize="none">
</el-input>
</div>
</div>
<div class="coupon flex flex-1 m-r-10" v-if="orderInfo.order_type == 0">
<div>店铺优惠</div>
<el-select size="small" v-model="selecteCoupon[index]" placeholder="请选择"
@change="orderBuy">
<el-option label="不使用" :value="0">
</el-option>
<el-option v-for="item in item.coupon_list" :key="item.value"
:label="item.coupon_name" :value="item.id">
</el-option>
</el-select>
</div>
<div class="remark flex flex-1">
<div>配送方式</div>
<span>{{ item.delivery_type_text }}</span>
</div>
</div>
<div class="flex-col">
<div class="flex coupon m-b-10 flex-1 row-right" v-if="item.discount_amount">
<div>优惠</div>
<div>-{{ item.discount_amount }}</div>
</div>
<div class="flex remark m-b-10 flex-1 row-right">
<div>运费</div>
<div>{{ item.shipping_price }}</div>
</div>
<div class="flex m-b-10 flex-1 row-right">
<span class="m-r-10">店铺合计</span>
<price-formate color="#FF2C3C" :price="item.total_amount" :firstSize="17"
:subscriptSize="12" :secondSize="12" />
</div>
<div class="flex m-b-20 flex-1 row-right">
<a target="_blank" :href="download_contract.domain + '/' + download_contract.path"><el-button type="success" icon="el-icon-download">点击下载合同</el-button></a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="order-footer flex bg-white" style="justify-content: space-between;">
<div class="front flex">
<span>开启订单前置</span>
<el-switch v-model="front" @change="front_change"></el-switch>
</div>
<div class="flex col-center">
<div class="money flex m-r-16">
<div class="lighter">实付金额</div>
<div class="primary" style="font-size: 20px">
<span class="xxs">¥</span>{{ orderInfo.total_amount }}
</div>
</div>
<div class="white bg-primary lg btn flex row-center" @click="submitOrder">
去结算
</div>
</div>
</div>
<address-add v-model="showAddressAdd" :aid="editId" @success="orderBuy" />
<address-list v-model="showAddress" @confirm="changeAddress" />
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
async asyncData({ query, $post, $get }) {
let { goods, carts } = JSON.parse(decodeURIComponent(query.data))
carts = carts || []
const asyncData = {}
await $post('order/settlement', {
goods: JSON.stringify(goods),
cart_id: carts.join(),
}).then(({ code, data, msg }) => {
if (code == 1) {
asyncData.orderInfo = data
asyncData.address = data?.address
asyncData.userRemark = data.shop.map((item) => ({
shop_id: item.shop_id,
remark: '',
}))
asyncData.selecteCoupon = data.shop.map(() => '')
}
})
await $post('order/contractDownload', {}).then(({ code, data, msg }) => {
if (code == 1) {
asyncData.download_contract = data;
}
})
return asyncData
},
data() {
return {
orderInfo: {},
address: {},
carts: [],
active: 0,
userRemark: [],
selecteCoupon: [],
showAddress: false,
showAddressAdd: false,
addressId: '',
editId: '',
isEdit: false,
shopPage: 1,
front:false,
is_frontend:0,
download_contract:{} //
}
},
watch: {
address: {
handler(val) {
this.addressId = val.id
},
immediate: true,
},
},
methods: {
...mapActions(['getPublicData']),
editAddress(id) {
this.editId = id
this.showAddressAdd = true
},
changeAddress(val) {
this.addressId = val
this.orderBuy()
},
front_change(e) {
if(e) {
this.is_frontend = 1
}else {
this.is_frontend = 0
}
},
async submitOrder() {
const { carts, goods, selecteCoupon } = this
const { orderInfo: { shop } } = this
const delivery_type = shop[0]?.delivery_type
const submitObj = {
goods: JSON.stringify(goods),
address_id: this.addressId,
is_frontend:this.is_frontend,
cart_id: carts.join(),
coupon_id: selecteCoupon.filter((item) => item),
delivery_type,
remark: this.userRemark.length
? JSON.stringify(this.userRemark)
: '',
}
const { data, code } = await this.$post(
'order/submit_order',
submitObj
)
if (code == 1) {
if(this.is_frontend == 1) {
this.$router.replace({
path: '/user/order',
query: {
is_frontend: this.is_frontend
},
})
}else {
this.getPublicData()
this.$router.replace({
path: '/payment',
query: {
id: data.trade_id,
from: data.type,
},
})
}
}
},
async orderBuy() {
console.log(this.selecteCoupon)
const { data, code } = await this.$post('order/settlement', {
goods: JSON.stringify(this.goods),
address_id: this.addressId,
cart_id: this.carts.join(),
coupon_id: this.selecteCoupon.filter((item) => item),
})
if (code == 1) {
let { address } = data
this.orderInfo = data
this.address = address
}
},
},
created() {
const { goods, type, carts } = JSON.parse(
decodeURIComponent(this.$route.query.data)
)
this.goods = goods
this.type = type
this.carts = carts || []
},
}
</script>
<style lang="scss" scoped>
.confirm-order {
padding: 16px 0;
.title {
padding: 12px 20px;
font-weight: bold;
>i {
cursor: pointer;
}
}
.contact {
padding: 10px 20px 22px;
&-item {
display: flex;
align-items: center;
height: 36px;
&-label {
width: 72px;
color: #999;
}
}
}
.order-hd {
.address {
padding: 10px 20px 22px;
.address-con {
position: relative;
cursor: pointer;
padding: 16px 20px;
width: 800px;
height: 100px;
padding-right: 150px;
border: 1px solid $--color-primary;
border-radius: 2px;
&:hover {
.oprate {
display: flex;
}
}
.oprate {
display: none;
position: absolute;
right: 20px;
bottom: 9px;
}
}
.address-add {
cursor: pointer;
width: 320px;
height: 100px;
border: 1px dashed $--border-color-base;
}
}
}
.order-con {
.shop {
padding: 0 20px;
.shop-name {
height: 40px;
background-color: #f6f6f6;
line-height: 40px;
}
}
.goods {
border-bottom: 1px dashed $--border-color-base;
.goods-hd {
height: 40px;
padding: 0 20px;
}
.goods-list {
.item {
padding: 10px 0;
&-disabled {
position: relative;
&::before {
z-index: 9;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
height: 100%;
display: block;
content: '';
background-color: rgba($color: #ffffff,
$alpha: 0.5);
}
}
}
}
.info {
width: 500px;
.pictrue {
margin-right: 10px;
.el-image {
width: 72px;
height: 72px;
}
}
.name {
margin-bottom: 10px;
}
.delivery-support {
font-size: 12px;
padding: 4px 15px;
border-radius: 60px;
margin-left: 20px;
background-color: #f4f4f4;
color: #666666;
}
}
.price {
width: 200px;
}
.num {
width: 250px;
}
.money {
width: 200px;
}
}
.input {
.textarea {
margin: 0 20px;
width: 1000px;
}
}
.integral {
.check-box {
padding: 0 20px 12px;
}
}
}
.order-footer {
margin-top: 2px;
padding: 25px 20px;
justify-content: flex-end;
.btn {
width: 152px;
height: 44px;
border-radius: 6px;
cursor: pointer;
}
}
}
</style>

View File

@ -0,0 +1,255 @@
<template>
<div class="news-details-container mt16">
<div class="nav-container flex">
<div class="nr" style="width: 70px">当前位置</div>
<el-breadcrumb style="flex: 1;" separator="/" class="flex">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>
<nuxt-link to="/demand_list">我的需求</nuxt-link>
</el-breadcrumb-item>
<el-breadcrumb-item class="line1 demand-title">{{detailsObj.name}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="content-box">
<div class="news-detail-box m-r-16">
<div class="content-header bg-white">
<div class="news-detail-title">
{{detailsObj.name}}
</div>
<div class="sign"><el-button type="primary" icon="el-icon-s-promotion" @click="dialogFormVisible = true">立即报名</el-button></div>
<div class="flex">
<div class="sm muted">
发布时间{{detailsObj.create_time}}
</div>
<div class="flex" style="margin-left: 40px">
<i class="el-icon-s-promotion muted"></i>
<div class="muted" style="margin-left: 3px;">已报名<span style="margin:0 5px;color: #f00;">{{detailsObj.reports_count}}</span></div>
</div>
</div>
</div>
<div class="content-html-box bg-white">
<div v-html="detailsObj.content"></div>
</div>
</div>
</div>
<!-- 填写表单 -->
<el-dialog title="立即报名" :visible.sync="dialogFormVisible">
<el-form :model="form" :rules="rules" ref="form">
<el-form-item label="姓名" prop="name" :label-width="formLabelWidth">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="电话" prop="phone" :label-width="formLabelWidth">
<el-input v-model="form.phone" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="公司名称" prop="company" :label-width="formLabelWidth">
<el-input v-model="form.company" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="报价" prop="price" :label-width="formLabelWidth">
<el-input v-model="form.price" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="其他" :label-width="formLabelWidth">
<el-input type="textarea" v-model="form.remarks" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="submitForm('form')"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
$get,
$post,
query
}) {
let detailsObj = {};
let demand_id = '';
let recommend_list = [];
demand_id = query.id
let res = await $get("demand/detail", {
params: {
id: query.id,
}
});
if (res.code == 1) {
detailsObj = res.data;
}
return {
detailsObj,
demand_id
};
},
watchQuery: ['id'],
data() {
return {
demand_id:'',
dialogFormVisible: false,
form: {
name: '',
phone: '',
company: '',
price: '',
remarks: '',
},
formLabelWidth: '120px',
rules: {
name: [
{ required: true, message: '请输入姓名', trigger: 'blur' },
],
phone: [
{ required: true, message: '请输入电话', trigger: 'blur' },
],
company: [
{ required: true, message: '请输入公司名称', trigger: 'blur' },
],
price: [
{ required: true, message: '请输入报价', trigger: 'blur' },
],
}
}
},
mounted() {
console.log('route', this.$route)
// this.getNewsDetails(this.$route.query.id);
},
methods: {
async getNewsDetails(id) {
let res = await this.$get("help/detail", {params: {id: id, client: 2}});
if(res.code == 1) {
this.detailsObj = res.data;
}
},
toOther(id) {
this.$router.push('/help_center/help_center_detail?id=' + id)
},
//
submitForm(form) {
console.log(this.demand_id)
this.$refs[form].validate((valid) => {
if (valid) {
console.log(this.form)
let params = this.form;
params.demand_id = this.demand_id;
this.$post("demand/report", params).then(res=>{
if(res.code == 1) {
this.dialogFormVisible = false,
this.$message({
message: '报名成功',
type: 'success'
});
}
});
} else {
return false;
}
});
},
}
}
</script>
<style lang="scss" scoped>
.news-details-container {
.nav-container {
padding: 15px 16px;
}
.content-box {
display: flex;
flex-direction: row;
.news-detail-box {
background-color: #FFFFFF;
width: 100%;
.content-header {
margin: 0px 20px;
padding: 20px 0px;
border-bottom: 1px solid #e5e5e5;
position: relative;
.news-detail-title {
color: #222;
font-size: 24px;
font-weight: 500;
margin-bottom: 30px;
max-width: 860px;
}
}
.content-html-box {
padding: 24px 20px;
&>div {
width: 100%;
overflow: hidden;
::v-deep img {
width: 100%;
}
}
}
}
.recommend-box {
width: 264px;
.recommend-box-header {
padding: 15px 10px;
border-bottom: 1px solid #e5e5e5;
.primary-line {
margin-right: 10px;
background-color: $--color-primary;
width: 4px;
height: 20px;
}
}
.recommend-box-content {
.recommend-list-container {
.recommend-list-item {
padding: 10px;
cursor: pointer;
.goods-info {
margin-top: 8px;
}
}
}
}
}
}
}
.demand-title {
max-width: 900px;
line-height: 30px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.sign {
position: absolute;
right: 0;
top: 30px;
}
</style>

View File

@ -0,0 +1,207 @@
<template>
<div class="help-center-container">
<div class="help-center-box">
<div class="article-lists-container m-l-16 bg-white" style="width: 100%;">
<div v-show="!dataNull">
<div>
<nuxt-link :to="'/demand_list/demand_detail?id=' + item.id"
class="article-item flex-col bg-white" v-for="(item) in articleList" :key="item.id">
<div class="lg article-name line2" style="font-weight: bold;">{{item.name}}</div>
<div class="lighter article-content" v-html="item.content"></div>
<div class="flex row-between" style="margin-top:16px;">
<div class="sm muted">发布时间{{item.create_time}}</div>
<div class="flex m-l-16">
<i class="el-icon-s-promotion muted"></i>
<div class="muted" style="margin-left: 3px;">已报名<span style="margin:0 5px;color: #f00;">{{item.reports_count}}</span></div>
</div>
</div>
<div class="sign"><el-button type="primary" icon="el-icon-s-promotion">查看报名</el-button></div>
</nuxt-link>
</div>
<div class="help-center-pagination row-center">
<el-pagination background hide-on-single-page layout="prev, pager, next" :total="count"
prev-text="上一页" next-text="下一页" :page-size="10" @current-change="changePage" />
</div>
</div>
<div class="data-null column-center" v-show="dataNull">
<img style="width: 150px;height: 150px;" src="~/static/images/news_null.png" />
<div class="xs muted">
暂无消息记录
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
$get,
$post
}) {
let currentId = 0;
let articleList = [];
let count = 0;
let dataNull = true;
let listsRes = await $get("demand/lists", {
params: {
page_size: 1,
}
});
if (listsRes.code == 1) {
articleList = listsRes.data.list;
count = listsRes.data.count
if (count <= 0) {
dataNull = true;
} else {
dataNull = false
}
}
return {
articleList,
count,
dataNull,
}
},
data() {
return {
articleList: [],
count: 0,
swiperOptions: {
width: 1180,
}
}
},
mounted() {
console.log(this.articleList, 'articleList')
},
methods: {
async changePage(current) {
let res = await this.$get("demand/lists", {
params: {
cid: this.currentId,
page_no: current,
page_size: 10
}
});
if (res.code == 1) {
this.articleList = res.data.list;
if (this.articleList.length <= 0) {
dataNull = true;
} else {
dataNull = false
}
}
},
changeList(id) {
this.currentId = id;
this.changePage(1)
}
}
}
</script>
<style lang="scss" scoped>
.help-center-container {
.help-center-banner {
margin-top: 16px;
}
.help-center-box {
margin-top: 16px;
display: flex;
flex-direction: row;
.help-center-aside {
width: 160px;
// min-height: 635px;
padding-top: 20px;
padding-bottom: 20px;
padding: 20px 30px;
.nav {
li {
margin: 10px 0px;
padding: 0px 30px;
cursor: pointer;
}
.active-item {
padding-left: 27px;
color: $--color-primary;
border-left: 3px solid $--color-primary;
}
}
}
.article-lists-container {
width: 1004px;
display: flex;
flex-direction: column;
justify-content: space-between;
.article-item {
margin: 0px 20px;
padding: 15px 0px;
border-bottom: 1px solid #E5E5E5;
cursor: pointer;
position: relative;
.article-name {
margin-bottom: 11px;
margin-top: 13px;
max-width: 720px;
}
}
.help-center-pagination {
padding-top: 38px;
margin-bottom: 30px;
}
.data-null {
padding-top: 150px;
}
}
}
}
::v-deep .el-pagination.is-background .btn-prev {
background: #fff;
padding: 0 10px;
}
::v-deep .el-pagination.is-background .btn-next {
background: #fff;
padding: 0 10px;
}
::v-deep .el-pagination.is-background .el-pager li {
background: #fff;
padding: 0 10px;
}
.article-content {
min-height: 50px;
max-height: 140px;
overflow: hidden;
}
.sign {
position: absolute;
right: 0;
top: 30px;
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<div class="get-coupons">
<div class="help-center-banner">
<client-only>
<swiper ref="mySwiper" :options="swiperOptions">
<swiper-slide class="swiper-item" v-for="(item, index) in bannerList" :key="index">
<ad-item :item="item"></ad-item>
</swiper-slide>
</swiper>
</client-only>
</div>
<div class="coupons bg-white">
<div class="title weight-500">每日领券</div>
<div class="list">
<coupons-list v-if="couponList.length" :list="couponList" :type="3" @reflash="getCouponsList" />
<null-data v-else :img="require('~/static/images/coupon_null.png')" text="暂无优惠券~"></null-data>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
query,
$get
}) {
const {
data
} = await $get("coupon/getCouponList");
console.log('datafadadaasd', data)
const { data: banner }= await $get("ad_content/lists", { params: { pid: 27, terminal: 2 } });
return {
couponList: data.lists,
bannerList: banner,
};
},
data() {
return {
swiperOptions: {
width: 1180,
}
}
},
methods: {
async getCouponsList() {
const {
data,
code
} = await this.$get("coupon/getCouponList");
if (code == 1) {
this.couponList = data.lists;
}
},
},
};
</script>
<style lang="scss">
.get-coupons {
padding: 16px 0;
.coupons {
padding: 0 14px;
.title {
padding: 16px 18px;
font-size: 20px;
}
}
}
</style>

View File

@ -0,0 +1,867 @@
<template>
<div>
<div class="goods-details" v-if="goodsDetails.id">
<div class="goods-info flex col-stretch">
<div class="goods-swiper m-r-16 bg-white flex-col" v-if="goodsImage != ''">
<el-image class="current-img" :preview-src-list="goodsImage.map((item) => item.uri)"
:src="goodsImage[swiperIndex].uri"></el-image>
<client-only>
<swiper class="swiper" ref="mySwiper" :options="swiperOptions">
<swiper-slide :class="{
'swiper-item': true,
active: index === swiperIndex,
}" v-for="(item, index) in goodsImage" :key="index">
<div style="width: 100%; height: 100%" @mouseover="swiperIndex = index">
<el-image style="width: 100%; height: 100%" :src="item.uri"></el-image>
</div>
</swiper-slide>
<div class="swiper-button-prev" slot="button-prev"></div>
<div class="swiper-button-next" slot="button-next"></div>
</swiper>
</client-only>
</div>
<!-- 右侧商品信息 -->
<div class="info-wrap bg-white flex-1">
<div class="name weight-500 m-b-16">
{{ goodsDetails.name }}
</div>
<!-- -->
<div class="seckill flex white" v-if="activity.type == 1">
<div class="xxl">限时秒杀</div>
<div class="flex">
<div class="white m-r-16">距离结束还有</div>
<count-down :time="countTime" :is-slot="true" @change="onChangeDate">
<div class="flex row-center count-down xxl">
<div class="item white">{{ timeData.hours }}</div>
<div class="white" style="margin: 0 4px">:</div>
<div class="item white">{{ timeData.minutes }}</div>
<div class="white" style="margin: 0 4px">:</div>
<div class="item white">{{ timeData.seconds }}</div>
</div>
</count-down>
</div>
</div>
<!-- -->
<!-- -->
<div class="price-wrap lighter">
<div class="flex row-between">
<div class="price">
<div class="flex" v-if="Number(checkedGoods.market_price || goodsDetails.market_price)">
{{ activity.type == 1 ? '日常价' : '原价' }}
<span class="m-l-20">
<price-formate :price="checkedGoods.market_price || goodsDetails.market_price" :weight="400" />
</span>
</div>
<div class="flex m-t-10">
{{ activity.type == 1 ? '秒杀价' : '价格' }}
<div class="primary m-l-20">
<price-formate :price="checkedGoods.price || goodsDetails.min_price"
:subscript-size="16" :first-size="26" :second-size="16" />
</div>
<div class="member-price m-l-10 flex xs"
v-if="activity.type != 1 && (checkedGoods.member_price || goodsDetails.member_price)">
会员价
<price-formate :price="checkedGoods.member_price || goodsDetails.member_price"
:weight="400" />
</div>
</div>
</div>
<div class="rate flex-col row-right">
<div class="primary" style="font-size: 20px">{{ comment.percent }}</div>
<div class="lighter">好评率</div>
</div>
</div>
</div>
<!-- -->
<div class="sales-click flex">
<div class="flex-1">销量{{ goodsDetails.sales_sum }}</div>
<div class="flex-1">浏览量{{ goodsDetails.clicks }}</div>
</div>
<div class="spec-wrap">
<div class="spec flex m-b-16" v-for="(item, index) in goodsSpec" :key="index">
<div class="lighter spec-name">{{ item.name }}</div>
<div class="spec-list flex flex-wrap">
<div :class="[
'spec-item lighter',
{ active: specitem.checked },
]" v-for="(specitem, sindex) in item.spec_value" :key="sindex"
@click="onChoseSpecItem(item.id, specitem.id)">
{{ specitem.value }}
</div>
</div>
</div>
</div>
<div class="goods-num flex">
<div class="num lighter">数量</div>
<number-box v-model="goodsNum" :min="1" :max="checkedGoods.stock" />
<div class="m-l-10">
库存: {{ checkedGoods.stock }}
</div>
</div>
<div class="goods-btns flex lg">
<el-button type="primary" class="btn white" @click="onBuyNow">
立即购买
</el-button>
<el-button type="primary" plain class="btn addcart" @click="onAddCart"
v-if="goodsDetails.type == 0 && activity.type != 1">
加入购物车
</el-button>
<div class="btn collection flex row-center" @click="onCollectionGoods">
<img class="start-icon m-r-8" :src="
goodsDetails.is_collect
? require('~/static/images/icon_star_s.png')
: require('~/static/images/icon_star.png')
" />
<span>{{ goodsDetails.is_collect ? '取消收藏' : '收藏商品' }}</span>
</div>
</div>
</div>
<div class="shop m-l-16 bg-white">
<div class="shop-logo flex-col col-center">
<el-image class="logo-img" :src="shop.logo"></el-image>
<nuxt-link class="m-t-10" :to="`/shop_street_detail?id=${shop.id}`">
<el-tag size="mini" v-if="shop.type == 1"></el-tag>
<span class="weight-500">{{ shop.name }}</span>
</nuxt-link>
<div class="xs muted m-t-10 line-5">
{{ shop.intro }}
</div>
</div>
<div class="flex m-t-20">
<div class="flex-1 text-center">
<div class="xxl m-b-10">{{ shop.goods_on_sale }}</div>
<div>全部商品</div>
</div>
<div class="flex-1 text-center">
<div class="xxl m-b-10">{{ shop.follow_num }}</div>
<div>关注人数</div>
</div>
</div>
<el-divider></el-divider>
<div class="flex xs m-b-16">
<div class="m-r-12">店铺星级</div>
<div class="m-t-5">
<el-rate v-model="shop.star" disabled> </el-rate>
</div>
</div>
<div class="flex xs m-b-16">
<div class="m-r-12">店铺评分</div>
<div class="">{{ shop.score }}</div>
</div>
<div>
<el-button type="primary" size="mini" @click="
$router.push(`/shop_street_detail?id=${shop.id}`)
">进入店铺</el-button>
<el-button size="mini" @click="changeShopFollow">{{
shop.shop_follow_status == 1 ? '已关注' : '关注店铺'
}}</el-button>
</div>
<el-popover placement="bottom" width="200" trigger="hover">
<div>
<el-image style="width: 100%" :src="shop.customer_image"></el-image>
</div>
<div slot="reference" class="xs lighter text-center m-t-30">
<i class="el-icon-chat-dot-round nr"></i>
<span>联系客服</span>
</div>
</el-popover>
</div>
</div>
<div class="details-wrap flex m-t-16">
<div class="details bg-white flex-1">
<el-tabs v-model="active">
<el-tab-pane label="商品详情">
<div class="details-tips" v-if="goodsDetails.custom_params.length">
<h2>产品参数</h2>
<div class="boxs">
<div class="tit" v-for="(items,index) in goodsDetails.custom_params" :key="index">
<span class="st">{{items.key}}:</span>{{items.value}}
</div>
</div>
</div>
<div class="rich-text" v-html="goodsDetails.content"></div>
</el-tab-pane>
<el-tab-pane label="商品评价">
<div class="evaluation">
<div class="evaluation-hd flex">
<div class="rate flex">
<div class="lighter m-r-8">好评率</div>
<div class="primary" style="font-size: 30px">
{{ goodsDetails.comment.percent }}
</div>
</div>
<div class="score flex">
<span class="m-r-8 lighter">评分</span>
<el-rate :value="goodsDetails.comment.goods_comment" disabled allow-half></el-rate>
</div>
</div>
<div class="evaluation-tab flex">
<div :class="[
'item',
{ active: commentActive == item.id },
]" v-for="(item, index) in comment.comment" :key="index"
@click="commentActive = item.id">
{{ item.name }}({{ item.count }})
</div>
</div>
</div>
<div>
<template v-for="(item, index) in comment.comment">
<comment-list v-if="commentActive == item.id" :goods-id="id" :type="item.id"
:key="index"></comment-list>
</template>
</div>
</el-tab-pane>
</el-tabs>
</div>
<div class="goods-like m-l-16" v-if="shop.goods_list.length">
<div class="title bg-white flex p-l-15">店铺推荐</div>
<div class="goods-list">
<template v-for="(item, index) in shop.goods_list">
<nuxt-link :to="`/goods_details/${item.id}`" class="item bg-white m-b-16" v-if="index < 5"
:key="index">
<el-image class="goods-img" :src="item.image"></el-image>
<div class="goods-name line-2">
{{ item.name }}
</div>
<div class="price flex m-t-8">
<div class="primary m-r-8">
<price-formate :price="item.min_price" :first-size="16" />
</div>
<div class="muted sm line-through">
<price-formate :price="item.market_price" />
</div>
</div>
</nuxt-link>
</template>
</div>
</div>
</div>
</div>
<!-- 推荐 -->
<div class="activity-area m-t-16">
<div class="title flex row-between">
<div class="font-size-20">推荐商品</div>
</div>
<div class="active-goods flex">
<div class="goods-list flex">
<nuxt-link
class="goods-item"
:to="`/goods_details/${gitem.id}`"
v-for="(gitem, gindex) in dataRecommend"
:key="gindex"
>
<div class="goods-img">
<el-image
lazy
:src="gitem.image"
fit="cover"
alt=""
></el-image>
</div>
<div class="name line-2 m-t-10">{{ gitem.name }}</div>
<div class="price flex col-baseline m-t-10">
<div class="primary m-r-8">
<price-formate
:price="gitem.min_price"
:first-size="16"
/>
</div>
<div class="muted sm line-through ">
<price-formate
:price="gitem.market_price"
/>
</div>
</div>
<div class="muted xs m-t-10">
{{ gitem.sales_total }}人购买
</div>
</nuxt-link>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions } from 'vuex'
import { Message } from 'element-ui'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
async asyncData({ params, $get, app }) {
const { data: dataRecommend } = await $get('goods/getRecommendGoods',{params: {goods_id: params.id}})
const { data, code, msg } = await $get('goods/getGoodsDetail', {
params: { goods_id: params.id },
})
if (code == 0) {
setTimeout(() => app.router.back(), 1500)
}
return {
dataRecommend: dataRecommend,
goodsDetails: data,
goodsImage: data.goods_image,
activity: data.activity,
shop: data.shop,
}
},
data() {
return {
goodsDetails: {},
goodsImage: [],
activity: {},
shop: {
goods_list: [],
},
swiperOptions: {
pagination: {
el: '.swiper-pagination',
clickable: true,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
preventClicks: true,
slidesPerView: 'auto',
},
active: '0',
commentActive: 0,
swiperIndex: 0,
checkedGoods: {},
comment: {},
goodsNum: 1,
goodsSpec: [],
id: '',
timeData: {},
dataRecommend: [], //
}
},
created() {
this.id = this.$route.params.id
this.getComment(this.id)
},
methods: {
...mapActions(['getPublicData']),
onClickSlide(e) {
this.swiperIndex = e
},
onChoseSpecItem(id, specid) {
const { goodsSpec } = this
goodsSpec.forEach((item) => {
if (item.spec_value && item.id == id) {
item.spec_value.forEach((specitem) => {
specitem.checked = 0
if (specitem.id == specid) {
specitem.checked = 1
}
})
}
})
this.goodsSpec = [...goodsSpec]
},
async onAddCart() {
const {
goodsNum,
checkedGoods: { id },
} = this
const { code, data, msg } = await this.$post('cart/add', {
item_id: id,
goods_num: goodsNum,
})
if (code == 1) {
this.getPublicData()
this.$message({
message: msg,
type: 'success',
})
}
},
async changeShopFollow() {
const { code, msg } = await this.$post('shop_follow/changeStatus', {
shop_id: this.shop.id,
})
if (code == 1) {
this.$message({
message: msg,
type: 'success',
})
this.getGoodsDetail()
}
},
onBuyNow() {
const {
goodsNum,
checkedGoods: { id },
} = this
const goods = [
{
item_id: id,
num: goodsNum,
goods_id: this.id,
shop_id: this.shop.id,
},
]
this.$router.push({
path: '/confirm_order',
query: {
data: encodeURIComponent(
JSON.stringify({
goods,
type: 'buy',
})
),
},
})
},
async getGoodsDetail() {
const { data, code } = await this.$get('goods/getGoodsDetail', {
params: { goods_id: this.id },
})
if (code == 1) {
this.goodsDetails = data
this.shop = data.shop
}
},
async onCollectionGoods() {
const { data, code, msg } = await this.$post(
'goods_collect/changeStatus',
{
goods_id: this.id,
}
)
if (code == 1) {
this.$message({
message: msg,
type: 'success',
})
this.getGoodsDetail()
}
},
async getComment() {
const { data, code } = await this.$get('/goods_comment/category', {
params: { goods_id: this.id },
})
if (code == 1) {
this.comment = data
this.commentActive = data.comment[0].id
}
},
onChangeDate(e) {
let timeData = {}
for (let prop in e) {
if (prop !== 'milliseconds')
timeData[prop] = ('0' + e[prop]).slice(-2)
}
this.timeData = timeData
},
},
watch: {
goodsSpec: {
immediate: true,
handler(value) {
const { goods_item } = this.goodsDetails
let keyArr = []
value.forEach((item) => {
if (item.spec_value) {
item.spec_value.forEach((specitem) => {
if (specitem.checked) {
keyArr.push(specitem.id)
}
})
}
})
if (!keyArr.length) return
let key = keyArr.join(',')
let index = goods_item.findIndex((item) => {
return item.spec_value_ids == key
})
if (index == -1) {
index = 0
}
this.checkedGoods = goods_item[index]
console.log(this.checkedGoods)
},
},
goodsDetails: {
immediate: true,
handler(value) {
if (!value.goods_spec) return
value.goods_spec.forEach((item) => {
item.spec_value.forEach((specitem, specindex) => {
if (specindex == 0) {
specitem.checked = 1
} else {
specitem.checked = 0
}
})
})
this.goodsSpec = [...value.goods_spec]
},
},
},
computed: {
countTime() {
const end_time = this.activity.end_time
return end_time ? end_time - Date.now() / 1000 : 0
},
},
}
</script>
<style lang="scss" scoped>
.goods-details {
padding: 16px 0 44px;
.goods-info {
.goods-swiper {
width: 400px;
border-radius: 4px;
.swiper {
margin: 10px 0;
padding: 0 25px;
--swiper-navigation-size: 15px;
--swiper-navigation-color: #888;
.swiper-button-next,
.swiper-button-prev {
top: 0;
width: 25px;
height: 100%;
margin-top: 0;
background-size: 12px 22px;
}
.swiper-button-prev {
left: 0;
}
.swiper-button-next {
right: 0;
}
.swiper-item {
cursor: pointer;
height: 66px;
width: 66px;
border: 2px solid transparent;
&~.swiper-item {
margin-left: 10px;
}
&.active {
border-color: $--color-primary;
}
}
}
.current-img {
width: 100%;
height: 400px;
}
}
.info-wrap {
min-height: 486px;
min-width: 504px;
border-radius: 4px;
padding: 20px;
.name {
font-size: 20px;
}
.seckill {
background-color: $--color-primary;
padding: 6px 10px;
.count-down {
.item {
width: 30px;
height: 30px;
background: rgba(0, 0, 0, 0.3);
text-align: center;
line-height: 30px;
border-radius: 4px;
}
}
}
.price-wrap {
background: #f6f6f6;
background-size: 100%;
padding: 16px 16px;
.member-price {
background-color: #482406;
color: #fdebd5;
border-radius: 100px 100px 100px 0px;
padding: 0 6px;
}
}
.sales-click {
border-bottom: 1px dashed $--border-color-base;
line-height: 28px;
text-align: center;
padding: 6px;
&>div:first-of-type {
border-right: 1px solid $--border-color-base;
}
}
.spec-wrap {
margin-top: 20px;
.spec {
align-items: flex-start;
.spec-name {
margin-right: 20px;
margin-top: 6px;
flex: none;
}
.spec-item {
padding: 0 20px;
line-height: 32px;
border: $--border-base;
border-radius: 2px;
margin-right: 10px;
margin-bottom: 10px;
cursor: pointer;
&.active {
color: $--color-primary;
background-color: #ffeeef;
border-color: currentColor;
}
}
}
}
.goods-num {
margin-bottom: 30px;
.num {
margin-right: 20px;
}
}
.goods-btns {
.btn {
margin-right: 14px;
text-align: center;
width: 120px;
font-size: 16px;
&.collection {
width: 146px;
line-height: 42px;
border: 1px solid rgba(229, 229, 229, 0.89804);
background-color: #fff;
border-radius: 4px;
cursor: pointer;
color: #666;
&:hover {
color: $--color-primary;
}
.start-icon {
width: 18.5px;
height: 18px;
}
}
}
}
}
.shop {
width: 210px;
padding: 16px;
.logo-img {
width: 62px;
height: 62px;
border-radius: 50%;
overflow: hidden;
}
.el-rate__icon {
font-size: 16px;
}
}
}
.rich-text img {
width: 100%;
display: block;
}
.details-wrap {
align-items: stretch;
.details {
padding: 10px 0;
overflow: hidden;
.rich-text {
padding: 0 10px;
width: 100%;
overflow: hidden;
img {
width: 100%;
display: block;
}
p {
margin: 0;
}
}
.evaluation {
.evaluation-hd {
height: 80px;
margin: 0 10px;
.rate {
height: 60px;
width: 220px;
border-right: 1px solid #e5e5e5;
padding-left: 10px;
margin-right: 40px;
}
}
.evaluation-tab {
margin: 16px 20px;
.item {
border-radius: 2px;
cursor: pointer;
height: 32px;
padding: 6px 20px;
color: #666;
background-color: #f2f2f2;
margin-right: 10px;
&.active {
color: #fff;
background-color: $--color-primary;
}
}
}
}
}
}
.goods-like {
width: 210px;
.title {
border-bottom: $--border-base;
height: 45px;
}
.goods-list {
.item {
padding: 10px;
display: block;
.goods-img {
width: 190px;
height: 190px;
margin-bottom: 10px;
}
}
}
}
}
.details-tips {
padding:20px;
h2 {
margin: 0 0 20px 0;
}
.boxs {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
column-gap: 10px;
row-gap: 10px;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: keep-all; /* 长单词换行 */
word-break: break-all; /* 单词内换行 */
.tit {
font-size: 14px;
.st {
font-size: 16px;
font-weight: bold;
margin-right: 5px;
}
}
}
}
.activity-area {
padding: 16px;
border-radius: 6px;
background-color: #fff;
.title {
font-size: 36px;
font-weight: bold;
margin-top: 10px;
margin-left: 10px;
}
.goods-list {
flex-wrap: wrap;
.goods-item {
width: 14.6%;
margin: 20px 1% 0 1%;
.goods-img {
width: 100%;
height: 0;
padding-top: 100%;
position: relative;
.el-image {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
}
.name {
line-height: 20px;
height: 40px;
}
}
}
}
</style>

View File

@ -0,0 +1,182 @@
<template>
<div class="goods-list">
<div class="banner m-t-16">
<!-- <ad-item :item="ad" v-if="ad.image"></ad-item> -->
<client-only>
<swiper ref="mySwiper" :options="swiperOptions">
<swiper-slide class="swiper-item" v-for="(item, index) in ad" :key="index">
<ad-item :item="item"></ad-item>
</swiper-slide>
</swiper>
</client-only>
</div>
<div class="sort m-b-16 flex bg-white">
<div class="sort-title">排序方式</div>
<div class="sort-name m-l-16 flex">
<div :class="['item', { active: sortType == '' }]" @click="changeSortType('')">
综合
</div>
<div :class="['item', { active: sortType == 'price' }]" @click="changeSortType('price')">
价格
<i v-show="priceSort == 'desc'" class="el-icon-arrow-down"></i>
<i v-show="priceSort == 'asc'" class="el-icon-arrow-up"></i>
</div>
<div :class="['item', { active: sortType == 'sales_sum' }]" @click="changeSortType('sales_sum')">
销量
<i v-show="saleSort == 'desc'" class="el-icon-arrow-down"></i>
<i v-show="saleSort == 'asc'" class="el-icon-arrow-up"></i>
</div>
</div>
</div>
<template v-if="goodsList.length">
<goods-list :list="goodsList" />
<div class="pagination flex m-t-30 row-center" style="padding-bottom: 38px" v-if="count">
<el-pagination background layout="prev, pager, next" :total="count" prev-text="" next-text=""
hide-on-single-page :page-size="20" @current-change="changePage">
</el-pagination>
</div>
</template>
<null-data v-else :img="require('~/static/images/goods_null.png')" text="暂无商品~"></null-data>
</div>
</template>
<script>
import { trottle } from "~/utils/tools";
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
async asyncData({ $get, params, query }) {
const { type } = params;
let pid = 0;
let ad = [];
switch (type) {
case "1":
pid = 25;
break;
case "2":
pid = 26;
break;
}
const { data } = await $get("ad_content/lists", {
params: {
pid: pid,
terminal: 2,
},
});
if (!data.length) return;
ad = data
return { ad };
},
components: {},
data() {
return {
sortType: "",
swiperOptions: {
width: 1180,
},
saleSort: "desc",
priceSort: "desc",
page: "",
count: 0,
ad: "",
goodsList: [],
};
},
created() {
this.getGoods();
this.changeSortType = trottle(this.changeSortType, 500, this);
},
methods: {
changeSortType(type) {
this.sortType = type;
switch (type) {
case "price":
if (this.priceSort == "asc") {
this.priceSort = "desc";
} else if (this.priceSort == "desc") {
this.priceSort = "asc";
}
break;
case "sales_sum":
if (this.saleSort == "asc") {
this.saleSort = "desc";
} else if (this.saleSort == "desc") {
this.saleSort = "asc";
}
break;
default:
}
this.getGoods();
},
changePage(current) {
this.page = current;
this.getGoods();
},
async getGoods() {
const { name } = this.$route.query;
const { priceSort, sortType, saleSort } = this;
let sort = "";
switch (sortType) {
case "price":
sort = priceSort;
break;
case "sales_sum":
sort = saleSort;
break;
}
const {
data: { list, count },
} = await this.$get("pc/goodsList", {
params: {
page_size: 20,
page_no: this.page,
sort_type: sortType,
sort,
name,
},
});
this.count = count;
this.goodsList = list;
},
},
watch: {
'$route.query.name' () {
this.getGoods();
}
}
};
</script>
<style lang="scss">
.goods-list {
.banner {
img {
width: 100%;
display: block;
}
}
.sort {
padding: 15px 16px;
.sort-name {
.item {
margin-right: 30px;
cursor: pointer;
&.active {
color: $--color-primary;
}
}
}
}
}
</style>

View File

@ -0,0 +1,189 @@
<template>
<div class="news-details-container mt16">
<div class="nav-container flex">
<div class="nr" style="width: 70px">当前位置</div>
<el-breadcrumb style="flex: 1;" separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>
<nuxt-link to="/help_center">帮助中心</nuxt-link>
</el-breadcrumb-item>
<el-breadcrumb-item class="line1" style="max-width: 800px;">{{detailsObj.title}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="content-box">
<div class="news-detail-box m-r-16">
<div class="content-header bg-white">
<div class="news-detail-title">
{{detailsObj.title}}
</div>
<div class="flex">
<div class="sm muted">
发布时间{{detailsObj.create_time}}
</div>
<div class="flex" style="margin-left: 40px">
<i class="el-icon-view muted"></i>
<div class="muted" style="margin-left: 3px;">{{detailsObj.visit}} 人浏览</div>
</div>
</div>
</div>
<div class="content-html-box bg-white">
<div v-html="detailsObj.content"></div>
</div>
</div>
<div class="recommend-box">
<div class="recommend-box-header flex bg-white">
<div class="primary-line"></div>
<div class="xxl" style="font-weight: 500">为您推荐</div>
</div>
<div class="recommend-box-content bg-white">
<div class="recommend-list-container">
<div class="recommend-list-item" v-for="(item) in recommend_list" :key="item.id"
@click="toOther(item.id)">
<el-image style="width: 244px; height:183px;border-radius: 6px" fit="cover"
:src="item.image" />
<div class="goods-info">
<div class="line2 goods-name">{{item.title}}</div>
<div class="flex" style="margin-top: 10px">
<i class="el-icon-view muted"></i>
<div class="muted xs" style="margin-left: 4px;">{{item.visit}} 人浏览</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
$get,
$post,
query
}) {
let detailsObj = {};
let recommend_list = [];
let res = await $get("help/detail", {
params: {
id: query.id,
client: 2
}
});
if (res.code == 1) {
detailsObj = res.data;
recommend_list = res.data.recommend_list
}
return {
detailsObj,
recommend_list,
};
},
watchQuery: ['id'],
data() {
return {
recommend_list: []
}
},
mounted() {
console.log('route', this.$route)
// this.getNewsDetails(this.$route.query.id);
},
methods: {
async getNewsDetails(id) {
let res = await this.$get("help/detail", {params: {id: id, client: 2}});
if(res.code == 1) {
this.detailsObj = res.data;
this.recommend_list = res.data.recommend_list
}
},
toOther(id) {
this.$router.push('/help_center/help_center_detail?id=' + id)
}
}
}
</script>
<style lang="scss" scoped>
.news-details-container {
.nav-container {
padding: 15px 16px;
}
.content-box {
display: flex;
flex-direction: row;
.news-detail-box {
background-color: #FFFFFF;
width: 900px;
.content-header {
margin: 0px 20px;
padding: 20px 0px;
border-bottom: 1px solid #e5e5e5;
.news-detail-title {
color: #222;
font-size: 24px;
font-weight: 500;
margin-bottom: 43px;
}
}
.content-html-box {
padding: 24px 20px;
&>div {
width: 100%;
overflow: hidden;
::v-deep img {
width: 100%;
}
}
}
}
.recommend-box {
width: 264px;
.recommend-box-header {
padding: 15px 10px;
border-bottom: 1px solid #e5e5e5;
.primary-line {
margin-right: 10px;
background-color: $--color-primary;
width: 4px;
height: 20px;
}
}
.recommend-box-content {
.recommend-list-container {
.recommend-list-item {
padding: 10px;
cursor: pointer;
.goods-info {
margin-top: 8px;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,233 @@
<template>
<div class="help-center-container">
<div class="help-center-banner">
<client-only>
<swiper ref="mySwiper" :options="swiperOptions">
<swiper-slide class="swiper-item" v-for="(item, index) in bannerList" :key="index">
<ad-item :item="item"></ad-item>
</swiper-slide>
</swiper>
</client-only>
</div>
<div class="help-center-box">
<div class="help-center-aside bg-white">
<ul class="nav flex-col col-center">
<li class="flex" :class="{'active-item': currentId <= 0}" @click="changeList(0)"></li>
<li class="flex" v-for="(item) in categoryList" :key="item.id"
:class="{'active-item': item.id == currentId}" @click="changeList(item.id)">{{item.name}}</li>
</ul>
</div>
<div class="article-lists-container m-l-16 bg-white">
<div v-show="!dataNull">
<div>
<nuxt-link :to="'/help_center/help_center_detail?id=' + item.id"
class="article-item flex row-between bg-white" v-for="(item) in articleList" :key="item.id">
<div>
<div class="lg article-name line2">{{item.title}}</div>
<div class="lighter">{{item.intro}}</div>
<div class="flex" style="margin-top: 56px;">
<div class="sm muted">发布时间{{item.create_time}}</div>
<div class="flex m-l-16">
<i class="el-icon-view muted"></i>
<div class="muted" style="margin-left: 3px;">{{item.visit}} 人浏览</div>
</div>
</div>
</div>
<el-image style="width: 200px; height: 150px;border-radius: 6px;" fit="cover"
:src="item.image" />
</nuxt-link>
</div>
<div class="help-center-pagination row-center">
<el-pagination background hide-on-single-page layout="prev, pager, next" :total="count"
prev-text="上一页" next-text="下一页" :page-size="10" @current-change="changePage" />
</div>
</div>
<div class="data-null column-center" v-show="dataNull">
<img style="width: 150px;height: 150px;" src="~/static/images/news_null.png" />
<div class="xs muted">
暂无消息记录
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
$get,
$post
}) {
let categoryList = [];
let currentId = 0;
let articleList = [];
let count = 0;
let dataNull = true;
const banner = $get("ad_content/lists", {
params: {
pid: 29,
terminal: 2
}
});
let res = await $get("help/category");
const {
data: bannerList
} = await banner;
if (res.code == 1) {
categoryList = res.data;
currentId = 0
let listsRes = await $get("help/lists", {
params: {
cid: currentId,
page_size: 10
}
});
if (listsRes.code == 1) {
articleList = listsRes.data.list;
count = listsRes.data.count
if (count <= 0) {
dataNull = true;
} else {
dataNull = false
}
}
}
return {
categoryList,
articleList,
count,
currentId,
bannerList,
dataNull,
}
},
data() {
return {
categoryList: [],
articleList: [],
currentId: -1,
count: 0,
swiperOptions: {
width: 1180,
}
}
},
mounted() {
console.log(this.articleList, 'articleList')
},
methods: {
async changePage(current) {
let res = await this.$get("help/lists", {
params: {
cid: this.currentId,
page_no: current,
page_size: 10
}
});
if (res.code == 1) {
this.articleList = res.data.list;
if (this.articleList.length <= 0) {
dataNull = true;
} else {
dataNull = false
}
}
},
changeList(id) {
this.currentId = id;
this.changePage(1)
}
}
}
</script>
<style lang="scss" scoped>
.help-center-container {
.help-center-banner {
margin-top: 16px;
}
.help-center-box {
margin-top: 16px;
display: flex;
flex-direction: row;
.help-center-aside {
width: 160px;
// min-height: 635px;
padding-top: 20px;
padding-bottom: 20px;
padding: 20px 30px;
.nav {
li {
margin: 10px 0px;
padding: 0px 30px;
cursor: pointer;
}
.active-item {
padding-left: 27px;
color: $--color-primary;
border-left: 3px solid $--color-primary;
}
}
}
.article-lists-container {
width: 1004px;
display: flex;
flex-direction: column;
justify-content: space-between;
.article-item {
margin: 0px 20px;
padding: 15px 0px;
border-bottom: 1px solid #E5E5E5;
cursor: pointer;
.article-name {
margin-bottom: 11px;
margin-top: 13px;
max-width: 720px;
}
}
.help-center-pagination {
padding-top: 38px;
margin-bottom: 30px;
}
.data-null {
padding-top: 150px;
}
}
}
}
::v-deep .el-pagination.is-background .btn-prev {
background: #fff;
padding: 0 10px;
}
::v-deep .el-pagination.is-background .btn-next {
background: #fff;
padding: 0 10px;
}
::v-deep .el-pagination.is-background .el-pager li {
background: #fff;
padding: 0 10px;
}
</style>

348
pc - 副本/pages/index.vue Normal file
View File

@ -0,0 +1,348 @@
<template>
<div class="index">
<!-- 广告位 -->
<div class="banner">
<client-only>
<el-carousel height="440px" autoplay>
<el-carousel-item
v-for="(item, index) in bannerList"
:key="index"
class="swiper-item"
>
<ad-item :item="item" />
</el-carousel-item>
</el-carousel>
</client-only>
</div>
<!-- 活动专区 -->
<div
class="activity-area flex flex-wrap"
v-if="indexData.activity_area && indexData.activity_area.length"
>
<nuxt-link
class="activity-item flex"
v-for="(item, index) in indexData.activity_area"
:key="index"
:to="`/special_area?id=${item.id}&name=${item.name}&title=${item.title}`"
>
<div class="flex-1 m-r-16" style="min-width: 0">
<div class="xxl m-b-10 line-1">{{ item.name }}</div>
<div class="m-b-6 line-2">{{ item.title }}</div>
<el-button size="mini">前往查看</el-button>
</div>
<el-image
class="activity-img"
lazy
:src="item.image"
alt=""
></el-image>
</nuxt-link>
</div>
<home-seckill :list="indexData.seckill_goods" @refreshhome="getIndex" />
<div class="active-goods flex">
<activity-area
class="flex-1 m-r-16"
:list="indexData.hots"
title="热销榜单"
url="/goods_list/1"
/>
<activity-area
class="flex-1"
:list="indexData.news"
title="新品推荐"
url="/goods_list/2"
/>
</div>
<div
class="shop-recommend card m-t-16"
v-if="indexData.shop_lists.length"
>
<div class="title flex row-between">
<div class="font-size-20">店铺推荐</div>
</div>
<div class="shop-list m-t-16">
<client-only>
<swiper
class="swiper"
ref="mySwiper"
:options="swiperOptions"
>
<swiper-slide
class="swiper-item"
v-for="(item, index) in indexData.shop_lists"
:key="index"
>
<shop-item
:cover="item.cover"
:shopId="item.id"
:logo="item.logo"
:type="item.type"
:name="item.name"
:sales="item.on_sales_count"
/>
</swiper-slide>
<div
class="swiper-button-prev"
slot="button-prev"
></div>
<div
class="swiper-button-next"
slot="button-next"
></div>
</swiper>
</client-only>
</div>
</div>
<div class="goods-column bg-white" v-if="columnList.length">
<div class="column-wrap flex">
<div
class="item flex-col col-center muted flex-none"
v-for="(item, index) in columnList"
:key="index"
@click="changeTab(index)"
>
<div class="item-con flex-col col-center">
<div
class="xxl normal title line-1"
:class="{ 'weight-500': active == index }"
>
{{ item.name }}
</div>
<div
class="m-t-8 xs line-1"
:class="{ normal: active == index }"
>
{{ item.remark }}
</div>
<div v-if="active == index" class="line"></div>
</div>
</div>
</div>
</div>
<div v-if="hasData" class="m-t-16">
<goods-list :list="goodsList" />
<div
class="pagination flex m-t-30 row-center"
style="padding-bottom: 38px"
>
<el-pagination
background
layout="prev, pager, next"
:total="count"
prev-text="上一页"
next-text="下一页"
hide-on-single-page
:page-size="20"
@current-change="changePage"
>
</el-pagination>
</div>
</div>
<null-data
v-else
:img="require('~/static/images/goods_null.png')"
text="暂无商品~"
></null-data>
</div>
</template>
<script>
import HomeSeckill from '../components/home-seckill.vue'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
components: { HomeSeckill },
async asyncData({ $get }) {
const { data } = await $get('index/index',{params: {terminal:'pc'}})
const { data: banner } = await $get('ad_content/lists', {
params: { pid: 23, terminal: 2 },
})
const { data: columnList } = await $get(
'goods_column/getGoodsColumnList'
)
return {
indexData: data,
columnList,
bannerList: banner,
}
},
data() {
return {
page: 1,
count: 0,
goodsList: [],
active: 0,
bannerList: [],
columnList: [],
hasData: true,
indexData: {
activity_area: [],
shop_recommend: [],
hots: [],
news: [],
shop_lists: [],
},
swiperOptions: {
pagination: {
el: '.swiper-pagination',
clickable: true,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// loopedSlides: 5,
preventClicks: true,
slidesPerView: 'auto',
autoplay: false
},
}
},
watch: {
columnList: {
immediate: true,
handler() {
this.getGoodsLists()
},
},
},
methods: {
async getGoodsLists() {
const { columnList, active, page } = this
if (!columnList.length) return
const columnId = columnList[active].id
const { data } = await this.$get('goods/getGoodsListByColumnId', {
params: {
page_size: 10,
page_no: page,
column_id: columnId,
},
})
if (!data.lists.length) {
this.hasData = false
} else {
this.hasData = true
}
this.goodsList = data.lists
},
changePage(page) {
this.page = page
this.getGoodsLists()
},
changeTab(index) {
this.active = index
this.getGoodsLists()
},
async getIndex() {
const { data } = await $get('index/index',{
params: {
terminal: 'pc'
}
})
this.indexData = data
},
},
}
</script>
<style lang="scss">
.index {
.banner {
margin-left: 160px;
margin-bottom: 16px;
height: 440px;
}
.activity-area {
.activity-item {
border-radius: 6px;
padding: 28px 16px;
background-color: #fff;
width: 280px;
margin-bottom: 20px;
&:not(:nth-of-type(4n)) {
margin-right: 20px;
}
.activity-img {
width: 104px;
height: 104px;
}
}
}
.card {
padding: 16px;
border-radius: 6px;
background-color: #fff;
}
.shop-recommend {
padding: 16px 20px;
}
.shop-list {
.swiper {
--swiper-navigation-size: 18px;
--swiper-navigation-color: #fff;
.swiper-button-next,
.swiper-button-prev {
width: 40px;
height: 40px;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 50%;
}
}
.swiper-item {
width: 270px;
height: 400px;
padding-right: 20px;
box-sizing: content-box;
&:last-of-type {
padding-right: 0;
}
}
}
.goods-column {
overflow-y: auto;
.column-wrap {
height: 100px;
.item {
padding: 0 25px;
cursor: pointer;
overflow: hidden;
.item-con {
position: relative;
.title {
position: relative;
z-index: 1;
}
.line {
position: absolute;
top: 16px;
left: 0;
width: 100%;
height: 6px;
background: linear-gradient(
90deg,
#{$--color-primary} 0%,
rgba(255, 44, 60, 0) 100%
);
border-radius: 60px;
}
}
}
}
margin-top: 16px;
}
}
</style>

View File

@ -0,0 +1,233 @@
<template>
<div class="help-center-container">
<div class="help-center-banner">
<client-only>
<swiper ref="mySwiper" :options="swiperOptions">
<swiper-slide class="swiper-item" v-for="(item, index) in bannerList" :key="index">
<ad-item :item="item"></ad-item>
</swiper-slide>
</swiper>
</client-only>
</div>
<div class="help-center-box">
<div class="help-center-aside bg-white">
<ul class="nav flex-col col-center">
<li class="flex" :class="{'active-item': currentId <= 0}" @click="changeList(0)"></li>
<li class="flex" v-for="(item) in categoryList" :key="item.id"
:class="{'active-item': item.id == currentId}" @click="changeList(item.id)">{{item.name}}</li>
</ul>
</div>
<div class="article-lists-container m-l-16 bg-white">
<div v-show="!dataNull">
<div>
<nuxt-link :to="'/news_list/news_list_detail?id=' + item.id"
class="article-item flex row-between bg-white" v-for="(item) in articleList" :key="item.id">
<div>
<div class="lg article-name line2">{{item.title}}</div>
<div class="lighter">{{item.intro}}</div>
<div class="flex" style="margin-top: 56px;">
<div class="sm muted">发布时间{{item.create_time}}</div>
<div class="flex m-l-16">
<i class="el-icon-view muted"></i>
<div class="muted" style="margin-left: 3px;">{{item.visit}} 人浏览</div>
</div>
</div>
</div>
<el-image style="width: 200px; height: 150px;border-radius: 6px;" fit="cover"
:src="item.image" />
</nuxt-link>
</div>
<div class="help-center-pagination row-center">
<el-pagination background hide-on-single-page layout="prev, pager, next" :total="count"
prev-text="上一页" next-text="下一页" :page-size="10" @current-change="changePage" />
</div>
</div>
<div class="data-null column-center" v-show="dataNull">
<img style="width: 150px;height: 150px;" src="~/static/images/news_null.png" />
<div class="xs muted">
暂无消息记录
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
$get,
$post
}) {
let categoryList = [];
let currentId = 0;
let articleList = [];
let count = 0;
let dataNull = true;
const banner = $get("ad_content/lists", {
params: {
pid: 28,
terminal: 2
}
});
let res = await $get("article/category");
const {
data: bannerList
} = await banner;
if (res.code == 1) {
categoryList = res.data;
currentId = 0
let listsRes = await $get("article/lists", {
params: {
cid: currentId,
page_size: 10
}
});
if (listsRes.code == 1) {
articleList = listsRes.data.list;
count = listsRes.data.count
if (count <= 0) {
dataNull = true;
} else {
dataNull = false
}
}
}
return {
categoryList,
articleList,
count,
currentId,
bannerList,
dataNull,
}
},
data() {
return {
categoryList: [],
articleList: [],
currentId: -1,
count: 0,
swiperOptions: {
width: 1180,
}
}
},
mounted() {
console.log(this.articleList, 'articleList')
},
methods: {
async changePage(current) {
let res = await this.$get("article/lists", {
params: {
cid: this.currentId,
page_no: current,
page_size: 10
}
});
if (res.code == 1) {
this.articleList = res.data.list;
if (this.articleList.length <= 0) {
dataNull = true;
} else {
dataNull = false
}
}
},
changeList(id) {
this.currentId = id;
this.changePage(1)
}
}
}
</script>
<style lang="scss" scoped>
.help-center-container {
.help-center-banner {
margin-top: 16px;
}
.help-center-box {
margin-top: 16px;
display: flex;
flex-direction: row;
.help-center-aside {
width: 160px;
// min-height: 635px;
padding-top: 20px;
padding-bottom: 20px;
padding: 20px 30px;
.nav {
li {
margin: 10px 0px;
padding: 0px 30px;
cursor: pointer;
}
.active-item {
padding-left: 27px;
color: $--color-primary;
border-left: 3px solid $--color-primary;
}
}
}
.article-lists-container {
width: 1004px;
display: flex;
flex-direction: column;
justify-content: space-between;
.article-item {
margin: 0px 20px;
padding: 15px 0px;
border-bottom: 1px solid #E5E5E5;
cursor: pointer;
.article-name {
margin-bottom: 11px;
margin-top: 13px;
max-width: 720px;
}
}
.help-center-pagination {
padding-top: 38px;
margin-bottom: 30px;
}
.data-null {
padding-top: 150px;
}
}
}
}
::v-deep .el-pagination.is-background .btn-prev {
background: #fff;
padding: 0 10px;
}
::v-deep .el-pagination.is-background .btn-next {
background: #fff;
padding: 0 10px;
}
::v-deep .el-pagination.is-background .el-pager li {
background: #fff;
padding: 0 10px;
}
</style>

View File

@ -0,0 +1,189 @@
<template>
<div class="news-details-container mt16">
<div class="nav-container flex">
<div class="nr" style="width: 70px">当前位置</div>
<el-breadcrumb style="flex: 1;" separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>
<nuxt-link to="/news_list">商城资讯</nuxt-link>
</el-breadcrumb-item>
<el-breadcrumb-item class="line1" style="max-width: 800px;">{{detailsObj.title}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="content-box">
<div class="news-detail-box m-r-16">
<div class="content-header bg-white">
<div class="news-detail-title">
{{detailsObj.title}}
</div>
<div class="flex">
<div class="sm muted">
发布时间{{detailsObj.create_time}}
</div>
<div class="flex" style="margin-left: 40px">
<i class="el-icon-view muted"></i>
<div class="muted" style="margin-left: 3px;">{{detailsObj.visit}} 人浏览</div>
</div>
</div>
</div>
<div class="content-html-box bg-white">
<div v-html="detailsObj.content"></div>
</div>
</div>
<div class="recommend-box">
<div class="recommend-box-header flex bg-white">
<div class="primary-line"></div>
<div class="xxl" style="font-weight: 500">为您推荐</div>
</div>
<div class="recommend-box-content bg-white">
<div class="recommend-list-container">
<div class="recommend-list-item" v-for="(item) in recommend_list" :key="item.id"
@click="toOther(item.id)">
<el-image style="width: 244px; height:183px;border-radius: 6px" fit="cover"
:src="item.image" />
<div class="goods-info">
<div class="line2 goods-name">{{item.title}}</div>
<div class="flex" style="margin-top: 10px">
<i class="el-icon-view muted"></i>
<div class="muted xs" style="margin-left: 4px;">{{item.visit}} 人浏览</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon
}],
};
},
async asyncData({
$get,
$post,
query
}) {
let detailsObj = {};
let recommend_list = [];
let res = await $get("pc/articleDetail", {
params: {
id: query.id,
client: 2
}
});
if (res.code == 1) {
detailsObj = res.data;
recommend_list = res.data.recommend_list
}
return {
detailsObj,
recommend_list,
};
},
watchQuery: ['id'],
data() {
return {
recommend_list: []
}
},
mounted() {
console.log('route', this.$route)
// this.getNewsDetails(this.$route.query.id);
},
methods: {
// async getNewsDetails(id) {
// let res = await this.$get("article/detail", {params: {id: id, client: 2}});
// if(res.code == 1) {
// this.detailsObj = res.data;
// this.recommend_list = res.data.recommend_list
// }
// },
toOther(id) {
this.$router.push('/news_list/news_list_detail?id=' + id)
}
}
}
</script>
<style lang="scss" scoped>
.news-details-container {
.nav-container {
padding: 15px 16px;
}
.content-box {
display: flex;
flex-direction: row;
.news-detail-box {
background-color: #FFFFFF;
width: 900px;
.content-header {
margin: 0px 20px;
padding: 20px 0px;
border-bottom: 1px solid #e5e5e5;
.news-detail-title {
color: #222;
font-size: 24px;
font-weight: 500;
margin-bottom: 43px;
}
}
.content-html-box {
padding: 24px 20px;
&>div {
width: 100%;
overflow: hidden;
::v-deep img {
width: 100%;
}
}
}
}
.recommend-box {
width: 264px;
.recommend-box-header {
padding: 15px 10px;
border-bottom: 1px solid #e5e5e5;
.primary-line {
margin-right: 10px;
background-color: $--color-primary;
width: 4px;
height: 20px;
}
}
.recommend-box-content {
.recommend-list-container {
.recommend-list-item {
padding: 10px;
cursor: pointer;
.goods-info {
margin-top: 8px;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,303 @@
<template>
<div class="payment bg-white">
<div class="payment-hd flex">
<template v-if="order.pay_status == 0">
<img src="~/static/images/pay_wait.png" alt="" />
<div class="status m-l-8 m-r-16 weight-500">
{{ getOrderStatus(order.order_status) }}
</div>
<div
v-if="getCancelTime(order.cancel_time) > 0"
class="flex"
>
请在
<count-down
:time="getCancelTime(order.cancel_time)"
format="hh时mm分ss秒"
:style="{ color: '#FF2C3C' }"
@finish="getOrder"
/>
完成支付, 超时后将取消订单
</div>
</template>
<template v-if="order.pay_status == 1">
<img src="~/static/images/pay_success.png" alt="" />
<div class="status m-l-8 m-r-16 weight-500">支付成功</div>
</template>
</div>
<div class="payment-con">
<div class="item flex m-b-16">订单编号{{ order.order_sn }}</div>
<div class="item flex m-b-16">
订单价格<span class="primary"
>{{ order.total_amount }}</span
>
</div>
<div class="item flex m-b-16">
收货地址
<div>
{{ address.contact }} {{ address.mobile }}
<span class="m-l-16">{{ address.delivery_address }}</span>
</div>
</div>
<div class="item flex m-b-16">
商品名称
<div>
<div
v-for="(item, index) in order.order_goods"
:key="index"
>
<div class="flex lin-1">
商品{{index + 1}}- {{ item.goods_name }}
</div>
</div>
</div>
</div>
</div>
<div class="payment-footer">
<template v-if="order.pay_status == 0 && order.order_status == 0">
<div class="title lg weight-500">请选择支付方式</div>
<div class="flex m-t-16">
<div
class="pay-way flex row-center"
v-for="(item, index) in payWayArr"
:key="index"
@click="orderPay(item.pay_way)"
>
<img :src="item.image" alt="" />
<div class="m-l-16">
<span class="md">{{ item.name }}</span>
<div class="muted m-t-2 sm">{{item.extra}}</div>
</div>
</div>
</div>
</template>
<nuxt-link v-else class="btn flex row-center" to="/user/order"
>查看订单</nuxt-link
>
</div>
<el-dialog
title="微信支付"
:visible.sync="showWxpay"
width="700px"
center
@close="clearTimer"
>
<div class="flex-col col-center black">
<img class="pay-code" :src="payInfo" alt="" />
<div class="m-t-8" style="font-size: 18px">
微信扫一扫完成支付
</div>
<div class="pay-money flex">
<span>需支付金额</span>
<span class="primary">
<price-formate
:price="order.total_amount"
:subscript-size="18"
:first-size="28"
:second-size="28"
/>
</span>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { client } from '@/utils/type'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
async asyncData({ query, $get }) {
const { data } = await $get('order/getPayStatus', {
params: {
id: query.id,
from: query.from
},
})
return { order: data, address: data.address }
},
data() {
return {
showWxpay: false,
showAlipay: false,
payWayArr: [],
payInfo: {},
cancelTime: 0,
alipayHtml: '',
address: {}
}
},
created() {
this.id = this.$route.query.id
this.from = this.$route.query.from
this.getPayway()
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
async getPayway() {
const { code, data } = await this.$get('order/getPayWay', {
params: { from: 'order', order_id: this.id },
})
if (code == 1) {
this.payWayArr = data.pay_way
if (!this.payWayArr.length)
this.$message({
message: '请联系管理员配置支付方式',
type: 'error',
})
}
},
async orderPay(payWay) {
const { data, code, msg } = await this.$post('pay/unifiedpay', {
order_id: this.id,
pay_way: payWay,
from: this.from,
})
if (code == 1) {
this.payInfo = data
this.showWxpay = true
this.createTimer()
} else if (code == 10001) {
let divForm = document.getElementsByTagName('divform')
if (divForm.length) {
document.body.removeChild(divForm[0])
}
const div = document.createElement('divform')
div.innerHTML = data // dataform
document.body.appendChild(div)
document.forms[0].submit()
} else if (code == 20001) {
this.$message({
message: msg,
type: 'success',
})
this.getOrder()
}
},
clearTimer() {
clearInterval(this.timer)
},
createTimer() {
if (this.timer) clearInterval(this.timer)
this.timer = setInterval(() => {
this.getOrder()
}, 2000)
},
async getOrder() {
const { data, code, msg } = await this.$get('order/getPayStatus', {
params: {
id: this.id,
from: this.from,
},
})
if (code == 1) {
this.order = data
if (data.pay_status == 1) {
clearInterval(this.timer)
this.showWxpay = false
}
}
},
},
computed: {
getOrderStatus() {
return (status) => {
let text = ''
switch (status) {
case 0:
text = '待支付'
break
case 1:
text = '待发货'
break
case 2:
text = '待收货'
break
case 3:
text = '已完成'
break
case 4:
text = '订单已关闭'
break
}
return text
}
},
getCancelTime() {
return (time) => time - Date.now() / 1000
},
},
}
</script>
<style lang="scss" scoped>
.payment {
margin: 16px 0;
padding: 0 40px;
.payment-hd {
> img {
width: 32px;
height: 32px;
}
.status {
font-size: 24px;
}
}
.payment-con,
.payment-hd {
padding: 32px 0;
border-bottom: 1px dashed $--border-color-base;
}
.payment-con {
.item {
align-items: flex-start;
}
}
.payment-footer {
padding: 32px 0;
.pay-way {
min-width: 200px;
padding: 0 20px;
height: 68px;
cursor: pointer;
margin-right: 32px;
border: 1px dashed $--border-color-base;
img {
width: 30px;
height: 30px;
}
}
.btn {
width: 134px;
height: 40px;
border: 1px solid $--border-color-base;
}
}
.el-dialog {
.pay-code {
width: 270px;
height: 270px;
}
.pay-money {
font-size: 18px;
margin-top: 24px;
align-items: baseline;
}
}
}
</style>

View File

@ -0,0 +1,326 @@
<template>
<div class="category">
<div class="category-hd bg-white">
<div class="category-wrap">
<div class="category-con flex">
<div class="name muted">全部分类</div>
<div class="category-list flex flex-wrap lighter">
<div
:class="[
'item line1',
{ active: threeIndex === index },
]"
v-for="(item, index) in categoryThree"
:key="index"
@click="changeData(item.id,index)"
>
{{ item.name }}
</div>
</div>
</div>
</div>
<div class="sort flex bg-white">
<div class="title muted">排序方式</div>
<div class="sort-name m-l-16 flex lighter">
<div
:class="['item', { active: sortType == '' }]"
@click="changeSortType('')"
>
综合
</div>
<div
:class="['item', { active: sortType == 'price' }]"
@click="changeSortType('price')"
>
价格
<i
v-show="priceSort == 'desc'"
class="el-icon-arrow-down"
></i>
<i
v-show="priceSort == 'asc'"
class="el-icon-arrow-up"
></i>
</div>
<div
:class="['item', { active: sortType == 'sales_sum' }]"
@click="changeSortType('sales_sum')"
>
销量
<i
v-show="saleSort == 'desc'"
class="el-icon-arrow-down"
></i>
<i
v-show="saleSort == 'asc'"
class="el-icon-arrow-up"
></i>
</div>
<div
:class="['item', { active: sortType == 'brand' && brandList.length}]"
@click="changeSortType('brand')"
>
品牌
</div>
</div>
</div>
<!-- 品牌 -->
<div class="sort flex bg-white" v-show="sortType == 'brand' && brandList.length > 0">
<div class="category-con flex" style="padding-top: 0;">
<div class="name muted">品牌</div>
<div class="category-list flex flex-wrap lighter">
<div
:class="['item', { active: brandIndex == index }]"
@click="getBrandGoods(index)" v-for="(item,index) in brandList" :key="index"
>
{{ item.name }}
</div>
</div>
</div>
</div>
</div>
<div v-if="isHasGoods" class="goods-list">
<goods-list :list="goodsList" />
<div
class="pagination flex row-center"
style="padding-bottom: 38px"
v-if="count"
>
<el-pagination
background
hide-on-single-page
layout="prev, pager, next"
:total="count"
prev-text="上一页"
next-text="下一页"
:page-size="20"
@current-change="changePage"
>
</el-pagination>
</div>
</div>
<null-data
v-else
:img="require('@/static/images/goods_null.png')"
text="暂无商品~"
></null-data>
</div>
</template>
<script>
import { trottle } from '~/utils/tools'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
watchQuery: true,
async asyncData({ query, $get }) {
let { data } = await $get('goodsCategory/getThirdListByKeyword',{
params: {
keyword:query.name,
},
})
return {
categoryList: data,
}
},
data() {
return {
count: 0,
threeIndex: 0,
brandIndex:-1,
categoryThree: [],
sortType: '',
saleSort: 'desc',
priceSort: 'desc',
brandSort:'desc',
page: '',
goodsList: [],
cateId: 0,
isHasGoods: true,
brandList:[],//
}
},
created() {
this.changeSortType = trottle(this.changeSortType, 500, this)
},
methods: {
changeData(id,index) {
const { categoryList } = this
this.categoryThree = categoryList;
this.threeIndex = index || 0;
this.cateId = id || categoryList[this.threeIndex].id;
this.getGoods();
this.brandIndex = '-1';
this.sortType = '';
this.brandList = [];
},
changeSortType(type) {
this.sortType = type
switch (type) {
case 'price':
if (this.priceSort == 'asc') {
this.priceSort = 'desc'
} else if (this.priceSort == 'desc') {
this.priceSort = 'asc'
}
break
case 'sales_sum':
if (this.saleSort == 'asc') {
this.saleSort = 'desc'
} else if (this.saleSort == 'desc') {
this.saleSort = 'asc'
}
break
case 'brand':
if (this.brandSort == 'asc') {
this.brandSort = 'desc'
} else if (this.brandSort == 'desc') {
this.brandSort = 'asc'
}
break
default:
}
if(this.sortType == 'brand') {
this.getBrand() //
}else {
this.getGoods()
}
},
changePage(current) {
this.page = current
this.getGoods()
},
async getGoods() {
const { priceSort, sortType, saleSort } = this
const params = {
page_size: 20,
page_no: this.page,
platform_cate_id: this.cateId,
}
switch (sortType) {
case 'price':
params.sort_by_price = priceSort
break
case 'sales_sum':
params.sort_by_sales = saleSort
break
}
if(this.brandIndex >= 0) {
params.brand_id = this.brandList[this.brandIndex].brand_id;
}
const {
data: { lists, count },
} = await this.$get('goods/getGoodsList', {
params,
})
this.goodsList = lists
if (!lists.length) {
this.isHasGoods = false
} else {
this.isHasGoods = true
}
this.count = count
},
//
async getBrand() {
const params = {
page_size: 20,
page_no: this.page,
cate_id: this.cateId,
}
const {
data
} = await this.$get('goods/getBrandListByCateId', {
params,
})
this.brandList = data
},
//
getBrandGoods(index) {
this.brandIndex = index;
this.getGoods();
},
},
watch: {
categoryList: {
immediate: true,
handler(value) {
const { id } = this.$route.query
this.changeData(Number(id));
},
},
},
}
</script>
<style lang="scss" scoped>
.category {
padding: 16px 0;
.category-hd {
.category-wrap {
padding: 0 16px;
}
.category-con {
border-bottom: 1px dashed #e5e5e5;
align-items: flex-start;
padding-top: 16px;
word-wrap: break-word;
.name {
flex: none;
}
.item {
margin-bottom: 16px;
width: 140px;
margin-left: 14px;
cursor: pointer;
&.active {
color: $--color-primary;
}
&:hover {
color: $--color-primary;
}
}
}
.sort {
padding: 15px 16px;
.sort-name {
.item {
margin-right: 30px;
cursor: pointer;
&.active {
color: $--color-primary;
}
}
}
}
}
.brand-list {
border-top: 1px dashed #e5e5e5;
}
}
.goods-list {
margin-top: 20px;
}
</style>

View File

@ -0,0 +1,195 @@
<template>
<div class="seckill">
<div class="banner mt16 column">
<ad-item :item="ad" v-if="ad.image"></ad-item>
<el-image v-else :src="require('~/static/images/seckill_banner.png')"></el-image>
</div>
<div class="time-list">
<client-only>
<swiper class="swiper" ref="mySwiper" :options="swiperOptions">
<swiper-slide :class="{ 'swiper-item': true, active: index === swiperIndex }"
v-for="(item, index) in timeList" :key="index">
<div class=" white" style="width: 100%; height: 100%" @click="changeTime(index)">
<div class="weight-500 xxl flex row-center">{{ item.start_time }}</div>
<div class="xs time-status flex row-center">{{ item.tips }}</div>
</div>
</swiper-slide>
<div class="swiper-button-prev" slot="button-prev"></div>
<div class="swiper-button-next" slot="button-next"></div>
</swiper>
</client-only>
</div>
<div class="goods m-t-16">
<template v-if="hasData">
<goods-list type="seckill" :list="goodsList" :status="status" />
<div class="pagination row-center" style="padding-bottom: 38px" v-if="count">
<el-pagination background layout="prev, pager, next" :total="count" prev-text="" next-text=""
hide-on-single-page :page-size="10" @current-change="changePage">
</el-pagination>
</div>
</template>
<null-data v-else :img="require('~/static/images/goods_null.png')" text="暂无秒杀~"></null-data>
</div>
</div>
</template>
<script>
import goodsList from "../components/goods-list.vue"
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
components: {
goodsList
},
watchQuery: true,
async asyncData({ $get }) {
let ad = {}
const banner = await $get("ad_content/lists",{params: {
pid: 24,
terminal: 2
}});
if(banner.data.length) {
ad = {
image: banner.data[0].image
}
}
const { data } = await $get("seckill_goods/getSeckillTime");
console.log(data)
let swiperIndex = data.findIndex((item) => item.status == 1);
if (swiperIndex == -1) {
swiperIndex = data.findIndex((item) => item.status == 2);
}
return { timeList: data, swiperIndex, ad };
},
data() {
return {
ad: {
image: 0
},
page: 1,
swiperIndex: 0,
count: 0,
goodsList: [],
timeList: [],
hasData: true,
swiperOptions: {
initialSlide: 0,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
preventClicks: true,
slidesPerView: "auto",
},
};
},
created() {
this.swiperOptions.initialSlide = this.swiperIndex;
this.getGoods();
},
methods: {
changeTime(index) {
this.swiperIndex = index;
this.getGoods();
this.page = 1;
this.goodsList = [];
},
changePage(current) {
this.page = current;
this.getGoods();
},
async getGoods() {
const { swiperIndex, timeList, page } = this;
const id = timeList[swiperIndex] ? timeList[swiperIndex].id : -1;
const {
data: { lists, count },
code,
} = await this.$get("seckill_goods/getSeckillGoods", {
params: {
page_size: 10,
page_no: page,
seckill_id: id,
},
});
if (code == 1) {
this.goodsList = lists;
this.hasData = !!lists.length;
this.count = count;
}
},
},
computed: {
status() {
const { swiperIndex, timeList } = this;
return timeList[swiperIndex] ? timeList[swiperIndex].status : -1;
},
},
};
</script>
<style lang="scss" scoped>
.seckill {
.banner {
img {
width: 100%;
display: block;
}
}
.time-list {
background-color: #414141;
.swiper {
padding: 0 40px;
--swiper-navigation-size: 20px;
--swiper-navigation-color: #fff;
.swiper-button-next,
.swiper-button-prev {
top: 0;
width: 25px;
height: 100%;
margin-top: 0;
background-size: 12px 22px;
}
.swiper-button-prev {
left: 0;
}
.swiper-button-next {
right: 0;
}
.swiper-item {
cursor: pointer;
height: 60px;
width: 120px;
padding: 10px 0;
display: inline-block;
&.active {
color: #fff;
background-color: $--color-primary;
.time-status {
color: #fff;
}
}
.time-status {
color: #ccc;
border-radius: 60px;
padding: 1px 8px;
}
}
}
}
}
</style>

View File

@ -0,0 +1,479 @@
<template>
<div class="shop-cart">
<div class="cart-list">
<div v-show="!isDataNull">
<div class="cart-hd flex bg-white">
<div class="check-box">
<!-- 更改选中状态 type为1选中店铺/2选中商品/3全选 -->
<el-checkbox
v-model="isSelectedAll"
@change="onBoxClick($event, 3, '')"
>全选</el-checkbox
>
</div>
<div class="info flex row-center">商品信息</div>
<div class="price flex row-center">单价</div>
<div class="num flex row-center">数量</div>
<div class="money flex row-center">合计</div>
<div class="operate flex row-center">操作</div>
</div>
<div class="cart-con bg-white">
<div
class="m-b-10 bg-white"
v-for="(item, index) in shopCartList"
:key="index"
>
<div class="flex shop">
<!-- 更改选中状态 type为1选中店铺/2选中商品/3全选 -->
<el-checkbox
:value="item.is_selected == 1"
@change="onBoxClick($event, 1, index)"
>
</el-checkbox>
<div class="xs normal m-l-10">
{{ item.shop.shop_name }}
</div>
</div>
<div
class="item flex"
v-for="(item2, index2) in item.cart"
:key="index2"
>
<div class="check-box">
<!-- 更改选中状态 type为1选中店铺/2选中商品/3全选 -->
<el-checkbox
:value="item2.selected == 1"
@change="
onBoxClick($event, 2, item2.cart_id)
"
>
</el-checkbox>
</div>
<nuxt-link
class="info flex"
:to="'/goods_details/' + item2.goods_id"
>
<div class="pictrue flexnone">
<img :src="item2.image" alt="" />
</div>
<div>
<div class="name line2">
{{ item2.goods_name }}
</div>
<div class="muted">
{{ item2.spec_value_str }}
</div>
</div>
</nuxt-link>
<div class="price flex row-center">
¥{{ item2.price }}
</div>
<div class="num flex row-center">
<number-box
:min="1"
v-model="item2.goods_num"
@change="
changeShopCartCount(
$event,
item2.cart_id
)
"
async-change
/>
</div>
<div class="money flex row-center">
¥{{ item2.sub_price }}
</div>
<el-popconfirm
title="确定删除该商品吗?"
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
@confirm="goodsDelete(item2.cart_id)"
>
<div
class="operate flex row-center delete-btn"
slot="reference"
>
<img
src="~/static/images/icon_cart_del.png"
/>
</div>
</el-popconfirm>
</div>
</div>
</div>
<div class="cart-footer flex row-between bg-white">
<div class="lighter flex">
<div class="check-box">
<el-checkbox
v-model="isSelectedAll"
@change="onBoxClick($event, 3, '')"
>全选</el-checkbox
>
</div>
<div style="margin: 0 24px"></div>
<el-popconfirm
title="确定删除选中商品吗?"
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
@confirm="deleteSelectedGoods"
>
<div
class="xs normal"
style="cursor: pointer"
slot="reference"
>
删除选中商品
</div>
</el-popconfirm>
<el-popconfirm
title="确定清空吗?"
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
@confirm="deleteAlldGoods"
>
<div
class="m-l-14 xs muted"
style="cursor: pointer"
slot="reference"
>
清空购物车
</div>
</el-popconfirm>
</div>
<div class="total flex">
<div class="flex m-r-14">
<div class="xs">已选{{ selected }}件商品</div>
<div class="primary m-l-20" style="font-size: 22px">
¥{{ totalAmount }}
</div>
</div>
<div
class="white lg btn flex row-center"
:style="{
background:
selected == 0 ? '#A4ADB3' : '#FF2C3C',
}"
@click="toOrderBuy"
>
去结算
</div>
</div>
</div>
</div>
<div class="column-center data-null" v-show="isDataNull">
<img
src="@/static/images/cart_null.png"
style="width: 150px; height: 150px"
/>
<div class="muted xs m-t-10">购物车是空的</div>
<div class="m-t-30">
<el-button
round
type="primary"
size="medium"
@click="toIndex"
>去逛逛</el-button
>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
data() {
return {
shopCartList: [],
totalAmount: 0,
totalNum: 0,
isDataNull: false,
}
},
mounted() {},
computed: {
//
isSelectedAll: {
get() {
if (!this.shopCartList.length) return false
if (this.allInvalid()) return false
let index = this.shopCartList.findIndex(
(item) => item.is_selected == 0
)
return index == -1 ? true : false
},
set(val) {
return val
},
},
//
selected: {
get() {
return this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.filter((i) => i.selected == 1))
}, []).length
},
},
},
methods: {
...mapActions(['getPublicData']),
async getCartList() {
let res = await this.$get('cart/lists')
if (res.code == 1) {
this.shopCartList = Object.assign([], res.data.lists)
this.totalAmount = res.data.total_amount
this.totalNum = res.data.total_num
if (this.shopCartList.length > 0) {
this.isDataNull = false
} else {
this.isDataNull = true
}
}
},
// type1/2/3
onBoxClick(e, type, number) {
let cartId = []
switch (type) {
case 1:
cartId = this.shopCartList[number].cart.map(
(item) => item.cart_id
)
break
case 2:
cartId.push(number)
break
case 3:
cartId = this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.map((i) => i.cart_id))
}, cartId)
break
}
this.changeSelected(cartId, e)
},
cartInvalid(item) {
return item.goods_status == 0 || item.goods_del != 0 ? true : false
},
shopInvalid(item) {
return item.cart.every((citem) => this.cartInvalid(citem))
},
allInvalid() {
return this.shopCartList.every((item) => this.shopInvalid(item))
},
// /
async changeSelected(id, selected) {
let res = await this.$post('cart/selected', {
cart_id: id,
selected: selected,
})
if (res.code == 1) {
this.getCartList()
}
},
//
async changeShopCartCount(number, cartId) {
let res = await this.$post('cart/change', {
cart_id: cartId,
goods_num: number,
})
if (res.code == 1) {
this.getCartList()
this.getPublicData()
}
},
//
async goodsDelete(cartId) {
let res = await this.$post('cart/del', {
cart_id: cartId,
})
if (res.code == 1) {
this.getPublicData()
this.getCartList()
this.$message({
message: '删除商品成功',
type: 'success',
})
}
},
//
deleteSelectedGoods() {
let selectedGoodsArr = this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.filter((i) => i.selected == 1))
}, [])
if (selectedGoodsArr.length <= 0) {
this.$message({
message: '没有选择商品',
type: 'error',
})
return
}
let cartIdArr = selectedGoodsArr.map((item) => item.cart_id)
this.goodsDelete(cartIdArr)
},
//
deleteAlldGoods() {
let allGoodsArr = this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.filter((i) => i.cart_id))
}, [])
if (allGoodsArr.length <= 0) {
this.$message({
message: '没有商品',
type: 'error',
})
return
}
let cartIdArr = allGoodsArr.map((item) => item.cart_id)
this.goodsDelete(cartIdArr)
},
getSelectCart() {
const { shopCartList } = this
return shopCartList.reduce((pre, item) => {
return pre.concat(
item.cart
.filter((i) => i.selected && !this.cartInvalid(i))
.map((i) => i.cart_id)
)
}, [])
},
//
toOrderBuy() {
let { shopCartList } = this
let goods = []
let carts = this.getSelectCart()
if (carts.length == 0) return this.$message.err('您还没有选择商品哦')
//
shopCartList.forEach((item) => {
if (item.cart.length != 0) {
item.cart.forEach((el, i) => {
//
if (el.selected == 1) {
goods.push({
item_id: el.item_id,
num: el.goods_num,
goods_id: el.goods_id,
shop_id: item.shop.shop_id,
})
}
})
}
})
const params = {
carts: carts,
goods: goods,
type: 'cart',
}
this.$router.push({
path: '/confirm_order',
query: {
data: encodeURIComponent(JSON.stringify(params)),
},
})
},
toIndex() {
this.$router.push('/')
},
},
created() {
this.getCartList()
},
}
</script>
<style lang="scss" scoped>
.shop-cart {
padding: 24px 0;
.cart-list {
min-height: 600px;
.cart-hd {
height: 50px;
color: #101010;
padding: 10px 10px;
margin-bottom: 10px;
}
.cart-con {
padding: 0 10px;
.shop {
padding: 20px 10px;
border-bottom: 1px solid #d7d7d7;
}
.item {
padding: 20px 10px;
border-bottom: 1px dashed #e5e5e5;
}
.item:last-child {
border-bottom: 0;
}
}
.check-box {
padding-left: 10px;
width: 40px;
}
.info {
width: 450px;
.pictrue {
margin-right: 10px;
img {
width: 72px;
height: 72px;
}
}
.name {
margin-bottom: 10px;
}
}
.price {
width: 150px;
}
.num {
width: 250px;
}
.money {
width: 150px;
}
.delete-btn {
cursor: pointer;
}
}
.cart-footer {
padding: 20px;
.total {
.btn {
width: 152px;
height: 50px;
cursor: pointer;
border-radius: 4px;
}
}
}
.data-null {
text-align: center;
padding-top: 170px;
}
}
</style>

View File

@ -0,0 +1,160 @@
<!-- 店铺街 -->
<template>
<div class="street">
<!-- 店铺卡片 -->
<div class="shop-street flex flex-wrap flex-center">
<div v-for="(item, index) in shopList" :key="index">
<!-- 店铺卡片 -->
<div class="shop-cart">
<shop-item
:cover="item.cover"
:shopId="item.id"
:logo="item.logo"
:type="item.type"
:name="item.name"
:sales="item.on_sale_goods"
/>
</div>
</div>
</div>
<!-- 分页栏 -->
<div
class=""
style="padding-bottom: 38px; text-align: center"
v-if="count"
>
<el-pagination
background
layout="prev, pager, next"
:total="count"
prev-text="上一页"
next-text="下一页"
hide-on-single-page
:page-size="pageSize"
@current-change="changePage"
>
</el-pagination>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
async asyncData({ query, $get }) {
const {
data: { list, count },
} = await $get('shop/getShopList', {
params: {
page_size: 8,
page_no: 1,
},
})
return {
shopList: list,
count: count,
}
},
data() {
return {
shopList: [],
count: 0,
page: 1,
pageSize: 8,
}
},
methods: {
changePage(current) {
this.page = current
this.getShopList()
},
async getShopList() {
const { page, pageSize } = this
const {
data: { list, count },
code,
} = await this.$get('shop/getShopList', {
params: {
page_size: pageSize,
page_no: page,
},
})
if (code == 1) {
this.shopList = list
this.count = count
}
},
},
}
</script>
<style lang="scss" scoped>
.shop-street {
width: 1180px;
padding: 20px 0;
.shop-cart {
width: 270px;
height: 400px;
// background-color: lightcoral;
margin-bottom: 20px;
&:not(:nth-of-type(4n)) {
margin-right: 20px;
}
.shop-desc {
width: 249px;
height: 124px;
background-color: #ffffff;
margin-top: 247px;
margin-bottom: 9px;
border-radius: 6px;
position: relative;
.shop-logo {
position: absolute;
top: -26px;
left: 89px;
z-index: 10;
}
.shop-name {
margin-top: 52px;
padding: 0 10px;
margin-bottom: 4px;
text-align: center;
font-size: 16px;
color: #101010;
}
.goods-num {
width: 82px;
height: 24px;
text-align: center;
background: #e5e5e5;
padding-top: 4px;
margin-bottom: 20px;
font-size: 12px;
border-radius: 4px;
color: #999999;
}
}
}
}
</style>

View File

@ -0,0 +1,780 @@
<template>
<div class="">
<!-- 顶部 -->
<div class="bg-white">
<div class="flex flex-1 row-center col-center" style="width: 100%; height: 150px;" v-if="shopInfo.banner">
<el-image :src="shopInfo.banner" fit="cover" style="height: 100%; width: 100%; max-width: 1920px;">
</el-image>
</div>
<div class="wrapper1180 flex flex-1 col-center row-between" style="height: 40px">
<div class="h-item flex row-center" :class="xuanIndex =='' ? 'h-item-x':''" @click="changeXuan('')">
店铺首页
</div>
<div class="flex row-left flex-1">
<div class="h-item flex row-center" :class="xuanIndex =='all' ? 'h-item-x':''"
@click="changeXuan('all')">
全部商品
</div>
<!-- <div class="" v-for="(item, index) in goodsClassList" :key="index">
<div class="h-item flex row-center" :class="xuanIndex == item.id ? 'h-item-x':''"
@click="changeXuan(item.id)">
{{item.name}}
</div>
</div> -->
<!-- 商品分类 -->
<swiper class="swiper flex row-left" ref="mySwiper" :options="swiperOptions"
style="width: 672px; display: flex; justify-content: flex-start;margin: 0;">
<swiper-slide class="swiper-item flex row-left" v-for="(itemd, indexd) in goodsClassListGroup"
:key="indexd">
<div class="flex">
<div class="" v-for="(item, index) in itemd" :key="index">
<div class="h-item flex row-center" :class="xuanIndex == item.id ? 'h-item-x':''"
@click="changeXuan(item.id)">
{{item.name}}
</div>
</div>
</div>
</swiper-slide>
</swiper>
</div>
<div class="search">
<el-input v-model="keyword" placeholder="店铺搜索" @change="search" size="mini"></el-input>
</div>
</div>
</div>
<div class="shop-details flex col-top wrapper1180 flex-1">
<!-- left -->
<div class="left">
<!-- 店铺介绍 -->
<div class="shop bg-white">
<div class="shop-logo flex-col col-center">
<el-image class="logo-img" :src="shopInfo.logo"></el-image>
<div class="m-t-10">
<el-tag size="mini" v-if="shopInfo.type == 1"></el-tag>
<span class="weight-500">{{ shopInfo.name }}</span>
</div>
<div class="xs muted m-t-10 line-5">
{{shopInfo.intro}}
</div>
</div>
<div class="flex m-t-30">
<div class="flex-1 text-center">
<div class="xxl m-b-10">{{ shopInfo.on_sale_count }}</div>
<div>全部商品</div>
</div>
<div class="flex-1 text-center">
<div class="xxl m-b-10">{{ shopInfo.follow_num }}</div>
<div>关注人数</div>
</div>
</div>
<el-divider></el-divider>
<div class="flex xs m-b-16">
<div class="m-r-12">店铺星级</div>
<div class="m-t-5">
<el-rate v-model="shopInfo.star" disabled> </el-rate>
</div>
</div>
<div class="flex xs m-b-16">
<div class="m-r-12">店铺评分</div>
<div class="">{{ shopInfo.score }}</div>
</div>
<div class="flex row-center row-between">
<div class="flex row-center">
<el-button size="mini" @click="shopFollow">{{
shopInfo.shop_follow_status == 1 ? '已关注' : '关注店铺'
}}</el-button>
</div>
<el-popover placement="bottom" width="200" trigger="hover">
<div>
<el-image style="width: 100%" :src="shopInfo.customer_image"></el-image>
</div>
<div slot="reference" class="xs lighter text-center">
<i class="el-icon-chat-dot-round nr"></i>
<span>联系客服</span>
</div>
</el-popover>
</div>
</div>
<!-- 商品分类 -->
<div class="m-t-10 bg-white">
<div class="l-fen flex row-center" @click="getClassGoods('')"
:class="gClassId == ''?'l-fen-select':''">
全部商品
</div>
<div class="" v-for="(item, index) in goodsClassList" :key="index" @click="getClassGoods(item.id)">
<div class="l-fen flex row-center" v-show="index < 4"
:class="gClassId == item.id?'l-fen-select':''">
{{item.name}}
</div>
</div>
</div>
</div>
<!-- right -->
<div class="right m-l-15">
<!-- 领券 -->
<div class="bg-white" v-if="couponsList.length && xuanIndex == ''">
<div class="coupon-list">
<div class="m-b-10 flex row-between">
<div class="">
领券
</div>
<div class="flex row-center coupons-more" @click="more=!more" v-if="couponsList.length > 3">
<div class="m-r-5">
更多
</div>
<i :class="more?'el-icon-arrow-up':'el-icon-arrow-down'"></i>
</div>
</div>
<div class="flex" :class="more? 'swiper-item-zk':'swiper-item-c'">
<div class="item" v-for="(item, index) in couponsList" :key="index">
<div :class="[
'info white',
{ gray: item.is_get },
]">
<div class="info-hd flex">
<div>
<price-formate :price="item.money" :first-size="38" :second-size="38" />
</div>
<div class="m-l-8 flex1">
<div class="line1">{{ item.name }}</div>
<div class="xs line1">{{ item.condition_type_desc }}
</div>
</div>
</div>
<div class="info-time xs">{{ item.user_time_desc }}</div>
</div>
<div class="flex row-between coupon-button">
<div class="tips-con xs lighter">
{{ item.use_scene_desc }}
</div>
<div class="primary sm" @click="hqCoupon(item.id)" v-if="!item.is_get">
立即领取
</div>
</div>
<img v-if="item.is_get" class="receice" src="~/static/images/coupons_img_receive.png"
alt="" />
</div>
</div>
</div>
</div>
<!-- 店铺推荐 -->
<div class="shop-list" v-if="recommend && xuanIndex == ''">
<div class="m-b-10">
店铺推荐
</div>
<el-carousel arrow="never" indicator-position="outside" trigger="click" height="300px"
:autoplay="false">
<el-carousel-item v-for="(itemd, indexd) in recommend" :key="indexd">
<div class="flex">
<div class="shop-item" v-for="(itemg, indexg) in itemd" :key="indexg">
<nuxt-link :to="`/goods_details/${itemg.id}`">
<div class="">
<div class="">
<el-image :src="itemg.image" style="height: 200px; width: 200px;">
</el-image>
</div>
<div class="name m-l-10 line-1">
{{itemg.name}}
</div>
<div class="m-l-10 flex">
<div class="primary m-r-8">
<price-formate :price="itemg.min_price" :first-size="16" />
</div>
<div class="muted sm line-through">
<price-formate :price="itemg.market_price" />
</div>
</div>
</div>
</nuxt-link>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
<!-- 分类商品 -->
<div :class="xuanIndex == ''? 'm-t-10':''">
<div class="sort m-b-16 flex bg-white col-top" id="goods-sort">
<div class="sort-title">排序方式</div>
<div class="sort-name m-l-16 flex">
<div :class="['item', { active: sortType == '' }]" @click="changeSortType('')">
综合
</div>
<div :class="['item', { active: sortType == 'price' }]" @click="changeSortType('price')">
价格
<i v-show="priceSort == 'desc'" class="el-icon-arrow-down"></i>
<i v-show="priceSort == 'asc'" class="el-icon-arrow-up"></i>
</div>
<div :class="['item', { active: sortType == 'sales_sum' }]"
@click="changeSortType('sales_sum')">
销量
<i v-show="saleSort == 'desc'" class="el-icon-arrow-down"></i>
<i v-show="saleSort == 'asc'" class="el-icon-arrow-up"></i>
</div>
</div>
</div>
<template v-if="goodsList.length">
<goods-list :list="goodsList" :num="4" />
<div class="pagination flex m-t-30 row-center" style="padding-bottom: 38px" v-if="count">
<el-pagination background layout="prev, pager, next" :total="count" prev-text=""
next-text="下一页" hide-on-single-page :page-size="20" @current-change="changePage">
</el-pagination>
</div>
</template>
<null-data v-else :img="require('~/static/images/goods_null.png')" text="暂无商品~"></null-data>
</div>
</div>
</div>
</div>
</template>
<script>
import {
trottle
} from "~/utils/tools";
import {
Message
} from 'element-ui';
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
}, ],
}
},
layout: "street",
components: {},
async asyncData({
$get,
query,
}) {
//
const
shopData = await $get("shop/getShopInfo", {
params: {
shop_id: query.id
},
});
if (shopData.code == 1) {
if (shopData.data.goods_list.length > 0) {
var num = [];
for (var i = 0; i < Math.ceil(shopData.data.goods_list.length / 4); i++) {
var start = i * 4;
var end = start + 4;
num.push(shopData.data.goods_list.slice(start, end));
}
}
}
console.log('num', num)
//
const
coupon = await $get("coupon/getCouponList", {
params: {
shop_id: query.id
},
});
//
const
goodsClass = await $get("shop_goods_category/getShopGoodsCategory", {
params: {
shop_id: query.id
},
});
if (goodsClass.code == 1) {
if (goodsClass.data.length > 0) {
var group = [];
for (var i = 0; i < Math.ceil(goodsClass.data.length / 6); i++) {
var start = i * 6;
var end = start + 6;
group.push(goodsClass.data.slice(start, end));
}
}
}
console.log('group', group)
return {
recommend: num, //
shopInfo: shopData.data, //
goodsClassList: goodsClass.data, //
goodsClassListGroup: group, //
couponsList: coupon.data.lists, //
};
},
data() {
return {
goodsClassListGroup: [],
recommend: [],
couponsList: [],
gClassId: '',
shopInfo: [],
goodsClassList: [],
swiperOptions: {
pagination: {
el: '.swiper-pagination',
clickable: true,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
preventClicks: true,
slidesPerView: 'auto',
autoplay: true,
},
sortType: "",
saleSort: "desc",
priceSort: "desc",
page: 1,
count: 0,
goodsList: [],
more: false,
keyword: '',
xuanIndex: '',
}
},
created() {
this.getGoods();
this.changeSortType = trottle(this.changeSortType, 500, this);
},
methods: {
//
search() {
this.getGoods()
//
if(this.xuanIndex == '') {
setTimeout(() => {
document.getElementById('goods-sort').scrollIntoView()
}, 500)
}
},
//
changeXuan(id) {
this.xuanIndex = id
if (id == 'all') {
this.gClassId = ''
this.getGoods()
} else {
this.gClassId = id
this.getGoods()
}
},
//
async getShopData() {
const
shopData = await this.$get("shop/getShopInfo", {
params: {
shop_id: this.$route.query.id
},
});
if (shopData.code == 1) {
this.shopInfo = shopData.data
//
if (shopData.data.goods_list.length > 0) {
var num = [];
for (var i = 0; i < Math.ceil(shopData.data.goods_list.length / 4); i++) {
var start = i * 4;
var end = start + 4;
num.push(shopData.data.goods_list.slice(start, end));
}
}
console.log('num', num)
this.recommend = num
}
},
//
shopFollow() {
const a = this.$post("shop_follow/changeStatus", {
shop_id: this.$route.query.id
});
this.getShopData()
},
//
async hqCoupon(id) {
const {
msg,
code
} = await this.$post("coupon/getCoupon", {
coupon_id: id,
});
if (code == 1) {
this.$message({
message: msg,
type: "success",
});
}
this.getCouponList()
},
//
async getCouponList() {
const
coupon = await this.$get("coupon/getCouponList", {
params: {
shop_id: this.$route.query.id
},
});
},
//
getClassGoods(id) {
this.gClassId = id
if (id == '') {
this.xuanIndex = 'all'
} else {
this.xuanIndex = id
}
this.getGoods()
},
changeSortType(type) {
this.sortType = type;
switch (type) {
case "price":
if (this.priceSort == "asc") {
this.priceSort = "desc";
} else if (this.priceSort == "desc") {
this.priceSort = "asc";
}
break;
case "sales_sum":
if (this.saleSort == "asc") {
this.saleSort = "desc";
} else if (this.saleSort == "desc") {
this.saleSort = "asc";
}
break;
default:
}
this.getGoods();
},
changePage(current) {
this.page = current;
this.getGoods();
},
async getGoods() {
const {
name
} = this.$route.query;
const {
priceSort,
sortType,
saleSort
} = this;
let sort = "";
switch (sortType) {
case "price":
sort = priceSort;
break;
case "sales_sum":
sort = saleSort;
break;
}
const {
data: {
list,
count
},
} = await this.$get("pc/goodsList", {
params: {
page_size: 20,
page_no: this.page,
sort_type: sortType,
sort,
category_id: this.gClassId,
shop_id: this.$route.query.id,
name: this.keyword,
},
});
this.count = count
this.goodsList = list;
},
},
}
</script>
<style lang="scss">
.shop {
width: 227px;
padding: 15px;
.logo-img {
width: 62px;
height: 62px;
border-radius: 50%;
overflow: hidden;
}
.el-rate__icon {
font-size: 16px;
}
}
.h-item {
width: 82px;
height: 24px;
margin-right: 30px;
cursor: pointer;
}
.h-item-x {
border-radius: 100px;
background-color: #FF2C3C;
color: #FFFFFF;
}
.search {
width: 240px;
::v-deep .el-input {
width: 240px;
border-radius: 10px;
}
}
.shop-details {
margin-top: 10px;
.left {
.l-border {
padding-bottom: 27px;
border-bottom: 1px solid #EEEEEE;
margin-bottom: 27px;
}
.desc {
color: #101010;
font-size: 12px;
}
.desc-b {
color: #FFFFFF;
font-size: 12px;
}
.desc-n {
color: #FFFFFF;
font-size: 18px;
}
.desc-n {
color: #101010;
font-size: 14px;
}
.left-btn {
width: 82px;
height: 29px;
border-radius: 4px;
border: 1px solid rgba(187, 187, 187, 100);
}
.left-shop {
background-color: #FFFFFF;
padding: 20px 15px;
width: 210px;
height: 364px;
}
.r-color-h {
background-color: #A4ADB3;
color: #FFFFFF;
}
.l-tips {
padding: 1px 2px;
}
.l-fen {
width: 210px;
height: 44px;
line-height: 20px;
color: rgba(16, 16, 16, 100);
font-size: 14px;
text-align: center;
cursor: pointer;
}
.l-fen-select {
color: #FF2C3C;
;
}
}
.right {
width: 961px;
.coupon-list {
background-color: #FFFFFF;
padding: 20px 0;
margin: 0 20px;
border-bottom: 1px solid #EEEEEE;
.coupons-more {
cursor: pointer;
}
.swiper-item-c {
width: 760px;
// height: 120px;
flex-wrap: nowrap;
overflow: hidden;
}
.swiper-item-zk {
width: 770px;
flex-wrap: wrap;
}
}
.shop-list {
background-color: #FFFFFF;
height: 360px;
padding: 0 20px;
padding-top: 10px;
.shop-item {
width: 200px;
height: 298px;
background-color: #FFFFFF;
margin-right: 12px;
.name {
color: rgba(16, 16, 16, 100);
font-size: 14px;
text-align: left;
margin-bottom: 18px;
}
}
}
}
.sort {
padding: 16px 16px 0;
.sort-name {
.item {
margin-right: 30px;
cursor: pointer;
&.active {
color: #FF2C3C
}
}
}
}
.swiper {}
.swiper-item {
width: 672px;
// box-sizing: content-box;
}
.item {
margin-bottom: 20px;
margin-right: 16px;
position: relative;
cursor: pointer;
.coupon-button {
background-color: #f2f2f2;
width: 240px;
height: 30px;
padding: 0 8px;
}
.info {
padding: 0 10px;
background: url("~/static/images/bg_coupon_s.png") no-repeat;
width: 240px;
height: 80px;
background-size: 100%;
&.gray {
background-image: url("~/static/images/bg_coupon.png");
}
.info-hd {
overflow: hidden;
}
}
.tips {
position: relative;
background-color: #f2f2f2;
height: 30px;
padding: 0 8px;
.tips-con {
width: 100%;
left: 0;
background-color: #f2f2f2;
position: absolute;
top: 30px;
padding: 10px;
z-index: 99;
}
}
.receice {
position: absolute;
top: 0;
right: 0px;
width: 58px;
height: 45px;
}
.choose {
position: absolute;
top: 0;
right: 0;
background-color: #ffe72c;
color: $--color-primary;
padding: 1px 5px;
}
}
.more {
position: absolute;
bottom: 20px;
cursor: pointer;
right: 30px;
}
}
</style>

View File

@ -0,0 +1,128 @@
<!-- 专区内页 -->
<template>
<div class="special-area">
<div class="header-top">
<el-breadcrumb style="flex: 1;" separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item class="line1" style="max-width: 800px;">{{ name }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="m-b-20 header-img">
<!-- <el-image :src="require('@/static/images/special_area_bg.jpg')" style="height: 240px; width: 1180px;"></el-image> -->
<div class="header-img-tile flex-col col-center row-center">
<div class="max-title white">
{{ name }}
</div>
<div class="m-t-22 min-title white">
{{ title }}
</div>
</div>
</div>
<template v-if="goodsList.length">
<goods-list :list="goodsList" />
<div class="pagination flex m-t-30 row-center" style="padding-bottom: 38px" v-if="count">
<el-pagination background layout="prev, pager, next" :total="count" prev-text="" next-text=""
hide-on-single-page :page-size="20" @current-change="changePage">
</el-pagination>
</div>
</template>
<null-data v-else :img="require('~/static/images/goods_null.png')" text="暂无商品~"></null-data>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
}, ],
}
},
async asyncData({ query }) {
return {
name: query.name,
title: query.title,
}
},
data() {
return {
goodsList: [],
page: 1,
count: 0,
}
},
methods: {
//
async getGoods() {
const id = this.$route.query.id
let {
code,
data: {
list,
count
}
} = await this.$get("activity_area/activityGoodsList", {
params: {
id: id,
page_no: this.page,
page_size: 20,
},
})
if (code == 1) {
this.goodsList = list
this.count = count
}
},
changePage(current) {
this.page = current;
this.getGoods();
},
},
created() {
this.getGoods()
},
}
</script>
<style lang="scss" scoped>
.special-area {
.header-top {
margin: 16px 0;
}
.header-img {
width: 1180px;
height: 240px;
background: url(../static/images/special_area_bg.jpg);
.header-img-tile {
.max-title {
margin-top: 65px;
font-size: 32px;
text-align: center;
}
.min-title {
padding: 5px 27px;
font-size: 14px;
text-align: center;
border-radius: 100px;
background-color: rgba(186, 122, 246);
}
}
}
}
</style>

View File

@ -0,0 +1,164 @@
<template>
<div class="detail">
<div class="m-t-20">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/store_settled' }"><a>商家入驻</a></el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/store_settled/record' }"><a>申请列表</a></el-breadcrumb-item>
<el-breadcrumb-item>详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="main bg-white m-t-20">
<div class="header">
<div class="m-b-30 pointer" @click="$router.back();">
<i class="el-icon-arrow-left"></i>
返回
</div>
<div v-if="detail.audit_status==1">
<div class="flex normal xxl bold" style="font-weight:600">
<img class="m-r-12" src="~/static/images/time.png" alt="">
恭喜您资料提交成功
</div>
<div class="xs muted m-t-12 m-l-42">
预计在3个工作日内审核完毕如通过我们将会发送短信通知您请注意查收
</div>
</div>
<div v-else-if="detail.audit_status==3">
<div class="flex normal xxl bold" style="font-weight:600">
<img class="m-r-12" src="~/static/images/error.png" alt="">
很遗憾审核不通过
</div>
<div class="xs muted m-t-12 m-l-42">
请尽量完善您的资料信息再重新提交
</div>
</div>
<div v-else-if="detail.audit_status==2">
<div class="flex normal xxl bold" style="font-weight:600">
<img class="m-r-12" src="~/static/images/success.png" alt="">
恭喜您审核已通过
</div>
<div class="xs muted m-t-12 m-l-42">
您的审核已通过
</div>
<div class="admin m-t-20">
<div class="xs p-t-16">
<span>PC管理后台地址</span>
<a :href="detail.admin_address">
{{detail.admin_address}}
</a>
</div>
<div class="xs m-t-16">
<span>商家账号</span>
<a href="" target="_blank" rel="noopener noreferrer">
{{detail.account}}
</a>
</div>
<div class="xs m-t-16">
<span>登录密码</span>
登录密码密码是您在创建账号时设置的登录密码如忘记密码可联系官方客服进行修改
</div>
</div>
</div>
</div>
<div class="section">
<div class="xl bold normal m-b-30">资料详情</div>
<el-form :model="detail" size="medium" :label-position="'left'" ref="form" label-width="110px"
class="demo-form">
<el-form-item label="商家名称:" prop="name">
<span>{{detail.name}}</span>
</el-form-item>
<el-form-item label="主营类目:" prop="name">
<span>{{detail.cid_desc}}</span>
</el-form-item>
<el-form-item label="联系人姓名:" prop="name">
<span>{{detail.nickname}}</span>
</el-form-item>
<el-form-item label="手机号码:" prop="name">
<span>{{detail.mobile}}</span>
</el-form-item>
<el-form-item label="商家账号:" prop="name">
<span>{{detail.account}}</span>
</el-form-item>
<el-form-item label="营业执照:" prop="name">
<el-image v-for="(item, index) in detail.license" :key="index"
style="width: 72px; height: 72px; margin-right: 10px" :src="item" fit="fit"></el-image>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
data() {
return {
detail: {},
};
},
async mounted() {
console.log(this.$route.query.id);
const { data } = await this.$get("ShopApply/detail", {
params: { id: this.$route.query.id },
});
this.detail = data
console.log("我艹啊私房话哀诉还是");
},
methods: {},
};
</script>
<style lang="scss" scope>
.detail {
width: 100%;
height: 788px;
.main {
width: 100%;
height: 788px;
padding: 30px;
.header {
padding: 0px 0 40px;
margin-bottom: 25px;
border-bottom: 1px dotted #e5e5e5;
img {
width: 32px;
height: 32px;
}
.admin {
background: #f6f6f6;
padding: 0 30px;
padding-bottom: 16px;
a:hover {
color: #ff2c3c;
}
}
}
}
}
</style>

View File

@ -0,0 +1,303 @@
<template>
<div>
<div class="m-t-20">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商家入驻</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="store bg-white m-t-16">
<div class="main">
<div class="title">入驻申请</div>
<el-form :model="form" :rules="rules" ref="form" label-width="110px" class="demo-form">
<el-form-item label="商家名称:" prop="name">
<el-input v-model="form.name" placeholder="请输入商家名称"></el-input>
</el-form-item>
<el-form-item label="主营类目:" prop="cid">
<el-select v-model="form.cid" placeholder="请选择" style="width: 100%">
<el-option v-for="item in category" :key="item.id" :label="item.name" :value="item.id">
{{item.name}}
</el-option>
</el-select>
</el-form-item>
<el-form-item label="联系人姓名:" prop="nickname">
<el-input v-model="form.nickname" placeholder="请输入联系人姓名"></el-input>
</el-form-item>
<el-form-item label="手机号码:" prop="mobile">
<el-input v-model="form.mobile" placeholder="请输入手机号码"></el-input>
</el-form-item>
<el-form-item label="验证码:" prop="code">
<el-input v-model="form.code" placeholder="请输入验证码" style="width:355px"></el-input>
<el-button style="margin-left: 14px;width: 175px" @click="sndSmsToPhone">
<div v-if="canSendPwd"></div>
<count-down v-else :time="60" format="ss秒" autoStart @finish="canSendPwd = true" />
</el-button>
</el-form-item>
<el-form-item label="创建账号:" prop="account">
<el-input v-model="form.account" placeholder="请设置登录账号(可用手机号代替)"></el-input>
</el-form-item>
<el-form-item label="设置密码:" prop="password">
<el-input v-model="form.password" placeholder="请输入登录密码"></el-input>
</el-form-item>
<el-form-item label="营业执照:" prop="">
<el-upload class="avatar-uploader" :action="action" :show-file-list="true"
list-type="picture-card" :on-success="uploadFileSuccess" :on-remove="handleRemove"
:headers="{token: $store.state.token}">
<i class="el-icon-picture avatar-uploader-icon"></i>
<div class="m-t-20 xs">上传图片</div>
</el-upload>
<div class="xs muted">支持jpgpngjpeg格式的图片最多可上传10张</div>
</el-form-item>
<el-form-item label="">
<div class="xs muted m-t-20">
<el-checkbox v-model="checked"></el-checkbox>
同意并阅读<span class="primary pointer" @click="dialogVisible=true"></span>
</div>
<div class="flex m-t-10">
<el-button style="width: 213px;" class="bg-primary white" @click="onSubmitStore('form')">
提交申请
</el-button>
<span class="m-l-20 xs muted pointer"
@click="$router.push('/store_settled/record')">查看申请记录</span>
</div>
</el-form-item>
</el-form>
</div>
</div>
<!-- 服务协议 -->
<el-dialog title="提示" :visible.sync="dialogVisible" width="50%">
<div style="height: 40vh;overflow-y: auto;">
<div v-html="content">
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import config from "~/config/app";
import { SMSType } from "~/utils/type";
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
data() {
return {
checked: false,
action: config.baseUrl + "/api/file/formimage",
category: [], //
fileList: [],
content: "", //
dialogVisible: false, //
canSendPwd: true, //
form: {
cid: "", //ID
clabel: "", //
name: "", //
nickname: "", //
mobile: "", //
account: "", //
password: "", //
code: "", //
},
rules: {
name: [
{
required: true,
message: "请输入商家名称",
trigger: "blur",
},
],
cid: [
{
required: true,
message: "请选择主营类目",
trigger: "change",
},
],
nickname: [
{
required: true,
message: "请输入联系人姓名",
trigger: "blur",
},
],
mobile: [
{
required: true,
message: "请输入手机号码",
trigger: "blur",
},
{
pattern: /^1[3|4|5|7|8][0-9]{9}$/,
message: "请输入正确的手机号",
},
],
code: [
{
required: true,
message: "请输入验证码",
trigger: "blur",
},
],
account: [
{
required: true,
message: "请输入登录账号",
trigger: "blur",
},
],
password: [
{
required: true,
message: "请输入设置登录密码",
trigger: "blur",
},
],
imageForm: [
{
required: true,
message: "请上传营业执照",
trigger: "blur",
},
],
},
};
},
async asyncData({ $get }) {
const { data } = await $get("shop_category/getList");
return { category: data };
},
mounted() {
this.getServiceData();
},
methods: {
async sndSmsToPhone() {
if (!/^1[3|4|5|7|8][0-9]{9}$/.test(this.form.mobile))
return this.$message.error("请输入正确的手机号码");
const { code } = await this.$post("sms/send", {
mobile: this.form.mobile,
key: SMSType.SJSQYZ,
});
if (code == 1) {
this.canSendPwd = false;
return this.$message.success("发送成功");
} else return this.$message.error("发送失败");
},
uploadFileSuccess(res, fileList) {
this.fileList.push(res.data.uri);
console.log(res, this.fileList);
},
handleRemove(file, fileList) {
console.log(fileList);
if (fileList.length >= 0) {
const res = fileList.map((item) => item.response.data.uri);
this.fileList = res;
}
},
async getServiceData() {
const res = await this.$get("ShopApply/getTreaty");
if (res.code == 1) {
this.content = res.data.content;
}
},
onSubmitStore(formName) {
if (!this.checked)
return this.$message.error("请同意并阅读服务协议");
this.$refs[formName].validate(async (valid) => {
if (valid) {
const { data, code, msg } = await this.$post(
"ShopApply/apply",
{
...this.form,
license: this.fileList,
}
);
if (code == 1) {
// data.id
this.$router.push({
path: "/store_settled/detail",
query: {
id: data.id,
},
});
}
} else return false;
});
},
},
};
</script>
<style lang="scss" scope>
.store {
width: 100%;
.main {
width: 660px;
margin: 0 auto;
padding-bottom: 52px;
.title {
padding: 16px 0;
color: #101010;
font-size: 18px;
text-align: center;
}
::v-deep .el-input__inner {
border-radius: 0 !important;
}
.avatar-uploader .el-upload {
width: 100px;
height: 100px;
border: 1px solid #d9d9d9;
cursor: pointer;
position: relative;
line-height: 0px;
padding: 20px 0;
color: #101010;
overflow: hidden;
border-radius: 0;
}
.avatar-uploader .el-upload:hover {
border-color: #ff2c3c;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
display: block;
}
}
}
</style>

View File

@ -0,0 +1,84 @@
<template>
<div class="record">
<div class="m-t-20">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/store_settled' }"><a>商家入驻</a></el-breadcrumb-item>
<el-breadcrumb-item>申请列表</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="main bg-white m-t-20">
<el-table :data="record" style="width: 100%" size="medium"
:header-cell-style="{background:'#eee',color:'#606266'}">
<el-table-column prop="name" label="商家名称" max-width="180">
</el-table-column>
<el-table-column prop="audit_status_desc" label="审核状态" max-width="180">
<template slot-scope="scope">
<div class="primary" v-if="scope.row.audit_status==3">{{scope.row.audit_status_desc}}</div>
<div v-else>{{scope.row.audit_status_desc}}</div>
</template>
</el-table-column>
<el-table-column prop="apply_time" label="提交时间" max-width="180">
</el-table-column>
<el-table-column label="操作" max-width="180">
<template slot-scope="scope">
<div class="pointer" @click="$router.push({
path: '/store_settled/detail',
query: {
id: scope.row.id
}
})">查看详情</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
data() {
return {
record: [],
};
},
mounted() {
// console.log("");
},
async asyncData({ $get }) {
const { data } = await $get("ShopApply/record");
console.log(data);
return { record: data.lists };
},
methods: {},
};
</script>
<style lang="scss" scope>
.record {
width: 100%;
height: 788px;
.main {
padding: 18px;
height: 100%;
}
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<div class="address-list">
<div class="address-header lg">收货地址</div>
<div class="address-content" v-show="!isDataNull">
<el-table :data="addressList" style="width: 100%">
<el-table-column prop="contact" label="收货人" width="200" />
<el-table-column prop="telephone" label="手机号码" width="150" />
<el-table-column prop="addressDetail" label="收货地区" />
<el-table-column fixed="right" label="操作" max-width="216">
<template slot-scope="scope">
<div class="flex">
<div class="flex m-r-20" style="margin-left: 36px;cursor: pointer;" @click="setDefault(scope.row)">
<div :class="{'default-border': scope.row.is_default == 0}"
style="width: 16px;height: 16px;margin-right: 8px;"
v-if="scope.row.is_default == 0" />
<img :class="{'default-border': scope.row.is_default == 0}"
style="width: 16px;height: 16px;margin-right: 8px;" v-else
src="~/static/images/logistics_success.png" />
<div class="nr" :class="{'primary': scope.row.is_default == 1}">
{{scope.row.is_default == 1 ? '设为默认' : '设为默认'}}</div>
<!-- <el-radio v-model="scope.row.is_default" >{{scope.row.is_default == 1 ? '默认' : '设为默认'}}</el-radio> logistics_success -->
</div>
<div style="margin-right: 24px;">
<el-button @click="modifyRow(scope.row)" type="text" class="nr" size="small">修改
</el-button>
</div>
<el-popconfirm confirm-button-text='' cancel-button-text='' icon="el-icon-info"
icon-color="red" title="确定要删除地址吗?" @confirm="deleteAddress(scope.row)">
<el-button type="text" slot="reference" size="small" class="nr">删除</el-button>
</el-popconfirm>
</div>
</template>
</el-table-column>
</el-table>
<div class="add-address-btn flex row-end">
<el-button type="primary" style="width: 106px" @click="showAddressPop"></el-button>
</div>
</div>
<div class="column-center data-null" v-show="isDataNull">
<img style="width: 150px;height: 150px" src="@/static/images/address_null.png" />
<div class="muted xs m-t-8">暂无地址记录</div>
<div class="m-t-30">
<el-button type="primary" style="width: 106px" @click="showAddressPop"></el-button>
</div>
</div>
<address-add v-model="addressPop" :aid="editId == -1 ? '' : editId" @success="getAddressList" />
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
async asyncData({ $get, $post }) {
let addressList = [];
let isDataNull = true;
let res = await $get("user_address/lists");
if (res.code == 1) {
addressList = res.data;
addressList.forEach((item) => {
item.addressDetail =
item.province +
" " +
item.city +
" " +
item.district +
" " +
item.address;
});
if (addressList.length <= 0) {
isDataNull = true;
} else {
isDataNull = false;
}
}
return {
addressList,
isDataNull,
};
},
data() {
return {
addressPop: false,
editId: -1,
isDataNull: false
};
},
mounted() {},
methods: {
modifyRow(e) {
this.editId = e.id;
this.addressPop = true;
},
//
async setDefault(e) {
let res = await this.$post("user_address/setdefault", { id: e.id });
if (res.code == 1) {
await this.getAddressList();
this.$message({
message: "设置成功",
type: "success",
});
}
},
//
async getAddressList() {
let res = await this.$get("user_address/lists");
if (res.code == 1) {
this.addressList = res.data;
this.addressList.forEach((item) => {
item.addressDetail =
item.province +
" " +
item.city +
" " +
item.district +
" " +
item.address;
});
if (this.addressList.length <= 0) {
this.isDataNull = true;
} else {
this.isDataNull = false;
}
}
},
//
async deleteAddress(e) {
let res = await this.$post("user_address/del", { id: e.id });
if (res.code == 1) {
await this.getAddressList();
this.$message({
message: "删除成功",
type: "success",
});
}
},
//
showAddressPop() {
this.addressPop = true;
this.editId = -1;
},
},
};
</script>
<style lang="scss" scoped>
.address-list {
width: 980px;
padding: 10px;
.address-header {
padding: 10px 5px;
border-bottom: 1px solid #e5e5e5;
}
.address-content {
margin-top: 15px;
.default-border {
border: 1px solid #e5e5e5;
border-radius: 60px;
}
::v-deep .el-table {
color: #222;
}
::v-deep .el-table .el-button--text {
color: #222;
font-weight: 400;
}
::v-deep .el-table th {
background-color: #f2f2f2;
}
::v-deep .el-table thead {
color: #555555;
}
.add-address-btn {
margin-top: 18px;
}
}
.data-null {
text-align: center;
padding-top: 150px;
}
}
</style>

View File

@ -0,0 +1,229 @@
<template>
<div class="apply-detail">
<div class="apply-detail-content">
<el-table :data="lists.order_goods" style="width: 100%">
<el-table-column prop="date" label="商品信息" max-width="180">
<template slot-scope="scope">
<div class="flex">
<el-image style="width: 80px; height: 80px" :src="scope.row.image" fit="fit"></el-image>
<div class="m-l-10">
<div class="line-2">
{{scope.row.goods_name}}
</div>
<div>
{{scope.row.spec_value}}
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="name" label="价格" width="180">
<template slot-scope="scope">
¥{{scope.row.goods_price}}
</template>
</el-table-column>
<el-table-column prop="goods_num" label="数量" width="180">
</el-table-column>
<el-table-column prop="address" label="申请状态" width="180">
<template>{{lists.status_text}}</template>
</el-table-column>
</el-table>
<div class="m-t-30" style="padding: 0 20px">
<div class="result-content">
<div class="result-item flex">
<div class="label">退款类型:</div>
<div class="desc">{{lists.refund_type_text}}</div>
</div>
<div class="result-item flex">
<div class="label">退款原因:</div>
<div class="desc">{{lists.refund_reason}}</div>
</div>
<div class="result-item flex">
<div class="label">退款金额:</div>
<div class="desc">
<price-formate :price="lists.refund_price" showSubscript color="red" />
</div>
</div>
<div class="result-item flex">
<div class="label">申请时间:</div>
<div class="desc">{{lists.create_time}}</div>
</div>
<div class="result-item flex">
<div class="label">退款编号:</div>
<div class="desc">{{lists.sn}}</div>
</div>
<div class="result-item flex">
<div class="label">退款说明:</div>
<div class="column desc">
<div class="m-b-16"></div>
<el-image style="width: 76px;height: 76px;" :src="lists.refund_image"
v-if="lists.refund_image" :preview-src-list="[lists.refund_image]" />
</div>
</div>
</div>
</div>
<div class="apply-detail-address flex" v-if="lists.refund_type_text == '退款退货' && lists.status == 2">
退货地址{{lists.shop.contact||'-'}},{{lists.shop.mobile||'-'}}, {{lists.shop.address||'-'}}
<div class="copy pointer" @click="onCopy"></div>
</div>
<div class="btn-group flex row-center m-t-60">
<el-popconfirm title="确定撤销商品吗?" confirm-button-text="" cancel-button-text="" icon="el-icon-info"
icon-color="red" @confirm="cancelApply(lists.id)">
<el-button class="apply-btn flex row-center sm" size="small" slot="reference"
v-if="lists.status!=6">撤销申请</el-button>
</el-popconfirm>
<el-button class="apply-btn flex row-center sm" size="small" v-if="lists.status==2"
@click="showInput=true">填写快递单号</el-button>
</div>
</div>
<input-express v-model="showInput" @success="getDetail" :aid="lists.id" />
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
data() {
return {
lists: {
order_goods: [],
shop: {},
},
showInput: false,
};
},
mounted() {
this.getDetail();
},
methods: {
async getDetail() {
let res = await this.$get("after_sale/detail", {
params: {
id: this.$route.query.afterSaleId,
},
});
if (res.code == 1) {
let goods = [res.data.order_goods];
res.data.order_goods = goods;
console.log(goods);
this.lists = res.data;
}
},
onCopy() {
// this.deliverOrder.invoice_no;
let oInput = document.createElement("input");
oInput.value = this.lists.shop.address;
document.body.appendChild(oInput);
oInput.select();
document.execCommand("Copy");
this.$message.success("复制成功");
oInput.remove();
},
async cancelApply(afterSaleId) {
let res = await this.$post("after_sale/cancel", {
id: afterSaleId,
});
if (res.code == 1) {
this.$message({
message: res.msg,
type: "success",
});
setTimeout(() => {
this.$router.go(-1);
}, 500);
}
},
goRefund(afterSaleId, orderId, itemId) {
this.$router.push(
"/user/after_sales/apply_result?afterSaleId=" +
afterSaleId +
"&order_id=" +
orderId +
"&item_id=" +
itemId
);
},
},
};
</script>
<style lang="scss" scoped>
.apply-detail {
padding: 10px;
.apply-detail-header {
padding: 15px 0;
border-bottom: 1px solid #e5e5e5;
}
.apply-detail-address {
margin: 0 10px;
padding-top: 16px;
border-top: 1px solid #e5e5e5;
.copy {
margin-left: 20px;
padding: 2px 6px;
color: $--color-primary;
background-color: rgba(255, 44, 60, 0.2);
}
}
.result-content {
padding: 24px 20px;
.result-item {
margin-bottom: 16px;
&:not(:last-of-type) {
.label {
width: 82px;
align-self: flex-start;
text-align: right;
&::before {
content: "* ";
color: red;
}
}
}
.label {
width: 82px;
align-self: flex-start;
text-align: right;
}
.desc {
margin-left: 24px;
width: 680px;
}
}
}
.apply-detail-content {
.btn-group {
.apply-btn {
border: 1px solid #cccccc;
border-radius: 2px;
width: 100px;
height: 32px;
align-self: flex-start;
margin-right: 10px;
}
}
}
}
</style>

View File

@ -0,0 +1,106 @@
<template>
<div class="apply-result-container">
<div class="result-header flex">
<img style="width: 40px;height: 40px;align-self: flex-start" src="~/static/images/pay_success.png" />
<div class="m-l-16">
<div class="apply-title" style="font-weight: 500;">提交申请</div>
<div class="muted m-t-8">申请已提交请耐心等待商家处理</div>
</div>
</div>
<div class="result-content">
<div class="result-item flex">
<div class="label">退款类型</div>
<div class="desc">{{lists.refund_type_text}}</div>
</div>
<div class="result-item flex">
<div class="label">退款原因</div>
<div class="desc">{{lists.refund_reason}}</div>
</div>
<div class="result-item flex">
<div class="label">退款金额</div>
<div class="desc">
<price-formate :price="lists.refund_price" showSubscript color="red" />
</div>
</div>
<div class="result-item flex">
<div class="label">退款说明</div>
<div class="column desc">
<div class="m-b-16">{{lists.refund_remark}}</div>
<el-image style="width: 76px;height: 76px;" :src="lists.refund_image" v-if="lists.refund_image" :preview-src-list="[lists.refund_image]" />
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{ rel: "icon", type: "image/x-icon", href: this.$store.getters.favicon}],
};
},
layout: "user",
async asyncData({$get, query}) {
const data = {
id: query.afterSaleId
};
let lists = {}
let res = await $get("after_sale/detail", {params: data});
if(res.code == 1) {
lists = res.data;
}
return {
lists,
}
},
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.apply-result-container {
padding: 10px;
.result-header {
padding: 46px 20px;
border-bottom: 1px solid #E5E5E5;
.apply-title {
font-size: 24px;
}
}
.result-content {
padding: 24px 20px;
.result-item {
margin-bottom: 16px;
&:not(:last-of-type) {
.label {
width: 82px;
align-self: flex-start;
text-align: right;
&::before {
content: '* ';
color: red;
}
}
}
.label {
width: 82px;
align-self: flex-start;
text-align: right;
}
.desc {
margin-left: 24px;
width: 680px;
}
}
}
}
</style>

View File

@ -0,0 +1,242 @@
<template>
<div class="apply-sale-list">
<div class="goods-info">
<div class="table-head flex">
<div class="info">商品信息</div>
<div class="price flex row-center">单价</div>
<div class="num flex row-center">数量</div>
<div class="sum flex row-center">合计</div>
<div class="act-pay flex row-center">实付</div>
</div>
<div class="table-content flex m-t-10">
<div class="info flex">
<div class="flex">
<el-image style="width: 72px;height: 72px; flex: none" :src="goods.image" />
<div class="m-l-10" style="flex: 1; align-self: flex-start">
<div class="line2">{{goods.goods_name}}</div>
<div class="mt10 muted sm">{{goods.spec_value}}</div>
</div>
</div>
</div>
<div class="price flex row-center" style="align-self: flex-start">
<price-formate :price="goods.goods_price" />
</div>
<div class="num flex row-center" style="align-self: flex-start">
{{goods.goods_num}}
</div>
<div class="sum flex row-center" style="align-self: flex-start">
<price-formate :price="goods.total_price" />
</div>
<div class="act-pay flex row-center" style="align-self: flex-start">
<price-formate :price="goods.total_pay_price" />
</div>
</div>
</div>
<div class="apply-form">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="退款类型:" prop="applyType">
<el-radio-group v-model="applyType" @change="applyRadioChange">
<el-radio label="仅退款"></el-radio>
<el-radio label="退货退款"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="退款原因:" prop="reason">
<el-select v-model="form.reason" placeholder="请选择">
<el-option :label="item" :value="item" v-for="(item, index) in reason" :key="index" />
</el-select>
</el-form-item>
<el-form-item label="退款说明:" prop="desc">
<el-input style="width: 600px" type="textarea" v-model="form.desc" placeholder="退款说明200字以内"
maxlength="200" show-word-limit resize="none" rows="5" />
</el-form-item>
<el-form-item>
<upload isSlot :file-list="fileList" @remove="uploadSuccess" @success="uploadSuccess" :limit="3">
<div class="" style="height: 100%">
<i class="el-icon-camera xs" style="font-size: 24px" />
</div>
</upload>
<div class="xs muted">最多可上传3张图片支持jpgpng格式图片大小1M以内</div>
</el-form-item>
<el-form-item>
<div class="flex">
<el-button type="primary" @click="onSubmit"></el-button>
<div class="m-l-20">
退款金额<span class="primary">¥{{goods.total_price}}</span>
</div>
</div>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
name: "applySale",
async asyncData({ $get, $post, query }) {
let goods = {};
let reason = [];
let res = await $get("after_sale/goodsInfo", {
params: {
order_id: query.order_id,
item_id: query.item_id,
},
});
if (res.code == 1) {
goods = res.data.goods;
reason = res.data.reason;
}
return {
reason,
goods,
};
},
data() {
return {
applyType: "仅退款",
form: {
applyType: 0,
reason: "",
desc: "",
},
rules: {
applyType: [{ required: true, message: "请选择退款类型" }],
reason: [
{
required: true,
message: "请选择退款原因",
triggle: "blur",
},
],
},
fileList: [],
};
},
methods: {
applyRadioChange(value) {
value == "仅退款"
? (this.form.applyType = 0)
: (this.form.applyType = 1);
},
onSubmit(e) {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.$route.query.afterSaleId) {
this.applyAgainFun();
} else {
this.$applyAfterSale();
}
} else {
return false;
}
});
},
onUploadChange(e) {
let fileList = Object.assign([], this.fileList);
fileList.push(e);
this.fileList = fileList;
console.log("onChange", e, " fileList:", this.fileList);
},
uploadSuccess(e) {
this.fileList = e.map((item) => item.response.data.uri);
},
//
async $applyAgain() {
const data = {
id: this.$route.query.afterSaleId,
reason: this.form.reason,
refund_type: this.form.applyType,
remark: this.form.desc,
img: fileList.length <= 0 ? "" : this.fileList[0],
};
let res = await $post("after_sale/again", data);
if (res.code == 1) {
this.$message({
message: "提交成功",
type: "success",
});
this.$router.push(
"/user/after_sales/apply_result?afterSaleId=" +
res.data.after_sale_id
);
}
},
//
async $applyAfterSale() {
console.log(this.fileList[0])
const data = {
item_id: this.$route.query.item_id,
order_id: this.$route.query.order_id,
reason: this.form.reason,
refund_type: this.form.applyType,
remark: this.form.desc,
//
img: this.fileList[0],
};
let res = await this.$post("after_sale/add", data);
if (res.code == 1) {
this.$message({
message: "提交成功",
type: "success",
});
this.$router.push(
"/user/after_sales/apply_result?afterSaleId=" +
res.data.after_sale_id
);
}
},
},
};
</script>
<style lang="scss" scoped>
.apply-sale-list {
padding: 10px;
.goods-info {
.table-head {
padding: 10px 20px;
border-bottom: 1px solid #e5e5e5;
}
.table-content {
padding: 10px 20px;
border-bottom: 1px solid #e5e5e5;
}
.info {
width: 500px;
}
.price {
width: 100px;
}
.num {
width: 100px;
}
.sum {
width: 100px;
}
.act-pay {
width: 100px;
}
}
.apply-form {
margin-top: 24px;
}
}
</style>

View File

@ -0,0 +1,148 @@
<template>
<div class="after-sales">
<div class="after-sales-header">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane v-for="(item, index) in afterSale" :key="index" :label="item.name" :name="item.type">
<template v-if="item.list.length">
<after-sales-list :type="item.type" :lists="item.list" @refresh="getAfterSaleList"
@show="onInputShow" />
<div class="pagination row-center" v-if="item.count">
<el-pagination hide-on-single-page background layout="prev, pager, next" :total="item.count"
prev-text="上一页" next-text="下一页" :page-size="10" @current-change="changePage">
</el-pagination>
</div>
</template>
<template v-else>
<null-data :img="require('~/static/images/order_null.png')" text="暂无售后~"></null-data>
</template>
</el-tab-pane>
</el-tabs>
</div>
<input-express v-model="showInput" :aid="aid" @success="getAfterSaleList" />
</div>
</template>
<script>
import { AfterSaleType } from "@/utils/type";
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
data() {
return {
activeName: AfterSaleType.NORMAL,
afterSale: [
{
type: AfterSaleType.NORMAL,
list: [],
name: "售后申请",
count: 0,
page: 1,
},
{
type: AfterSaleType.HANDLING,
list: [],
name: "处理中",
count: 0,
page: 1,
},
{
type: AfterSaleType.FINISH,
list: [],
name: "已处理",
count: 0,
page: 1,
},
],
showInput: false,
aid: -1,
};
},
async asyncData({ $get, $post }) {
let afterList = [];
let res = await $get("after_sale/lists", {
params: { page_no: 1, page_size: 10 },
});
if (res.code == 1) {
const { list, count } = res.data;
afterList = { list, count };
}
return {
afterList: afterList,
};
},
methods: {
handleClick() {
this.getAfterSaleList();
},
onInputShow(e) {
this.aid = e;
this.showInput = true;
},
changePage(val) {
this.afterSale.some((item) => {
if (item.type == this.activeName) {
item.page = val;
}
});
this.getAfterSaleList();
},
async getAfterSaleList() {
const { activeName, afterSale } = this;
const item = afterSale.find((item) => item.type == activeName);
const {
data: { list, count },
code,
} = await this.$get("after_sale/lists", {
params: {
page_size: 10,
page_no: item.page,
type: activeName,
},
});
if (code == 1) {
this.afterList = { list, count };
}
},
},
watch: {
afterList: {
immediate: true,
handler(val) {
this.afterSale.some((item) => {
if (item.type == this.activeName) {
Object.assign(item, val);
return true;
}
});
},
},
},
};
</script>
<style lang="scss" scoped>
.after-sales {
.after-sales-header {
padding: 15px;
}
::v-deep .el-tabs__header {
margin-left: 5px;
}
::v-deep .el-tabs .el-tabs__nav-scroll {
padding: 0;
}
}
</style>

View File

@ -0,0 +1,336 @@
<template>
<div class="user-collection-container">
<div class="user-collection-content">
<el-tabs v-model="activeName" class="mt10" @tab-click="handleClick">
<el-tab-pane v-for="(item, index) in userCollection" :label="item.name" :name="item.type+''"
:key="index">
<div v-if="index == activeName">
<template v-if="userCollection[activeName].lists.length">
<!-- 商品收藏 -->
<template v-if="activeName == 0">
<div @click.stop="$router.push({
path: '/goods_details/'+item2.id
})" class="goods"
v-for="(item2, index2) in item.lists" :key="index2">
<div class="goods-image">
<el-image style="width: 180px; height: 180px" :src="item2.image" fit="fit">
</el-image>
<div class="goods-image-wrap flex">
<div @click.stop="cancelColl(item2.id)">取消收藏</div>
<div @click.stop="$router.push({
path: '/shop_street_detail',
query: {
id: item2.shop_id
}
})">进入店铺</div>
</div>
</div>
<div class="goods-name m-t-10">
<div class="line-2">{{item2.name}}</div>
</div>
<div class="m-t-14">
<span class="primary xl">¥{{item2.min_price}}</span>
</div>
</div>
</template>
<!-- 店铺收藏 -->
<template v-if="activeName == 1">
<div class="shop flex" style="width:100%" v-for="(item2, index2) in item.lists" :key="index2">
<!-- 店铺 -->
<div class="shop-item flex-col row-right" :style="{
'background-image': `url(${item2.cover})`,
}">
<div class="shop-wrap xs flex">
<div @click.stop="cancelColl(item2.id)">取消收藏</div>
<div @click.stop="$router.push({
path: '/shop_street_detail',
query: {
id: item2.shop_id
}
})">进入店铺</div>
</div>
<div class="bg-white shop-info text-center">
<el-image class="logo" :src="item2.logo"></el-image>
<div class="m-t-12 line-1 lg">
{{ item2.name }}
</div>
</div>
</div>
<!-- 店铺下的商品 -->
<div style="width: 100%" class="flex-1 m-l-20" v-if="item2.goods_list.length >= 1">
<div class="shop-title flex row-between">
<span>店铺推荐</span>
<div class="pointer" @click.stop="$router.push({
path: '/shop_street_detail',
query: {
id: item2.shop_id
}
})">
进入店铺<i class="el-icon-arrow-right"></i>
</div>
</div>
<div class="m-t-20 flex">
<div class="m-r-16" @click.stop="$router.push({
path: '/goods_details/'+item3.id
})" v-for="(item3, index3) in item2.goods_list" :key="index3">
<el-image style="width: 150px; height: 150px" :src="item3.image"
fit="fit">
</el-image>
<div class="primary flex row-center m-t-10">
¥{{item3.min_price}}
</div>
</div>
</div>
</div>
</div>
</template>
</template>
<template v-else>
<null-data :img="require('~/static/images/profit_null.png')" text="暂无收藏~"></null-data>
</template>
</div>
</el-tab-pane>
</el-tabs>
</div>
<!-- <null-data
style="padding: 150px"
img-style="width: 94px;height:118px"
:img="require('~/assets/images/img_null.png')"
text="请前往移动端进行查看"
></null-data> -->
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
data() {
return {
activeName: 0,
recodeList: {},
userCollection: [
{
type: 0,
lists: [],
name: "商品",
count: 0,
page: 1,
},
{
type: 1,
lists: [],
name: "店铺",
count: 0,
page: 1,
},
],
};
},
fetch() {
this.handleClick();
},
mounted() {
this.getRecodeList();
},
methods: {
handleClick() {
this.getRecodeList();
},
changePage(val) {
this.userCollection.some((item) => {
if (item.type == this.activeName) {
item.page = val;
}
});
this.getRecodeList();
},
async getRecodeList() {
const { activeName, userCollection } = this;
const item = userCollection.find((item) => item.type == activeName);
const {
data: { lists, count },
code,
} =
activeName == 0
? await this.$get("goods_collect/lists", {
params: {
page_size: 10,
page_no: item.page,
},
})
: await this.$get("pc/shopFollowList", {
params: {
page_size: 10,
page_no: item.page,
},
});
if (code == 1) {
this.recodeList = { lists, count };
}
},
async cancelColl(id) {
const { code, msg } =
this.activeName == 0
? await this.$post("goods_collect/changeStatus", {
goods_id: id,
})
: await this.$post("shop_follow/changeStatus", {
shop_id: id,
});
if (code == 1) {
this.$message.success("取消成功");
}
this.getRecodeList();
},
},
watch: {
recodeList: {
immediate: true,
handler(val) {
console.log("val:", val);
this.userCollection.some((item) => {
if (item.type == this.activeName) {
Object.assign(item, val);
return true;
}
});
},
},
},
};
</script>
<style lang="scss" scoped>
.user-collection-container {
width: 980px;
padding: 10px 10px 60px 10px;
::v-deep .el-tabs__header {
margin-left: 10px;
}
::v-deep .el-tabs .el-tabs__nav-scroll {
padding: 0;
}
.user-collection-content {
// margin-top: 17px;
.goods {
width: 180px;
height: 260px;
margin-right: 15px;
margin-bottom: 30px;
float: left;
&-image {
width: 180px;
height: 180px;
cursor: pointer;
position: relative;
}
&-image:hover .goods-image-wrap {
opacity: 1;
}
&-image-wrap {
left: 0;
bottom: 0;
width: 180px;
height: 26px;
padding: 8px 0;
color: #fff;
text-align: center;
position: absolute;
opacity: 0;
transition: opacity 0.2s linear;
background-color: rgba(0, 0, 0, 0.2);
> div {
width: 90px;
cursor: pointer;
}
> div:first-child {
border-right: 1px solid #fff;
}
}
}
.goods:nth-child(5n) {
margin-right: 0;
}
.goods-name {
height: 36px;
color: #101010;
}
.shop {
padding: 20px 0;
border-bottom: 1px solid #e5e5e5;
.shop-item:hover .shop-wrap {
opacity: 1;
}
.shop-item {
width: 148px;
height: 220px;
background-size: cover;
background-position: center;
padding: 10px;
border-radius: 6px;
position: relative;
.shop-wrap {
top: 0;
left: 0;
position: absolute;
width: 148px;
height: 26px;
padding: 8px 0;
color: #fff;
opacity: 0;
text-align: center;
transition: opacity 0.2s linear;
background-color: rgba(0, 0, 0, 0.2);
> div {
width: 74px;
cursor: pointer;
}
> div:first-child {
border-right: 1px solid #fff;
}
}
.shop-info {
border-radius: 6px;
padding: 18px 15px;
.logo {
width: 70px;
height: 70px;
border-radius: 50%;
margin-top: -45px;
}
}
}
}
.shop:last-child {
border-bottom: 0;
}
}
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<div class="user-coupons">
<div class="coupons-header lg">
我的优惠券
</div>
<div class="tabs">
<el-button v-for="(value,key,index) in expand" @click="changeTabs(index)" :key="key" class="button m-l-18"
:class="index==active?'active':''" type="primary">
{{coupons[index].title}}({{value}})</el-button>
<div v-for="(item2, index2) in coupons" :key="index2">
<div class="m-t-20" v-if="index2==active">
<coupons-list v-if="item2.hasData" :list="item2.list" :type="active" />
<null-data v-else :img="require('~/static/images/coupon_null.png')" text="暂无优惠券~"></null-data>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
components: {},
data() {
return {
active: 0,
expand: {
valid: 0,
used: 0,
expired: 0,
},
coupons: [
{
title: "可使用",
type: "valid",
list: [],
hasData: true,
},
{
title: "已使用",
type: "used",
list: [],
hasData: true,
},
{
title: "已过期",
type: "expired",
list: [],
hasData: true,
},
],
};
},
mounted() {
this.getMyCoupons();
},
methods: {
changeTabs(index) {
this.active = index;
this.getMyCoupons();
},
async getMyCoupons() {
let { data, code } = await this.$get("coupon/myCouponList", {
params: {
type: this.coupons[this.active].type + "",
page_size: 100,
},
});
if (code == 1) {
for (const key in this.expand) {
this.$set(this.expand, key, data.expand[key]);
}
this.changeData(data);
}
},
changeData(data) {
this.coupons.some((item, index) => {
console.log(data, index);
if (index == this.active) {
Object.assign(item, {
list: data.lists,
hasData: data.lists.length,
});
return true;
}
});
},
},
};
</script>
<style lang="scss">
.user-coupons {
width: 980px;
.coupons-header {
padding: 20px 15px;
border-bottom: 1px solid #e5e5e5;
}
.tabs {
padding: 15px 0;
.button {
width: 104px;
height: 30px;
line-height: 0px;
display: inline-block;
background: #fff;
color: #666;
border: 1px solid #e5e5e5;
}
.active {
color: #fff;
border: 0;
background: $--color-primary;
}
}
}
</style>

View File

@ -0,0 +1,240 @@
<template>
<div class="evaluate">
<div class="goods">
<div class="goods-hd lighter flex">
<div class="info flex flex-1">商品信息</div>
<div class="price flex row-center">单价</div>
<div class="num flex row-center">数量</div>
<div class="total flex row-center">合计</div>
</div>
<div class="goods-con">
<div class="goods-item flex ">
<div class="info flex flex-1">
<img class="goods-img" :src="goodsInfo.goods_item.image" alt="" />
<div class="goods-info flex flex-1">
<div class="goods-name line-2">
{{ goodsInfo.name }}
</div>
<div class="sm lighter m-t-8">{{goodsInfo.spec_value_str}}</div>
</div>
</div>
<div class="price flex row-center">
<price-formate :price="goodsInfo.goods_price" weight="400" />
</div>
<div class="num flex row-center">{{ goodsInfo.goods_num }}</div>
<div class="total flex row-center">
<price-formate :price="goodsInfo.total_price" weight="400" />
</div>
</div>
</div>
</div>
<div class="evaluate-con">
<div class="goods-rate">
<div class="flex item">
<div class="name">商品评价</div>
<el-rate v-model="goodsRate" show-text text-color="#FF9E2C" :texts="goodsTexts"></el-rate>
</div>
<div class="flex item">
<div class="name">描述相符</div>
<el-rate v-model="descRate"></el-rate>
</div>
<div class="flex item">
<div class="name">服务态度</div>
<el-rate v-model="serverRate"></el-rate>
</div>
<div class="flex item">
<div class="name">配送服务</div>
<el-rate v-model="deliveryRate"></el-rate>
</div>
</div>
<div class="evaluate-input flex">
<div class="name">商品评价</div>
<div>
<el-input type="textarea" placeholder="收到商品您有什么想法或者反馈,用几个字来评价下商品吧~" v-model="comment"
maxlength="150" :rows="6" show-word-limit resize="none">
</el-input>
<div class="upload m-t-16">
<upload :limit="9" @success="onSuccess" />
<div class="muted m-t-8">
最多可上传9张图片支持jpgpng格式图片大小1M以内
</div>
</div>
<div class="submit-btn white bg-primary m-t-16 flex row-center" @click="onSubmit">
提交评价
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
}, ],
};
},
async asyncData({
$get,
query
}) {
const id = query.id;
let {
data
} = await $get("goods_comment/getCommentPage", {
params: {
order_goods_id: id,
},
});
return {
goodsInfo: data,
id,
};
},
layout: "user",
data() {
return {
goodsInfo: {},
goodsRate: 0,
descRate: 0,
serverRate: 0,
deliveryRate: 0,
comment: "",
fileList: [],
goodsTexts: ["差评", "差评", "中评", "好评", "好评"],
};
},
methods: {
onSuccess(res) {
console.log('res', res)
this.fileList = res.map((item) => item.response.data);
console.log('fileList', this.fileList)
},
onSubmit() {
let {
goodsRate,
fileList,
comment,
deliveryRate,
descRate,
serverRate,
} = this;
let image = fileList.map((item) => item.uri);
if (!goodsRate)
return this.$message({
message: "请对商品进行评分",
type: "error",
});
if (!descRate)
return this.$message({
message: "请对描述相符进行评分",
type: "error",
});
if (!serverRate)
return this.$message({
message: "请对服务态度进行评分",
type: "error",
});
if (!deliveryRate)
return this.$message({
message: "请对配送服务进行评分",
type: "error",
});
this.$post("goods_comment/addGoodsComment", {
id: parseInt(this.id),
goods_comment: goodsRate,
service_comment: serverRate,
express_comment: deliveryRate,
description_comment: descRate,
comment,
image,
order_goods_id: this.$route.query.id
}).then((res) => {
if (res.code == 1) {
this.$message({
message: "评价成功",
type: "success",
});
setTimeout(() => {
this.$router.replace({
path: "/user/evaluation",
// query: {
// type: 2,
// },
});
}, 1500);
}
});
},
},
};
</script>
<style lang="scss" scoped>
.evaluate {
width: 1010px;
padding: 0 10px;
.goods {
.goods-hd,
.goods-con {
padding: 10px 20px;
border-bottom: 1px solid #e5e5e5;
.goods-item {
padding: 10px 0;
}
}
.info {
.goods-img {
width: 72px;
height: 72px;
margin-right: 10px;
}
}
.price,
.num,
.total {
width: 150px;
}
}
.evaluate-con {
padding: 20px;
.goods-rate {
.item {
margin-bottom: 18px;
}
}
.name {
margin-right: 24px;
flex: none;
}
.evaluate-input {
align-items: flex-start;
.el-textarea {
width: 630px;
}
.submit-btn {
width: 100px;
height: 32px;
cursor: pointer;
}
}
}
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<div class="user-evaluate">
<el-tabs v-model="type" @tab-click="handleClick">
<el-tab-pane v-for="(item, index) in evaluate" :key="index" :label="item.name" :name="item.type">
<template v-if="item.lists.length">
<evaluation-list :list="item.lists" :type="item.type" :userInfo="userInfo"/>
<div class="pagination flex row-center" v-if="item.count">
<el-pagination hide-on-single-page background layout="prev, pager, next" :total="item.count"
prev-text="上一页" next-text="下一页" :page-size="10" @current-change="changePage">
</el-pagination>
</div>
</template>
<null-data v-else :img="require('~/static/images/news_null.png')" text="暂无评价~"></null-data>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
}, ],
};
},
layout: "user",
watchQuery: true,
async asyncData({
$get,
query
}) {
const type = query.type || "1";
let {
data: {
lists,
count
}
} = await $get("goods_comment/getUnCommentOrder", { //
params: {
page_size: 10
},
});
let {
data: userInfo
} = await $get("user/info"); //
return {
commentList: {
lists,
count
},
type,
userInfo,
};
},
components: {},
data() {
return {
evaluate: [{
type: "1",
lists: [],
name: "待评价",
count: 0,
page: 1,
},
{
type: "2",
lists: [],
name: "已评价",
count: 0,
page: 1,
},
],
};
},
methods: {
handleClick() {
this.getEvaluateList();
},
async getEvaluateList() {
const {
type,
evaluate
} = this;
const item = evaluate.find((item) => item.type == type);
const {
data: {
lists,
count
},
code,
} = type == 1 ? await this.$get("goods_comment/getUnCommentOrder", { //
params: {
page_size: 10,
page_no: item.page,
},
}) : await this.$get("goods_comment/getCommentOrder", { //
params: {
page_size: 10,
page_no: item.page,
},
});
if (code == 1) {
this.commentList = {
lists,
count
};
}
},
changePage(val) {
this.evaluate.some((item) => {
if (item.type == this.type) {
item.page = val;
}
});
this.getEvaluateList();
},
},
watch: {
commentList: {
immediate: true,
handler(val) {
this.evaluate.some((item) => {
if (item.type == this.type) {
Object.assign(item, val);
console.log(item);
return true;
}
});
},
},
}
};
</script>
<style lang="scss" scoped>
.user-evaluate {
width: 1000px;
padding: 20px 0;
}
</style>

View File

@ -0,0 +1,453 @@
<template>
<div class="order-detail">
<div class="detail-hd row-between">
<div class="lg">订单详情</div>
<div :class="[
'status lg',
{ primary: orderDetail.order_status == 0 },
]">
{{ orderDetail.order_status_desc }}
</div>
</div>
<div class="address">
<div class="address-item">
<div class="lighter address-item-label">收件人</div>
<div>{{ orderDetail.consignee }}</div>
</div>
<div class="address-item">
<div class="lighter address-item-label">联系方式</div>
<div>{{ orderDetail.mobile }}</div>
</div>
<div class="address-item">
<div class="lighter address-item-label">收货地址</div>
<div>{{ orderDetail.delivery_address }}</div>
</div>
</div>
<div class="detail-con">
<div class="title flex">
<nuxt-link class="flex-1 lighter sm line-1 m-r-20" style="min-width: 0"
:to="`/shop_street_detail?id=${orderDetail.shop.id}`">
{{ orderDetail.shop.name }}
</nuxt-link>
<div class="flex-1 lighter sm">
下单时间{{ orderDetail.create_time }}
</div>
<div class="flex-1 lighter sm">
订单编号{{ orderDetail.order_sn }}
</div>
<div :class="[
'status sm',
{ primary: orderDetail.order_status == 0 },
]">
{{ getOrderStatus(orderDetail.order_status) }}
</div>
</div>
<div class="goods">
<div class="goods-hd lighter flex">
<div class="info flex-1">商品信息</div>
<div class="price flex row-center">商品价格</div>
<div class="num flex row-center">数量</div>
<div class="total flex row-center">合计</div>
</div>
<div class="goods-list">
<div class="goods-item flex" v-for="(item, index) in orderDetail.order_goods" :key="index">
<nuxt-link :to="`/goods_details/${item.goods_id}`" class="info flex flex-1">
<el-image class="goods-img" :src="item.image" alt="" />
<div class="goods-info flex-1">
<div class="goods-name line-2">
<el-tag size="mini" effect="plain" v-if="item.is_seckill"></el-tag>
{{ item.goods_name }}
</div>
<div class="sm lighter m-t-8">
{{ item.spec_value }}
</div>
</div>
</nuxt-link>
<div class="price">
<price-formate :price="item.goods_price" />
</div>
<div class="num flex row-center">{{ item.goods_num }}</div>
<div class="total flex row-center">
<price-formate :price="item.sum_price" />
</div>
</div>
</div>
</div>
<div class="m-t-16" v-if="orderDetail.user_remark">
<span class="lighter m-r-8">买家留言</span>
<span>{{ orderDetail.user_remark }}</span>
</div>
<div class="m-t-16" v-if="orderDetail.delivery_content">
<span class="lighter m-r-8">发货内容</span>
<span>{{ orderDetail.delivery_content }}</span>
</div>
</div>
<div class="detail-footer flex">
<div>
<div class="flex-col" style="align-items: flex-end">
<div class="money flex m-b-8">
<div class="lighter">商品总价</div>
<div>
<price-formate :price="orderDetail.goods_price" />
</div>
</div>
<div class="money flex m-b-8">
<div class="lighter">运费</div>
<div>
<price-formate :price="orderDetail.shipping_price" />
</div>
</div>
<div class="money flex m-b-8">
<div class="lighter">会员抵扣</div>
<div class="primary">
-<price-formate :price="orderDetail.member_amount" color="#FF0808" />
</div>
</div>
<div class="money flex m-b-16" v-if="orderDetail.discount_amount != 0">
<div class="lighter">优惠券</div>
<div>
-
<price-formate :price="orderDetail.discount_amount" />
</div>
</div>
<div class="money flex">
<div class="lighter">实付金额</div>
<div class="primary">
<price-formate :price="orderDetail.order_amount" :subscript-size="14" :first-size="28"
:second-size="28" />
</div>
</div>
</div>
<div class="oprate-btn flex row-right m-t-16">
<div class="btn plain flex row-center lighter" v-if="orderDetail.cancel_btn"
@click="handleOrder(0)">
取消订单
</div>
<div class="btn plain flex row-center m-l-8 lighter" v-if="orderDetail.delivery_btn"
@click="showDeliverPop = true">
物流查询
</div>
<div class="btn bg-primary flex row-center white m-l-8" v-if="orderDetail.take_btn"
@click="handleOrder(2)">
确认收货
</div>
<div class="btn plain flex row-center lighter m-l-8" v-if="orderDetail.del_btn"
@click="handleOrder(1)">
删除订单
</div>
<nuxt-link :to="`/payment?id=${orderDetail.id}&from=order`"
class="btn bg-primary flex row-center white m-l-8" v-if="orderDetail.pay_btn">
<span class="mr8">去付款</span>
<count-down v-if="
getCancelTime(orderDetail.order_cancel_time) > 0
" :time="getCancelTime(orderDetail.order_cancel_time)" format="hh:mm:ss"
@finish="getOrderDetail" />
</nuxt-link>
</div>
</div>
</div>
<div class="detail-upload" v-if="orderDetail.frontend_array.length > 0">
<div class="tit">上传合同列表</div>
<div class="img-boxs">
<div class="img" v-for="(item, index) in orderDetail.frontend_array" :key="index">
<el-image
style="width: 100%; height: 100%"
:src="baseUrl + item"
:preview-src-list="frontend_arrayNew"
>
</el-image>
</div>
</div>
</div>
<deliver-search v-model="showDeliverPop" :aid="id" />
</div>
</template>
<script>
import { copyClipboard } from '@/utils/tools'
import config from "~/config/app";
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
layout: 'user',
async asyncData({ $get, query }) {
const { data, code } = await $get('order/getOrderDetail', {
params: {
id: query.id,
},
})
if (code == 1) {
return {
orderDetail: data,
id: query.id,
}
}
},
data() {
return {
orderDetail: {},
showDeliverPop: false,
baseUrl:config.baseUrl + '/',
frontend_arrayNew:[], //
}
},
mounted() {
if (this.orderDetail.delivery_type === 2) {
this.creatQrCode(this.orderDetail.pickup_code)
}
if(this.orderDetail.frontend_array) {
this.frontend_arrayNew = this.orderDetail.frontend_array.map(item => {
return this.baseUrl + item
})
}
},
methods: {
async getOrderDetail() {
const { data, code } = await this.$get('order/getOrderDetail', {
params: {
id: this.id,
},
})
if (code == 1) {
this.orderDetail = data
}
},
handleOrder(type) {
this.type = type
this.$confirm(this.getTipsText(type), {
title: '温馨提示',
center: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
width: '300px',
callback: (action) => {
if (action == 'confirm') {
this.postOrder()
}
},
})
},
async postOrder() {
const { type, id } = this
let url = ''
switch (type) {
case 0:
url = 'order/cancel'
break
case 1:
url = 'order/del'
break
case 2:
url = 'order/confirm'
break
}
let { code, data, msg } = await this.$post(url, { id })
if (code == 1) {
this.$message({
message: msg,
type: 'success',
})
if (type == 1) {
setTimeout(() => {
this.$router.go(-1)
}, 1500)
} else {
this.getOrderDetail()
}
}
},
getTipsText(type) {
switch (type) {
case 0:
return '确认取消订单吗?'
case 1:
return '确认删除订单吗?'
case 2:
return '确认收货吗?'
}
},
},
computed: {
getOrderStatus() {
return (status) => {
let text = ''
switch (status) {
case 0:
text = '待支付'
break
case 1:
text = '待发货'
break
case 2:
text = '待收货'
break
case 3:
text = '已完成'
break
case 4:
text = '订单已关闭'
break
}
return text
}
},
getCancelTime() {
return (time) => time - Date.now() / 1000
},
},
}
</script>
<style lang="scss" scoped>
.order-detail {
padding: 0 16px 20px;
.detail-hd {
padding: 14px 5px;
border-bottom: 1px solid #e5e5e5;
}
.address {
padding: 16px 0;
>div {
margin-bottom: 10px;
}
&-item {
display: flex;
&-label {
width: 70px;
text-align: justify;
text-align-last: justify;
}
}
}
.detail-con {
.title {
height: 40px;
background: #f2f2f2;
border: 1px solid #e5e5e5;
padding: 0 20px;
}
.goods {
.goods-hd,
.goods-list {
padding: 10px 20px;
border: 1px solid #e5e5e5;
border-top-width: 0;
.goods-item {
padding: 10px 0;
.goods-name {
line-height: 1.5;
}
}
}
.info {
.goods-img {
width: 72px;
height: 72px;
margin-right: 10px;
}
}
.price,
.num,
.total {
width: 150px;
}
}
}
.detail-footer {
padding: 25px 20px;
justify-content: flex-end;
.money {
>div {
text-align: right;
&:first-of-type {
width: 80px;
}
&:last-of-type {
width: 120px;
display: flex;
justify-content: flex-end;
}
}
}
.oprate-btn {
.btn {
width: 152px;
height: 44px;
cursor: pointer;
border-radius: 2px;
&.plain {
border: $--border-base;
}
}
}
}
.qr-container {
width: 120px;
height: 120px;
padding: 6px;
border: $--border-base;
border-radius: 6px;
}
}
.detail-upload {
.tit {
font-size: 20px;
color: #333;
font-weight: bold;
line-height: 1;
margin-bottom: 20px;
border-left: 4px solid #f00;
padding-left: 14px;
}
.img-boxs {
display: flex;
align-items: center;
flex-wrap: wrap;
.img {
width: 150px;
height: 150px;
margin-top: 10px;
margin-right: 15px;
border: 1px solid #ededed;
}
}
}
</style>

View File

@ -0,0 +1,184 @@
<template>
<div class="user-order">
<div class="download-box">
<a target="_blank" :href="download_contract.domain + '/' + download_contract.path"><el-button type="success" icon="el-icon-download" size="medium">下载合同</el-button></a>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane
v-for="(item, index) in order"
:key="index"
:label="item.name"
:name="item.type"
>
<template v-if="item.list.length">
<order-list :list="item.list" @refresh="getOrderList" />
<div class="pagination flex row-center" v-if="item.count">
<el-pagination
hide-on-single-page
background
layout="prev, pager, next"
:total="item.count"
prev-text="上一页"
next-text="下一页"
:page-size="10"
@current-change="changePage"
>
</el-pagination>
</div>
</template>
<null-data
v-else
:img="require('~/static/images/order_null.png')"
text="暂无订单~"
></null-data>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import { Message } from 'element-ui';
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
layout: 'user',
async asyncData({query, $get, $post }) {
let that = this;
let download_contract = {};
const {
data: { list, count },
code,
} = await $get('order/lists', {
params: {
page_size: 10,
},
})
await $post('order/contractDownload', {}).then(({ code, data, msg }) => {
if (code == 1) {
download_contract = data;
}
})
if(query.is_frontend == 1) {
Message.success('订单前置成功')
}
if (code == 1) {
return {
orderList: { list, count },
download_contract
}
}
},
components: {},
data() {
return {
activeName: 'all',
order: [
{
type: 'all',
list: [],
name: '全部',
count: 0,
page: 1,
},
{
type: 'pay',
list: [],
name: '待付款',
count: 0,
page: 1,
},
{
type: 'delivery',
list: [],
name: '待收货',
count: 0,
page: 1,
},
{
type: 'finish',
list: [],
name: '已完成',
count: 0,
page: 1,
},
{
type: 'close',
list: [],
name: '已关闭',
count: 0,
page: 1,
},
],
download_contract:{} //
}
},
methods: {
handleClick() {
this.getOrderList()
},
async getOrderList() {
const { activeName, order } = this
const item = order.find((item) => item.type == activeName)
const {
data: { list, count },
code,
} = await this.$get('order/lists', {
params: {
page_size: 10,
page_no: item.page,
type: activeName,
},
})
if (code == 1) {
this.orderList = { list, count }
}
},
changePage(val) {
this.order.some((item) => {
if (item.type == this.activeName) {
item.page = val
}
})
this.getOrderList()
},
},
watch: {
orderList: {
immediate: true,
handler(val) {
this.order.some((item) => {
if (item.type == this.activeName) {
Object.assign(item, val)
console.log(item)
return true
}
})
},
},
},
}
</script>
<style lang="scss">
.user-order {
padding: 20px 0;
position: relative;
}
.download-box {
position: absolute;
right: 16px;
top: 22px;
z-index: 999;
}
</style>

View File

@ -0,0 +1,426 @@
<template>
<div class="user-profile">
<div class="user-header lg">
个人资料
</div>
<div class="user-container">
<div class="user-form-item flex">
<label class="user-form-label nr">头像</label>
<div class="user-avatar-upload">
<el-upload class="avatar-uploader" :action="action" :show-file-list="false" :file-list="fileList"
:on-success="uploadFileSuccess" :headers="{token: $store.state.token}"
accept="image/jpg,image/jpeg,image/png"
:before-upload="beforeAvatarUpload">
<div class="avatar">
<el-image style="width: 64px;height: 64px;border-radius: 60px" :src="avatar" />
<div class="mask white"></div>
</div>
</el-upload>
</div>
</div>
<div class="user-form-item flex">
<label class="user-form-label nr">用户ID</label>
<div class="normal nr">{{sn}}</div>
</div>
<div class="user-form-item flex">
<label class="user-form-label nr">昵称</label>
<el-input v-model="nickName" class="user-input" suffix-icon="el-icon-edit" />
</div>
<div class="user-form-item flex">
<label class="user-form-label nr">性别</label>
<el-radio-group v-model="radio">
<el-radio :label="'男'"></el-radio>
<el-radio :label="'女'"></el-radio>
<!-- <el-radio :label="3">保密</el-radio> -->
</el-radio-group>
</div>
<div class="user-form-item flex">
<label class="user-form-label nr">手机号</label>
<div class="normal nr">{{mobile}}</div>
<div style="color: #6699CC;margin-left: 13px;cursor: pointer;" @click="openChangeNumber">
{{mobile?'修改号码':'绑定手机号'}}</div>
</div>
<div class="user-form-item flex">
<label class="user-form-label nr">注册时间</label>
<div class="normal nr">{{createTime}}</div>
</div>
<div class="user-form-item flex">
<label class="user-form-label nr">登录密码</label>
<div class="nr" style="color: #6699CC;cursor: pointer;" @click="openChangePwdPop"></div>
</div>
<div class="user-form-item flex">
<label class="user-form-label nr">我的团队</label>
<div class="normal nr flex">
<div class="name">团队名称<span class="primary">{{team_info.name}}</span></div>
<div class="phone m-l-30">联系电话<span class="primary">{{team_info.phone}}</span></div>
</div>
</div>
<button class="primary-btn bg-primary flex-center white" @click="saveUserInfo">
保存
</button>
</div>
<!-- 修改手机号 -->
<el-dialog :center="true" :title="mobile ? '更换手机号': '绑定手机'" :visible.sync="showChangeNumber" width="40%">
<div>
<el-form style="width: 50%;margin: 0 auto">
<el-form-item>
<el-input v-model="telephone" placeholder="请输入新的手机号码" />
</el-form-item>
<el-form-item>
<div class="flex">
<el-input v-model="verifyCode" placeholder="短信验证码" />
<el-button style="margin-left: 14px;" @click="sndSmsToPhone">
<div v-if="canSendNumber"></div>
<count-down v-else :time="60" format="ss秒" autoStart @finish="canSendNumber = true" />
</el-button>
</div>
</el-form-item>
</el-form>
</div>
<div slot="footer">
<el-button style="width:134px" type="primary" @click="changeUserMobile"></el-button>
<el-button style="width:134px" @click="closeChangeNumber"></el-button>
</div>
</el-dialog>
<!-- 登录密码设置 -->
<el-dialog title="设置登录密码" :center="true" :visible.sync="showPwdPop" width="40%">
<div>
<el-form style="width: 50%;margin: 0 auto;">
<el-form-item>
<el-input v-model="mobile" placeholder="请输入手机号码" />
</el-form-item>
<el-form-item>
<div class="flex">
<el-input v-model="verifyCode" placeholder="短信验证码" />
<el-button style="margin-left: 14px;" @click="sndSmsToPhone">
<div v-if="canSendPwd"></div>
<count-down v-else :time="60" format="ss秒" autoStart @finish="canSendPwd = true" />
</el-button>
</div>
</el-form-item>
<el-form-item>
<el-input v-model="pwd" type="password" placeholder="请输入密码 (数字与字母自由组合)" />
</el-form-item>
<el-form-item>
<el-input v-model="againPwd" type="password" placeholder="再次输入密码" />
</el-form-item>
</el-form>
</div>
<div slot="footer">
<el-button style="width:134px" type="primary" @click="setPassWord"></el-button>
<el-button style="width:134px" @click="closePwdPop"></el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { SMSType, client, FieldType } from "~/utils/type";
import Cookies from "js-cookie";
import { mapActions } from "vuex";
import config from "~/config/app";
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
mounted() {
this.getUserInfoFun();
},
data() {
return {
avatar: "",
mobile: "",
sex: 0,
createTime: "",
sn: "",
action: config.baseUrl + "/api/file/formimage",
nickName: "",
radio: 1,
showChangeNumber: false,
showPwdPop: false,
telephone: "",
verifyCode: "",
pwd: "",
againPwd: "",
smsType: SMSType.CHANGE_MOBILE,
canSendNumber: true,
canSendPwd: true,
fileList: [],
team_info:{} //
};
},
methods: {
beforeAvatarUpload(file) {
var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
console.log('fdsadsf')
const extension = testmsg === 'jpg'
const extension2 = testmsg === 'png'
const extension4 = testmsg === 'jpeg'
if (!extension && !extension2) {
this.$message({
message: '上传文件只能是 jpg, jpeg, png格式!',
type: 'warning'
})
return false
}
return extension || extension2 || extension4
},
...mapActions(["getPublicData"]),
async getUserInfoFun() {
let res = await this.$get("user/info");
if (res.code == 1) {
this.avatar = res.data.avatar;
this.nickName = res.data.nickname;
this.mobile = res.data.mobile;
this.sex = res.data.sex;
this.radio = this.sex;
this.createTime = res.data.create_time;
this.sn = res.data.sn;
}
let resData = await this.$get("user/center");
if (resData.code == 1) {
this.team_info = resData.data.team_info;
}
},
async saveUserInfo() {
let res = await this.$post("pc/changeUserInfo", {
sex: this.radio == "男" ? 1 : 2,
nickname: this.nickName,
});
if (res.code == 1) {
this.$message({
message: res.msg,
type: "success",
});
this.getPublicData();
}
},
closeChangeNumber() {
this.telephone = "";
this.verifyCode = "";
this.showChangeNumber = false;
},
closePwdPop() {
this.telephone = "";
this.verifyCode = "";
this.showPwdPop = false;
},
//
openChangeNumber() {
this.showChangeNumber = true;
this.smsType = this.mobile ? SMSType.CHANGE_MOBILE : SMSType.BIND;
},
//
openChangePwdPop() {
if (this.mobile == "") return this.$message.error("请先绑定手机号");
this.showPwdPop = true;
this.smsType = SMSType.FINDPWD;
},
//
async sndSmsToPhone() {
if (
(this.smsType == SMSType.CHANGE_MOBILE ||
this.smsType == SMSType.BIND) &&
!this.canSendNumber
)
return;
else if (this.smsType == SMSType.FINDPWD && !this.canSendPwd)
return;
if (this.smsType == SMSType.CHANGE_MOBILE && !this.telephone)
return this.$message.error("请输入手机号");
let res = await this.$post("sms/send", {
mobile:
this.smsType == SMSType.FINDPWD
? this.mobile
: this.telephone,
key: this.smsType,
});
if (res.code == 1) {
this.smsType == SMSType.FINDPWD
? (this.canSendPwd = false)
: (this.canSendNumber = false);
this.$message.success("发送成功");
}
},
//
async changeUserMobile() {
if (!this.telephone)
return this.$message.error("请输入新的手机号码");
if (!this.verifyCode) return this.$message.error("请输入验证码");
let res = await this.$post("user/changeMobile", {
mobile: this.mobile,
new_mobile: this.telephone,
code: this.verifyCode,
action: this.mobile ? "change" : "",
client: client,
});
if (res.code == 1) {
this.showChangeNumber = false;
this.$message.success(res.msg);
this.getPublicData();
this.getUserInfoFun();
}
},
//
async setPassWord() {
if (!this.verifyCode) return this.$message.error("请输入验证码");
if (!this.pwd) return this.$message.error("请输入密码");
if (!this.againPwd) return this.$message.error("请输入确认密码");
if (this.pwd != this.againPwd)
return this.$message.error("两次密码输入不一致");
let res = await this.$post("login_password/forget", {
mobile: this.mobile,
code: this.verifyCode,
password: this.pwd,
repassword: this.againPwd,
client: client,
});
if (res.code == 1) {
this.$message({
message: res.msg,
type: "success",
});
this.showPwdPop = false;
const token = res.data.token;
Cookies.set("token", token, { expires: 60 });
}
},
async uploadFileSuccess(res, fileList) {
let respond = await this.$post("user/setInfo", {
field: FieldType.AVATAR,
value: res.data.uri,
});
if (respond.code == 1) {
this.$message({
message: respond.msg,
type: "success",
});
let userRes = await this.$get("user/info");
if (userRes.code == 1) {
this.avatar = userRes.data.avatar;
this.nickName = userRes.data.nickname;
this.mobile = userRes.data.mobile;
this.sex = userRes.data.sex;
this.radio = this.sex;
this.createTime = userRes.data.create_time;
}
}
},
},
};
</script>
<style lang="scss">
.user-profile {
width: 980px;
padding: 10px;
.user-header {
padding: 10px 5px;
border-bottom: 1px solid #e5e5e5;
}
.user-container {
margin-top: 35px;
.user-form-item {
padding-left: 13px;
margin-top: 24px;
.user-form-label {
width: 60px;
text-align: left;
margin-right: 24px;
}
.user-avatar-upload {
.avatar-uploader {
&:hover {
.avatar {
.mask {
display: flex;
}
&::after {
opacity: 1;
}
}
}
.avatar {
position: relative;
.mask {
display: none;
position: absolute;
}
&::after {
content: "更换头像";
position: absolute;
transition: opacity 0.3s ease;
opacity: 0;
width: 100%;
height: 64px;
left: 0;
top: 0;
border-radius: 60px;
background-color: rgba(
$color: #000000,
$alpha: 0.3
);
color: white;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 12px;
}
}
}
}
.user-input {
width: 240px;
}
.el-radio__input.is-checked + .el-radio__label {
color: #007aff;
}
.el-input__inner:focus {
border-color: #007aff;
}
.el-radio__input.is-checked .el-radio__inner {
border-color: #007aff;
background: #007aff;
}
.el-radio__inner:hover {
border-color: #007aff;
}
}
.primary-btn {
height: 32px;
width: 100px;
margin-top: 32px;
border: none;
border-radius: 4px;
cursor: pointer;
&:focus {
border: none;
outline: none;
}
}
}
}
</style>

View File

@ -0,0 +1,211 @@
<template>
<div class="user-wallet-container">
<div class="user-wallet-header lg">
我的钱包
</div>
<div class="user-wallet-content">
<div class="wallet-info-box flex">
<div class="user-wallet-info">
<div class="xs title">我的余额</div>
<div class="nr white flex" style="font-weight: 500;align-items: baseline;">¥<label
style="font-size: 24px;">{{wallet.user_money || 0}}</label></div>
</div>
<div class="user-wallet-info" style="margin-left: 144px">
<div class="xs title">累计消费</div>
<div class="nr white flex" style="font-weight: 500;align-items: baseline;">¥<label
style="font-size: 24px;">{{wallet.total_order_amount || 0}}</label></div>
</div>
</div>
<el-tabs v-model="activeName" class="mt10" @tab-click="handleClick">
<el-tab-pane v-for="(item, index) in userWallet" :label="item.name" :name="item.type" :key="index">
<div class="user-wallet-table">
<el-table :data="item.list" style="width: 100%">
<el-table-column prop="source_type" label="类型" />
<el-table-column prop="change_amount" label="金额">
<div slot-scope="scope" :class="{'primary': scope.row.change_type == 1}">
{{scope.row.change_amount}}
</div>
</el-table-column>
<el-table-column prop="create_time" label="时间" />
</el-table>
</div>
</el-tab-pane>
</el-tabs>
</div>
<!-- <null-data
style="padding: 150px"
img-style="width: 94px;height:118px"
:img="require('~/assets/images/img_null.png')"
text="请前往移动端进行查看"
></null-data> -->
</div>
</template>
<script>
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: "icon",
type: "image/x-icon",
href: this.$store.getters.favicon,
},
],
};
},
layout: "user",
data() {
return {
activeName: "all",
userWallet: [
{
type: "all",
list: [],
name: "全部记录",
count: 0,
page: 1,
},
{
type: "output",
list: [],
name: "收入记录",
count: 0,
page: 1,
},
{
type: "income",
list: [],
name: "消费记录",
count: 0,
page: 1,
},
],
};
},
async asyncData({ $get, query }) {
let wallet = {};
let recodeList = [];
let walletRes = await $get("user/myWallet");
let recodeRes = await $get("user/accountLog", {
params: {
page_no: 1,
page_size: 10,
source: 1,
type: 0,
},
});
if (walletRes.code == 1) {
wallet = walletRes.data;
}
if (recodeRes.code == 1) {
recodeList = recodeRes.data.list;
}
return {
wallet,
recodeList,
};
},
fetch() {
this.handleClick();
},
methods: {
handleClick() {
this.getRecodeList();
},
changePage(val) {
this.userWallet.some((item) => {
if (item.type == this.activeName) {
item.page = val;
}
});
this.getRecodeList();
},
async getRecodeList() {
const { activeName, userWallet } = this;
let type = activeName == "all" ? 0 : activeName == "income" ? 2 : 1;
const item = userWallet.find((item) => item.type == activeName);
const {
data: { list, count },
code,
} = await this.$get("user/accountLog", {
params: {
page_size: 10,
page_no: item.page,
type: type,
source: 1,
},
});
if (code == 1) {
this.recodeList = { list, count };
}
},
},
watch: {
recodeList: {
immediate: true,
handler(val) {
console.log("val:", val);
this.userWallet.some((item) => {
if (item.type == this.activeName) {
Object.assign(item, val);
return true;
}
});
},
},
},
};
</script>
<style lang="scss" scoped>
.user-wallet-container {
width: 980px;
padding: 10px 10px 60px 10px;
.user-wallet-header {
padding: 10px 5px;
border-bottom: 1px solid #e5e5e5;
}
::v-deep .el-tabs__header {
margin-left: 5px;
}
::v-deep .el-tabs .el-tabs__nav-scroll {
padding: 0;
}
.user-wallet-content {
margin-top: 17px;
.wallet-info-box {
padding: 24px;
background: linear-gradient(87deg, #ff2c3c 0%, #ff9e2c 100%);
.user-wallet-info {
.title {
color: #ffdcd7;
margin-bottom: 8px;
}
}
}
}
.user-wallet-table {
background-color: #f2f2f2;
::v-deep .el-table {
color: #222;
}
::v-deep .el-table .el-button--text {
color: #222;
font-weight: 400;
}
::v-deep .el-table th {
background-color: #f2f2f2;
}
::v-deep .el-table thead {
color: #555555;
font-weight: 400;
}
}
}
</style>

View File

@ -0,0 +1,35 @@
import { Message } from 'element-ui';
import config from '~/config/app'
export default function ({ $axios, redirect, store }, inject) {
$axios.setBaseURL(config.baseUrl + '/api')
$axios.onRequest(config => {
config.headers.token = store.state.token
})
$axios.onResponse((response) => {
const {
code,
show,
msg
} = response.data;
console.log(response.data)
if (code == 0 && show && msg) {
Message({
message: msg,
type: 'error'
})
}else if(code == -1){
store.commit('logout')
redirect('/account/login')
}
})
$axios.onError(error => {
Message({
message: '系统错误',
type: 'error'
})
})
inject('get', $axios.$get)
inject('post', $axios.$post)
}

View File

@ -0,0 +1,5 @@
import Vue from 'vue'
import Element from 'element-ui'
import locale from 'element-ui/lib/locale/lang/zh-CN'
Vue.use(Element, { locale })

View File

@ -0,0 +1,8 @@
import Cookies from 'js-cookie'
export default function ({ store }) {
const token = Cookies.get('token')
token && store.commit('setToken', token)
store.dispatch('getCategory')
store.dispatch('getPublicData')
store.dispatch('getConfig')
}

View File

@ -0,0 +1,3 @@
import Vue from 'vue'
import VueAwesomeSwiper from 'vue-awesome-swiper'
Vue.use(VueAwesomeSwiper)

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Some files were not shown because too many files have changed in this diff Show More