初始项目

This commit is contained in:
liupopo
2023-02-11 12:55:02 +08:00
parent 1748bda84a
commit 0b89e36064
3363 changed files with 506201 additions and 1 deletions

View File

@@ -0,0 +1,26 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": [
"transform-runtime",
["component", [
{
"libraryName": "element-ui",
"styleLibraryName": "theme-default"
}
]]
],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["istanbul"]
}
}
}

View File

@@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@@ -0,0 +1,2 @@
build/*.js
config/*.js

23
mallplusui-web-pc/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
# Maven #
target/
# IDEA #
.idea/
*.iml
*.zip
# Eclipse #
.settings/
.classpath
.project
mall-admin-web
mall-front-vue/
wechatapp
Mall-Vue-master/
mall-admin-web/src
vue-h5-mall
*.js
# Node.js
node_modules/
.idea/

View File

@@ -0,0 +1,95 @@
## mallcloud-Front
### 基于Vue开发的mallcloud商城前台页面
### [宣传视频](https://www.bilibili.com/video/av23121122/)
- 作者亲自制作 [点我观看](https://www.bilibili.com/video/av23121122/)
### 项目已部署在线Demo
- 前台商城http://xmall.Mallcloud.cn/
- 后台管理系统http://xmadmin.Mallcloud.cn/
### 感谢 [yucccc](https://github.com/yucccc) 的开源 [vue-mall](https://github.com/yucccc/vue-mall) 项目提供前端页面及框架支持
### 后端全部重新开发接口,实现后台系统管理,后端接口项目请跳转至 [xmall](https://github.com/Mallcloud/xmall) 项目仓库查看
### 新增与优化
- [x] 优化页脚、增加商品搜索框组件
- [x] 优化登录注册界面
- [x] 新增搜索页面,实现高亮分页搜索
- [x] 新增捐赠页面,捐赠列表显示
- [x] 全部商品页面实现分页
- [x] 优化订单详情,实现查看订单进度,可对订单进行处理
- [x] 实现生成订单接口、优化地址管理编辑选择
- [x] 实现查看个人订单分页
- [x] 接入[XPay个人免签收款支付系统](https://github.com/Mallcloud/xpay)
- [x] 首页升级重构首页后台可配置包括3D轮播图
- [x] 新增分类查看品牌周边等
![](https://i.loli.net/2018/07/21/5b52e192366a0.jpg "首页")
![](https://i.loli.net/2018/07/22/5b5447c0f2b69.jpg "页脚")
![](https://i.loli.net/2018/07/22/5b5447e84edd9.jpg "搜索框组件")
![](https://i.loli.net/2018/07/22/5b5448040ff95.jpg "搜索结果")
![](https://i.loli.net/2018/07/22/5b54489e41551.jpg "分页")
![](https://i.loli.net/2018/07/22/5b54482cca360.jpg "订单详情")
![](https://i.loli.net/2018/07/22/5b5448494d6b6.jpg "订单进度")
![](https://i.loli.net/2018/07/22/5b54486109ade.jpg "登录界面")
### 所用技术
- Vue 2.x
- Vuex
- Vue Router
- [Element UI](http://element.eleme.io/#/zh-CN)
- ES6
- webpack
- axios
- Node.js
- 第三方SDK
- [极验Test-button人机验证码](http://www.geetest.com/Test-button.html)
- 第三方插件
- [hotjar](https://github.com/Mallcloud/xmall/blob/master/study/hotjar.md):一体化分析和反馈
- ~~[搜狐畅言评论插件](http://changyan.kuaizhan.com/)~~ 垃圾广告评论插件 现已更换 [Gitment](https://github.com/imsun/gitment)
### 本地开发运行
- 启动后端 [xmall](https://github.com/Mallcloud/xmall) 项目后,在 `config/index.js` 中修改你的后端接口地址配置
- Gitment评论配置见 [Gitment](https://github.com/imsun/gitment) 使用到的页面为 `thanks.vue`
- `index.html` 中复制粘贴替换你的 [hotjar](https://github.com/Mallcloud/xmall/blob/master/study/hotjar.md) 代码
- 若不启动后端项目,勉强预览运行此前端项目可尝试注释掉 `src/main.js` 中第 `8、10、39-61` 行代码
- 在项目根文件夹下先后执行命令 `npm install``npm run dev`
- 商城前台端口默认9999 http://localhost:9999
## 部署
- 先后执行命令 `npm install``npm run build` 将打包生成的 `dist` 静态文件放置服务器中若使用Nginx等涉及跨域请配置路由代理
### 技术疑问交流
- QQ交流群 `475743731(付费)`,可获取各项目详细图文文档、疑问解答 [![](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=7b60cec12ba93ebed7568b0a63f22e6e034c0d1df33125ac43ed753342ec6ce7)
- 免费交流群 `562962309` [![](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=52f6003e230b26addeed0ba6cf343fcf3ba5d97829d17f5b8fa5b151dba7e842)
- 个人博客:[http://blog.Mallcloud.cn](http://blog.Mallcloud.cn)
### 开源协议
- 请遵循原作者MIT开源协议
### 作者其他项目推荐
- [X-Boot前后端分离开发平台](https://github.com/Mallcloud/x-boot)
![](https://i.loli.net/2018/07/21/5b52e274d2085.png)
- [XPay个人免签收款支付系统v1.2](https://github.com/Mallcloud/xpay)
- 现已支持移动端支付 手机扫码体验
![](http://p77xsahe9.bkt.clouddn.com/18-7-21/16350122.jpg)
- 微信小程序APP
- [前台源码点我提前获取](http://xpay.Mallcloud.cn/pay) [预览视频](https://v.qq.com/x/page/f0627kf4x1e.html)
![](https://i.loli.net/2018/07/21/5b52e1de385e7.png)
- 机器学习笔记
- [Machine-Learning](https://github.com/Mallcloud/Machine-Learning)
### 捐赠
![](http://p77xsahe9.bkt.clouddn.com/18-7-20/54731550.jpg)
![](http://p77xsahe9.bkt.clouddn.com/18-6-28/32845239.jpg)

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>宇运动商城</title>
<meta name="keywords" content="宇运动,宇运动商城,宇运动购物电商商城">
<meta name="description" content="宇运动电商商城">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="wap-font-scale" content="no">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> -->
<!-- <link rel="shortcut icon " type="images/x-icon" href="/static/images/M.png"> -->
</head>
<!-- <script src="https://cdn.bootcss.com/vue/2.5.3/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.17.1/axios.min.js"></script> -->
<script>
(function (h, o, t, j, a, r) {
h.hj = h.hj || function () { (h.hj.q = h.hj.q || []).push(arguments) }
h._hjSettings = { hjid: 695959, hjsv: 6 }
a = o.getElementsByTagName('head')[0]
r = o.createElement('script')
r.async = 1
r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv
a.appendChild(r)
})(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv=')
// 百度统计
/*var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5804d09853fcc4866132fbc306348993";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();*/
</script>
</script>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<style>
body{
min-width:1250px;
}
</style>

20644
mallplusui-web-pc/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
{
"name": "vue-node-mall",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "二次开发:Mallcloud 原:yucccc <13450003105@163.com>",
"private": true,
"scripts": {
"dev": "node build/dev-server.js",
"start": "node build/dev-server.js",
"build": "node build/build.js",
"lint": "eslint --ext .js,.vue src"
},
"dependencies": {
"axios": "^0.16.2",
"element-ui": "^1.4.13",
"geetest3": "^1.0.0",
"gitment": "0.0.3",
"vue": "^2.5.16",
"vue-content-placeholders": "^0.2.1",
"vue-cookie": "^1.1.4",
"vue-cropper": "^0.1.7",
"vue-infinite-scroll": "^2.0.2",
"vue-lazyload": "^1.2.2",
"vue-router": "^2.8.1",
"vuex": "^2.5.0"
},
"devDependencies": {
"autoprefixer": "^6.7.2",
"babel-core": "^6.22.1",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.10",
"babel-plugin-component": "^0.10.1",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^1.1.3",
"connect-history-api-fallback": "^1.5.0",
"copy-webpack-plugin": "^4.5.1",
"css-loader": "^0.28.11",
"element-theme-default": "^1.4.13",
"eslint": "^3.19.0",
"eslint-config-standard": "^6.2.1",
"eslint-friendly-formatter": "^2.0.7",
"eslint-loader": "^1.7.1",
"eslint-plugin-html": "^2.0.0",
"eslint-plugin-promise": "^3.7.0",
"eslint-plugin-standard": "^2.0.1",
"eventsource-polyfill": "^0.9.6",
"express": "^4.16.3",
"extract-text-webpack-plugin": "^2.0.0",
"file-loader": "^0.11.1",
"friendly-errors-webpack-plugin": "^1.7.0",
"html-webpack-plugin": "^2.28.0",
"http-proxy-middleware": "^0.17.3",
"node-sass": "^6.0.1",
"opn": "^4.0.2",
"optimize-css-assets-webpack-plugin": "^1.3.0",
"ora": "^1.4.0",
"rimraf": "^2.6.2",
"sass-loader": "^6.0.7",
"semver": "^5.5.0",
"shelljs": "^0.7.6",
"url-loader": "^0.5.8",
"vue-loader": "^12.1.0",
"vue-style-loader": "^3.1.2",
"vue-template-compiler": "^2.5.16",
"webpack": "^2.6.1",
"webpack-bundle-analyzer": "^2.11.1",
"webpack-dev-middleware": "^1.12.2",
"webpack-hot-middleware": "^2.22.0",
"webpack-merge": "^4.1.2"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -0,0 +1,21 @@
<template>
<div id="app">
<router-view class="main"></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style lang="scss" rel="stylesheet/scss">
@import "assets/style/index.scss";
#app {
height: 100%;
}
.main {
background: #ededed;;
}
</style>

View File

@@ -0,0 +1,35 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1507378437149'); /* IE9*/
src: url('iconfont.eot?t=1507378437149#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAvMAAsAAAAAEQwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW8UlpY21hcAAAAYAAAAChAAACGDcJ1AZnbHlmAAACJAAAB3IAAAoA3a2KqGhlYWQAAAmYAAAALwAAADYPHRAEaGhlYQAACcgAAAAcAAAAJAfeA4tobXR4AAAJ5AAAABQAAAAoJ+kAAGxvY2EAAAn4AAAAFgAAABYMJgjSbWF4cAAAChAAAAAdAAAAIAEeASduYW1lAAAKMAAAAUUAAAJtPlT+fXBvc3QAAAt4AAAAVAAAAG9o9X8deJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/sc4gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDyvZG7438AQw9zA0AwUZgTJAQAueAzveJzFkV0OgkAMhGf5U8QHA4YnjuDJPAEk3oLEJy/ERYZjwHRLTNB3bfNt0tm0u5kCyAGk4iYyILwQYPGUGqKe4hT1DHfVNS5SEvSs2LBlx5HTPCyL7kyrP7R9BPVbXt9pWq7ZCY6aW+CAUlLx1fmzCP97eh/neD62Sq6g39AXWTm2P9aO7Y+NIz/B1pGzYOfYrjk6chucHPmOeXBQrtpJLfUAAAB4nG1VW4zcVhn2f46Pjz2e8W18mZ3dGY/t7Hh3k8zu3Owk2+wlCSikSRqyTdKSFraNUKXQNkghLJckSiqhpFWFqBBFiArohdsD6hNvEYoqFAkVeIEHLqVKlQjaUsELSDxkHf4zmzQg8OX497H/y/ed//+PxCTp9jv0Cq1JVWlK6kp7pEOSBMpmiA3SgCgddMhm8CLmBa5B0ySNeBJ36E4IYsX1e9mgHShcMcGAJvSjXpZ2SArDwQKZh57fABgbr684kxMO/RqUamnzK8U+8gp4YTJhLmwtPrZl0e21qupa2XHGHOd5VWFMJUQ2DXgq8DWmlZTiNWbWvSvhNAmhPJbW9z9caY07j10ePN2YDDSACxegOt4yfrho1228ztb9qjPGrYpaq1eSTS6s3dRr1XKjfUPCgyDWa/Qq3YVYQ0TZxtD9oAl5kHv9IE8hazMD0vYgz3o4TaYevvnQCjy45/XDhy5dgktQvNyeKP4RHYlaYXQ0CoH8Hb/iP8vj6SEY/fHI4dcvh9CKjsRhGB0RPkvo87os0ZakS65Ul1rSJuR5izQnDaQljKED6QLkTQjQsQEblFZnIQ+BpYsQcOh7iRfdO1nkTZNh347svhfZEazuPk7I8d0b43SWHc6ytYkH3NNx8cxSfNp9AH6AFEm3pbt3cR2Wiqvke8X167cuXC8wNFj9UH/38QKEhcPZ+vpPxu5Lf6OWftu+bwyOLG0cF5aWyNX1pSW6JMkCHP2A3EAse6XL0rOSNBkhmCGiQUSDdprfeYsQnGcADwS8gN95G3ZgkOXDQTuJYqWB2eMq3HN9kUPDycRzRQa2d0ISt4WReRjekfI+rs8iZCHkePuuCf0Ni5il/Z4vpKRLf3rrxSAEMMuwqdPZBGUTIAzoyf+d687Pdy391i91a0OiA90qrq2qbIKpqwoH4Mrqnef9D1LqqNrq46rmUHpk/39/RQi1V9EmLW0/uL1E0c2rtSb838lf2CtPrthrZdMsr90TX9ujqKqyBz0rPFeVcTT7iFxiVc5PfkZVq7IuP4puxhU15woGJ+hnozU4Td7EnBpKB6Sj0qcwoyIDGsC7GJHIpnyYC5ozsQyeLWaGdgdAVO88LOAKDdoxMs9wSDqQjNYItZDUvlhFFrcHWc93leiuQKeKldbMd3nJ1OClCvg2fN/2dVuH6fVfqbquPt4ogW6VAI61h+znyqA9k+czyUC9pg6S6TwvVmqt1myrBU/VwnCu1SJvwkz45eNM+5em69rfPsEq5y0fwLeKE8IavBzOFC+gPRKRg1zX+cFPz01OzkG2ksFMHM8I4ZvC3t1LUILk3L5M/0i/IJWlQGpKsTQtdaQd0keRHcECdqoODO0ktTF1IkA+0irmU8pD4Glu0hxSLzAhh0hUYxoJUvKRLJLV9cnNxlRxUS/ebUzVAtjVhRi+hY/OMWf1/CedZ+P5eGWdhS+BfXb+3X1OcYa4pUqltP6BGP9DpvsgbRZXijVIG+TXnXW5uwzwHXi0uwvWv/pQ9bHzJ2yebJt019m3Q3DOLs//2doPfyk7ZQAcXiw7lYpTvtvXztG36AXsLLOIEasniXBI27MggC6I1ux7doJFl0SBoKAvMmOSDyM8ydvI9numcf/nntfK4FnkactfBEMvmn9wrZu6AbDzZ8UbmCw7/mT5P1JLfGr5IHN0csv2fbu48X7JPKWHlfW3Tf3HF9+4+MzFUTzv0CfpMnbZ1qjH5V2s3A5mnSh/X+HYADzsuz4GgeSTNV6rTA+BfPaVUxSGM5WGduzrsvLWs8/9nrNvHIcuRLNbzu154uTJJz5ybvPMJAlP5BN7ewC9vRPbTjQliv5uoL8JANyI6qKzp7EySxB+7M8CPsSYttMOiL1KXLkQMp7gDsCVNhclowQitkBsCFkuTgw5E/WBilgjLnabtAlt8Qiw7bg5HymjGQ/1hc0PTYvZOEu40p+BNN5wjsNdwRfLIqze+zJM24sw4AugYG8TN8/Fo5dkQS/fCCfDV56PJnt9PxxFEtw5cbfdCMxvB2ILYVlPNEclRtuDIBeFi5FhCdOj1ZoZWp7rupRQoqjcIkQrl52qPVMtqaY7hhyWuKoTIKo2tdmKLG8CtNLWODswm+t+vTzfOzCMpzkDypnCKprMACiF0SETFGVeUhiBUqVhMSC6FSYOoWXD8HEDYJQQYKjMaAlbtWESmRhJs6Ir6M9qVBQFrWg6l4VFwoRN1KBACCNEpZSoBAxzEkE6VrPmOBxkTijHz0zVUKdRG/fqhuW6jUaNylTdUMIo199TTOUM08Xwpb8ys6y8r5g6ecEi6IcQdA9UlrGysMc4tsE0ptq1qiBBZkwAU/E/WUn8A9u37zw9+PjO9rjCOA83Lx/d9sWlXm9rOdBVRdYq+DeROSUY0465rgnEsewwNEwMw6/P+QqQSjVu4ryqa6aOWwega6YbWklHSW9EhqEiZG+2XjGQnLFmaFsuQtF6/UWEicwwgQh1NlRlqjDNGatWOZHFhGBuvObZJUYE1yPrCBAj+6einEHM7PPMPPU7wYQY/g3PhnyyAAB4nGNgZGBgAGI7/veS8fw2Xxm4WRhA4Oq/Z6wI+n8tCwNzA5DLwcAEEgUAJNcKjwB4nGNgZGBgbvjfwBDDwgACQJKRARVwAQBHEAJzeJxjYWBgYH7JwMDCgB8DACNPAREAAAAAAHYAsAEcAd4CagLiAyoDYgUAAAB4nGNgZGBg4GKUZuBiAAEmEA/M/g/mMwAADPsBRwAAAHicZY9NTsMwEIVf+gekEqqoYIfkBWIBKP0Rq25YVGr3XXTfpk6bKokjx63UA3AejsAJOALcgDvwSCebNpbH37x5Y08A3OAHHo7fLfeRPVwyO3INF7gXrlN/EG6QX4SbaONVuEX9TdjHM6bCbXRheYPXuGL2hHdhDx18CNdwjU/hOvUv4Qb5W7iJO/wKt9Dx6sI+5l5XuI1HL/bHVi+cXqnlQcWhySKTOb+CmV7vkoWt0uqca1vEJlODoF9JU51pW91T7NdD5yIVWZOqCas6SYzKrdnq0AUb5/JRrxeJHoQm5Vhj/rbGAo5xBYUlDowxQhhkiMro6DtVZvSvsUPCXntWPc3ndFsU1P9zhQEC9M9cU7qy0nk6T4E9XxtSdXQrbsuelDSRXs1JErJCXta2VELqATZlV44RelzRiT8oZ0j/AAlabsgAAAB4nG3JSwqAMAxF0bx+rNZVFlqpEyOJQd29glPP8F5y9Mn0L8PBIyBiQMKICRkz4Rr3onqy1LBuCw83W7c1lVqlqca3N/FsRzBtkrS/m43oAU4lE+0=') format('woff'),
url('iconfont.ttf?t=1507378437149') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1507378437149#iconfont') format('svg'); /* iOS 4.1- */
}
[class^="el-icon"], [class*=" el-icon"] {
font-family:"iconfont" !important;
/* 以下内容参照第三方图标库本身的规则 */
font-size: 16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.el-icon-password:before { content: "\e613"; }
.el-icon-info:before { content: "\e61c"; }
.el-icon-youhui:before { content: "\e612"; }
.el-icon-address:before { content: "\e60b"; }
.el-icon-order:before { content: "\e693"; }
.el-icon-out:before { content: "\e6c9"; }
.el-icon-user:before { content: "\e616"; }
.el-icon-shouhou:before { content: "\e779"; }

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,72 @@
.w {
width: 1220px;
margin: 0 auto;
}
.fl {
float: left;
}
.fr {
float: right;
}
.pr {
position: relative;
}
.pa {
position: absolute;
}
.active {
color: #c81623;
}
.clearfix:after {
content: '';
display: block;
clear: both;
line-height: 0;
visibility: hidden;
}
.clearfix {
*zoom: 1
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 删除按钮
.del-btn {
display: block;
cursor: pointer;
width: 20px;
height: 20px;
background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) -50px -60px no-repeat;
background-size: 240px 107px;
text-indent: -9999em;
&:hover {
background-position: -75px -60px;
}
}
.layout-container {
min-height: 400px;
background: #E6E6E6;
}
.gray-box {
overflow: hidden;
background: #fff;
border-radius: 8px;
border: 1px solid #dcdcdc;
border-color: rgba(0, 0, 0, .14);
box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);
}

View File

@@ -0,0 +1,3 @@
// @import "reset";
@import "./reset.scss";
@import "common";

View File

@@ -0,0 +1,10 @@
%block-center {
display: flex;
align-items: center;
justify-content: center;
}
@mixin wh($w,$h:$w) {
width: $w;
height: $h;
}

View File

@@ -0,0 +1,66 @@
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: PingFang SC, Helvetica Neue, Helvetica, Arial, Hiragino Sans GB, Microsoft Yahei, \\5FAE\8F6F\96C5\9ED1, STHeiti, \\534E\6587\7EC6\9ED1, sans-serif;
color: #666;
font-size: 14px;
}
a {
font-style: normal;
text-decoration: none;
color: #5079d9;
cursor: pointer;
transition: all .15s ease-out;
&:hover {
color: #6b95ea;
}
}
li {
list-style-type: none;
}
input,
img,
button {
border: none;
outline: none;
}
h1, h2, h3, h4, h5, h6 {
font-size: 100%;
font-weight: 400;
}
i, em {
font-style: normal;
}
input[type=number], textarea {
-moz-appearance: textfield;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button,
input[type="submit"],
input[type="search"],
input[type="reset"] {
-webkit-appearance: none;
}
::-webkit-input-placeholder { /* WebKit browsers */
color: #BEBEBE;
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #BEBEBE;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #BEBEBE;
}
:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #BEBEBE;
}

View File

@@ -0,0 +1,10 @@
// 主色
$main-col: #5079d9;
// 头部
$head-bgc: #1a1a1a;
// 字体颜色
$cc: #ccc;
$c6: #666;
$c9: #999;
$c3: #333;
$cf: #fff

View File

@@ -0,0 +1,272 @@
<template>
<div class="footer">
<div class="container">
<div class="siteinfo">
<ul class="c0">
<h3 class="c1">订单服务</h3>
<ul>
<li class="c2"><router-link to="/thanks"><a class="c3">购买指南</a></router-link></li>
<li class="c2"><a class="c3" @click="open4">支付方式</a></li>
<li class="c2"><a class="c3" @click="open5">送货政策</a></li>
</ul>
</ul>
<ul class="c0">
<h3 class="c1">服务支持</h3>
<ul>
<li class="c2"><a class="c3" target="_blank" href="https://gitee.com/zscat-platform/mall">官方开源</a></li>
<li class="c2"><a class="c3" target="_blank" href="https://gitee.com/catshen/mall-applet">项目前端</a></li>
<li class="c2"><a class="c3" target="_blank" href="https://gitee.com/zscat-platform/mall">项目后端</a></li>
</ul>
</ul>
<ul class="c0">
<h3 class="c1">自助服务</h3>
<ul>
<li class="c2"><a class="c3" target="_blank" href="https://github.com/shenzhuan/mall-dubbo">dubbo版本</a></li>
<li class="c2"><a class="c3" target="_blank" href="https://blog.csdn.net/a1439226817">个人简介</a></li>
<li class="c2"><a class="c3" target="_blank" href="https://www.bilibili.com/video/av15860053/">个人视频</a></li>
</ul>
</ul>
<ul class="c0">
<h3 class="c1">其他项目</h3>
<ul>
<li class="c2"><a class="c3" target="_blank" href="http://xpay.Mallcloud.cn">XPay支付系统</a></li>
<li class="c2"><a class="c3" target="_blank" href="http://shouji.baidu.com/software/11783429.html">数据共享</a></li>
<li class="c2"><a class="c3" target="_blank" href="https://github.com/Mallcloud">待开发...</a></li>
</ul>
</ul>
<ul class="c0">
<h3 class="c1">友情链接</h3>
<ul>
<li class="c2"><a class="c3" target="_blank" href="http://yucccc.com/">宇cccc</a></li>
<li class="c2"><a class="c3" target="_blank" href="http://www.smartisan.com">Smartisan</a></li>
<li class="c2"><a class="c3" target="_blank" href="https://cn.vuejs.org/">Vue</a></li>
</ul>
</ul>
<ul class="c0">
<h3 class="c1">关注我吧</h3>
<ul>
<li class="c2"><a class="c3" target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=1012139570&site=qq&menu=yes">腾讯 QQ</a></li>
<li class="c2"><a class="c3" target="_blank" href="http://weibo.com/2255094222/profile">新浪微博</a></li>
<li class="c2"><a class="c3" target="_blank" href="mailto:1012139570@qq.com">官方邮箱</a></li>
</ul>
</ul>
<!-- <ul class="c4">
<li class="tel"><a class="c5" href="http://wpa.qq.com/msgrd?v=3&uin=1012139570&site=qq&menu=yes" target="_blank">1012139570</a></li>
<li class="time">周一至周日 10:00-23:00限Starrer或捐赠人联系</li>
<li class="online">
<y-button text="在线帮助" class="button" @btnClick="open3"></y-button>
</li>
</ul> -->
</div>
<div class="copyright" style="margin-left: 23%;">
<h4 class="content-c2">Copyright ©2017, Mallcloud.cn Co., Ltd. All Rights Reserved.本网站设计内容大部分属石家庄市宇信通电子有限公司</h4>
<!-- <ul class="privacy">
<li class="content-c1"><a class="content-c0" @click="open1">法律声明</a></li>
<li class="content-c1"><a class="content-c0" @click="open2">隐私条款</a></li>
<li class="content-c1"><a class="content-c0" target="_blank" href="https://github.com/Mallcloud">开发者中心</a></li>
</ul> -->
</div>
<div class="cop">
<a class="content-c3" href="https://beian.miit.gov.cn/" target="_blank">
<!-- <span class="content-c3">蜀ICP备16030308号-1</span> -->
<!-- <span class="content-c3">蜀ICP证16030308号</span> -->
<span class="content-c3" style="margin-left: 43%;">冀ICP备10002647号-11</span>
</a>
</div>
</div>
</div>
</template>
<script>
import YButton from '/components/YButton'
export default {
data () {
return {
}
},
methods: {
open1 () {
this.$notify.info({
title: '法律声明',
message: '此仅为个人练习开源模仿项目,仅供学习参考,承担不起任何法律问题'
})
},
open2 () {
this.$notify.info({
title: '隐私条款',
message: '本网站将不会严格遵守有关法律法规和本隐私政策所载明的内容收集、使用您的信息'
})
},
open3 () {
this.$notify({
title: '离线帮助',
message: '没人会帮助你,请自己靠自己',
type: 'warning'
})
},
open4 () {
this.$notify.info({
title: '支付方式',
message: '支持支付宝、微信等方式捐赠'
})
},
open5 () {
this.$notify({
title: '送货政策',
message: '本网站所有商品购买后不会发货,将用作捐赠',
type: 'warning'
})
}
},
components: {
YButton
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.footer {
padding: 50px 0 20px;
border-top: 1px solid #e6e6e6;
background: #fafafa;
margin-top: 60px;
height: 350px;
display: flex;
flex-direction: column;
align-items: center;
}
.container {
width: 1220px;
}
.siteinfo {
height: 100px;
padding: 50px 0 130px;
border-bottom: 1px solid #e6e6e6;
position: relative;
}
.c0 {
width: 149px;
line-height: 1;
float: left;
}
.c1 {
color: #646464;
font-size: 12px;
padding: 0 0 14px;
}
.c2 {
color: #c3c3c3;
font-size: 12px;
padding: 6px 0;
}
.c3 {
color: #969696;
}
.c4 {
position: absolute;
right: 0;
overflow: hidden;
line-height: 34px;
}
.tel {
font-size: 30px;
line-height: 1;
color: #646464;
top: -2px;
position: relative;
}
.c5 {
color: #646464;
right: -70px;
position: relative;
}
.time {
margin-top: 5px;
right: -4px;
position: relative;
clear: both;
width: 241px;
font-size: 12px;
line-height: 18px;
color: #c3c3c3;
text-align: right;
}
.online {
clear: both;
width: 241px;
font-size: 12px;
line-height: 18px;
color: #c3c3c3;
text-align: right;
}
.button {
width: 130px;
height: 34px;
font-size: 14px;
color: #5079d9;
border: 1px solid #dcdcdc;
margin-top: 8px;
}
.copyright {
color: #434d55;
font-size: 12px;
padding: 40px 0 0;
display: flex;
align-items: left;
}
.privacy {
float: left;
margin: 0 0 0 12px;
}
.content-c0 {
color: #5079d9;
cursor: pointer;
text-decoration: none;
&:hover {
color: #3A5FCD;
}
}
.content-c1 {
float: left;
line-height: 12px;
padding: 1px 10px 0;
border-left: 1px solid #ccc;
}
.content-c2 {
float: left;
height: 15px;
line-height: 15px;
color: #757575;
}
.cop {
clear: both;
padding: 10px 0 0;
height: 15px;
}
.content-c3 {
margin-right: 20px;
color: #bdbdbd;
font-size: 12px;
height: 12px;
line-height: 1;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
<template>
<input :type="inputType"
readonly
:class="classStyle"
@click="btnClick($event)"
:disabled="classStyle==='disabled-btn'"
:value="text">
</template>
<script>
export default {
props: {
text: {
type: [String, Number],
default: '一颗小按钮'
},
inputType: {
type: [String],
default: 'button'
},
classStyle: {
type: String,
default: 'default-btn'
}
},
methods: {
btnClick (event) {
this.$emit('btnClick', event)
}
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "../assets/style/theme";
%style {
width: 100px;
height: 30px;
line-height: 28px;
vertical-align: middle;
}
@mixin color($a,$b,$c) {
border: 1px solid $a;
border-radius: 4px;
font-size: 12px;
color: $b;
background-color: $c;
}
input {
display: inline-block;
cursor: pointer;
text-align: center;
/*> span {*/
/*user-select: none;*/
/*display: inline-block;*/
/*width: 100%;*/
/*height: 100%;*/
/*}*/
}
/*灰色的按钮*/
.gray-btn {
border: 1px solid #d5d5d5;
color: #646464;
}
// 默认按钮
.default-btn {
@include color(#e1e1e1, #646464, #f9f9f9);
@extend %style;
background-image: -webkit-linear-gradient(top, $cf, #f9f9f9);
background-image: linear-gradient(180deg, $cf, #f9f9f9);
&:hover {
background-color: #eee;
background-image: -webkit-linear-gradient(top, #f5f5f5, #eee);
background-image: linear-gradient(180deg, #f5f5f5, #eee);
}
}
// 主色按钮
.main-btn {
@include color(#5c81e3, #fff, #678ee7);
background-image: -webkit-linear-gradient(top, #678ee7, #5078df);
background-image: linear-gradient(180deg, #678ee7, #5078df);
@extend %style;
&:hover {
background-color: #6c8cd4;
background-image: -webkit-linear-gradient(top, #6c8cd4, #4769c2);
background-image: linear-gradient(180deg, #6c8cd4, #4769c2);
}
}
// 禁用
.disabled-btn {
cursor: not-allowed;
@include color(#afafaf, $cf, #a9a9a9);
@extend %style;
background-image: -webkit-linear-gradient(top, #b8b8b8, #a9a9a9);
background-image: linear-gradient(180deg, #b8b8b8, #a9a9a9);
}
</style>

View File

@@ -0,0 +1,207 @@
<template>
<!--数量-->
<div class="item-cols-num clearfix">
<div class="select">
<span class="down"
@click.stop.prevent="down()"
:class="{'down-disabled':Num<=1}">-
</span>
<span class="num">
<input type="text"
:class="{show:show}"
v-model="Num>=limit?limit:Num"
@blur="blur()"
maxlength="2">
<ul ref="ul">
<li v-for="i in numList" :key="i">{{i}}</li>
</ul>
</span>
<span class="up" :class="{'up-disabled':Num>=limit}"
@click.stop.prevent="up()">+</span>
</div>
</div>
</template>
<script>
export default {
props: {
num: {
type: [Number],
default: 1
},
id: {
type: [Number, String]
},
checked: {
type: [String, Boolean]
},
limit: {
type: Number,
default: 10
}
},
computed: {},
data () {
return {
show: true,
flag: true,
Num: this.num,
numList: []
}
},
methods: {
up () {
if (this.flag && this.Num < this.limit) {
this.ani('up')
}
return false
},
down () {
if (this.flag && this.Num > 1) {
this.ani('down')
}
return false
},
blur () {
this.Num = this.Num > this.limit ? Number(this.limit) : Number(this.Num)
this.$emit('edit-num', this.Num, this.id, this.checked)
},
ani (opera) {
this.flag = false
let n = this.Num
this.numList = [n - 1, n, n + 1]
let ul = this.$refs.ul
let ulStyle = ul.style
this.show = false
ulStyle.zIndex = '99'
ulStyle.transition = 'all .2s ease-out'
if (opera === 'up') {
this.Num++
ulStyle.transform = 'translateY(-54px)'
} else {
this.Num--
ulStyle.transform = `translateY(-18px)`
}
ul.addEventListener('transitionend', () => {
this.show = true
this.domInt(ulStyle)
this.flag = true
})
ul.addEventListener('webkitAnimationEnd', () => {
this.show = true
this.domInt(ulStyle)
this.flag = true
})
this.$emit('edit-num', this.Num, this.id, this.checked)
},
domInt (domStyle) {
domStyle.zIndex = '1'
domStyle.transition = 'all 0s'
domStyle.transform = 'translateY(-36px)' // 回到原位
}
}
}
</script>
<style lang="scss" scoped>
.select {
input {
z-index: 10;
width: 36px;
height: 18px;
background-color: #fff;
border: none;
text-align: center;
line-height: 18px;
font-size: 14px;
padding: 0;
color: #666;
visibility: hidden;
position: relative;
border: none;
&.show {
visibility: visible;
}
}
ul {
padding: 0;
line-height: 18px;
font-size: 14px;
display: inline-block;
position: absolute;
left: 0;
list-style: none;
width: 36px;
font-family: system-ui;
z-index: 1;
transform: translateY(-36px);
}
.up.up-disabled, .up.up-disabled:hover {
background-position: 0 -240px !important;
cursor: not-allowed !important;
}
}
/*数量*/
.item-cols-num {
display: inline-block;
}
.select {
height: 40px;
padding-top: 4px;
input {
width: 100%;
text-align: center;
}
.down {
background-position: 0 -60px;
}
.down.down-disabled:hover {
background-position: 0 -300px;
cursor: not-allowed;
}
.down, .up {
background: url(../../static/images/cart-updown_8303731e15@2x.jpg) no-repeat;
overflow: hidden;
float: left;
width: 34px;
height: 37px;
background-size: 100% auto;
line-height: 40px;
text-indent: -9999em;
cursor: pointer;
user-select: none;
}
.num {
position: relative;
overflow: hidden;
text-align: center;
float: left;
width: 36px;
height: 18px;
margin: 7px 0 0;
border: none;
border-radius: 3px;
line-height: 18px;
text-align: center;
font-size: 14px;
}
.up {
margin: 0;
background-position: 0 0;
&:hover {
background-position: 0 -120px;
}
}
.down {
background-position: 0 -60px;
&:hover {
background-position: 0 -180px;
}
}
}
.down.down-disabled {
background-position: 0 -300px;
cursor: not-allowed;
}
</style>

View File

@@ -0,0 +1,74 @@
<template>
<span :endTime="endTime" :callback="callback" :endText="endText">
<slot>
{{content}}
</slot>
</span>
</template>
<script>
export default {
data () {
return {
content: ''
}
},
props: {
endTime: {
type: String,
default: ''
},
endText: {
type: String,
default: '已结束'
},
callback: {
type: Function,
default: null
}
},
methods: {
countdowm (timestamp) {
let self = this
let timer = setInterval(function () {
let nowTime = new Date()
let t = timestamp - nowTime.getTime()
if (t > 0) {
let day = Math.floor(t / 86400000)
let hour = Math.floor((t / 3600000) % 24)
let min = Math.floor((t / 60000) % 60)
let sec = Math.floor((t / 1000) % 60)
hour = hour < 10 ? '0' + hour : hour
min = min < 10 ? '0' + min : min
sec = sec < 10 ? '0' + sec : sec
let format = ''
if (day > 0) {
format = `${day}${hour} 小时 ${min}${sec}`
}
if (day <= 0 && hour > 0) {
format = `${hour} 小时 ${min}${sec}`
}
if (day <= 0 && hour <= 0) {
format = `${min}${sec}`
}
self.content = format
} else {
clearInterval(timer)
self.content = self.endText
self._callback()
}
}, 1000)
},
_callback () {
if (this.callback && this.callback instanceof Function) {
this.callback(...this)
}
}
},
mounted () {
this.countdowm(this.endTime)
}
}
</script>
<style lang='scss' rel='stylesheet/scss' scoped>
</style>

View File

@@ -0,0 +1,142 @@
<template>
<div class="good-item">
<div style="">
<div class="good-img">
<a @click="openProduct(msg.id)">
<img v-lazy="msg.pic" :alt="msg.name" :key="msg.pic">
</a>
</div>
<h6 class="good-title" v-html="msg.name">{{msg.name}}</h6>
<h3 class="sub-title ellipsis">{{msg.subTitle}}</h3>
<div class="good-price pr">
<div class="ds pa">
<a @click="openProduct(msg.id)">
<y-button text="查看详情" style="margin: 0 5px"></y-button>
</a>
<y-button text="加入购物车"
style="margin: 0 5px"
@btnClick="addCart(msg.id,msg.price,msg.name,msg.pic)"
classStyle="main-btn"
></y-button>
</div>
<p><span style="font-size:14px"></span>{{Number(msg.price).toFixed(2)}}</p>
</div>
</div>
</div>
</template>
<script>
import YButton from '/components/YButton'
import { addCart } from '/api/goods.js'
import { mapMutations, mapState } from 'vuex'
import { getStore } from '/utils/storage'
export default {
props: {
msg: {
salePrice: 0
}
},
data () {
return {}
},
methods: {
...mapMutations(['ADD_CART', 'ADD_ANIMATION', 'SHOW_CART']),
goodsDetails (id) {
this.$router.push({path: 'goodsDetails/id=' + id})
},
openProduct (id) {
window.open('//' + window.location.host + '/#/goodsDetails?id=' + id)
},
addCart (id, price, name, img) {
if (!this.showMoveImg) { // 动画是否在运动
if (this.login) { // 登录了 直接存在用户名下
addCart({userId: getStore('userId'), id: id, productNum: 1}).then(res => {
// 并不重新请求数据
this.ADD_CART({id: id, salePrice: price, productName: name, productImg: img})
})
} else { // 未登录 vuex
this.ADD_CART({id: id, salePrice: price, productName: name, productImg: img})
}
// 加入购物车动画
var dom = event.target
// 获取点击的坐标
let elLeft = dom.getBoundingClientRect().left + (dom.offsetWidth / 2)
let elTop = dom.getBoundingClientRect().top + (dom.offsetHeight / 2)
// 需要触发
this.ADD_ANIMATION({moveShow: true, elLeft: elLeft, elTop: elTop, img: img})
if (!this.showCart) {
this.SHOW_CART({showCart: true})
}
}
}
},
computed: {
...mapState(['login', 'showMoveImg', 'showCart'])
},
mounted () {
},
components: {
YButton
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "../assets/style/mixin";
@import "../assets/style/theme";
.good-item {
background: #fff;
width: 25%;
transition: all .5s;
height: 430px;
&:hover {
transform: translateY(-3px);
box-shadow: 1px 1px 20px #999;
.good-price p {
display: none;
}
.ds {
display: flex;
}
}
.ds {
@extend %block-center;
width: 100%;
display: none;
}
.good-img {
img {
margin: 50px auto 10px;
@include wh(206px);
display: block;
}
}
.good-price {
margin: 15px 0;
height: 30px;
text-align: center;
line-height: 30px;
color: #d44d44;
font-family: Arial;
font-size: 18px;
font-weight: 700;
}
.good-title {
line-height: 1.2;
font-size: 16px;
color: #424242;
margin: 0 auto;
padding: 0 14px;
text-align: center;
overflow: hidden;
}
h3 {
text-align: center;
line-height: 1.2;
font-size: 12px;
color: #d0d0d0;
padding: 10px;
}
}
</style>

View File

@@ -0,0 +1,111 @@
<template>
<div class="popup" v-if="open">
<div class="mask">
<div class="content">
<div class="topbar">
<div class="dialog-tit">
<h4>{{title}}</h4>
</div>
<span class="close" @click="close">
<svg t="1501234940517" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3014" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"><path d="M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z" fill="#cdcdcd" p-id="3015"></path></svg>
</span>
</div>
<div class="s-content">
<slot name="content"></slot>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
open: {
type: Boolean,
default: false
},
title: {
type: String,
default: '管理收货地址'
}
},
methods: {
close () {
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.popup {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 1000;
text-align: center;
transition: opacity .2s ease-in;
.mask {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .5);
}
.content {
width: 30%;
background: #fff;
border-radius: 10px;
}
.topbar {
position: relative;
z-index: 10;
overflow: hidden;
width: 100%;
height: 60px;
background: #F5F5F5;
background: linear-gradient(#FFF,#F5F5F5);
border-bottom: 1px solid #DCDCDC;
border-radius: 10px 10px 0 0;
box-shadow: 2px 0 5px rgba(0,0,0,.1);
}
.dialog-tit {
height: 60px;
padding: 0 15px;
line-height: 60px;
h4 {
text-align: center;
font-size: 18px;
font-weight: 400;
color: #666;
}
}
.s-content{
padding: 30px 15px;
}
.close{
position: absolute;
right: 10px;
top: 50%;
transform:translateY(-50%);
width: 20px;
height: 20px;
&:hover{
svg{
transition: all 1s;
transform: rotate(360deg);
transform-origin:50% 50%;
}
path{
fill: #8a8a8a;
}
}
}
}
</style>

View File

@@ -0,0 +1,63 @@
<template>
<div class="item" id="product.spu.id">
<div class="img-box">
<img :src="product.spu.sku_info[0].ali_image" alt="">
</div>
<div class="info">
<h6 class="ellipsis">{{product.spu.sku_info[0].title}}</h6>
<p>{{product.spu.sku_info[0].sub_title}}</p>
</div>
<p class="price">
<i>¥</i>
<span>{{product.spu.price}}</span>
</p>
<ul class="dot-list">
<li></li>
</ul>
</div>
</template>
<script>
export default {
props: [
'product'
]
}
</script>
<style scoped lang="scss">
@import "../assets/style/mixin";
.item {
position: relative;
height: 429px;
text-align: center;
img {
display: block;
width: 206px;
height: 206px;
}
.img-box {
@extend %block-center
}
.info {
width: 100%;
padding: 0 10px;
h6 {
overflow: hidden;
font-size: 16px;
line-height: 1.2;
white-space: nowrap;
text-overflow: ellipsis;
color: #424242;
}
p {
overflow: hidden;
padding-top: 7px;
font-size: 12px;
line-height: 1.2;
white-space: nowrap;
text-overflow: ellipsis;
color: #b2b2b2;
}
}
}
</style>

View File

@@ -0,0 +1,58 @@
<template>
<div class="gray-box">
<div class="title">
<h2>{{title}}</h2>
<div>
<slot name="right"></slot>
</div>
</div>
<!--内容-->
<div>
<slot name="content"></slot>
</div>
</div>
</template>
<script>
export default {
props: [
'title'
]
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.gray-box {
position: relative;
margin-bottom: 30px;
overflow: hidden;
background: #fff;
border-radius: 8px;
border: 1px solid #dcdcdc;
border-color: rgba(0, 0, 0, .14);
box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);
.title {
padding-left: 30px;
position: relative;
z-index: 10;
height: 60px;
padding: 0 10px 0 24px;
border-bottom: 1px solid #d4d4d4;
border-radius: 8px 8px 0 0;
box-shadow: rgba(0, 0, 0, .06) 0 1px 7px;
background: #f3f3f3;
background: -webkit-linear-gradient(#fbfbfb, #ececec);
background: linear-gradient(#fbfbfb, #ececec);
line-height: 60px;
font-size: 18px;
color: #333;
display: flex;
justify-content: space-between;
align-items: center;
h2 {
font-size: 18px;
font-weight: 400;
color: #626262;
display: inline-block;
}
}
}
</style>

View File

@@ -0,0 +1,569 @@
<template>
<div class="shopping-cart">
<y-header>
<div slot="nav"></div>
</y-header>
<div class="store-content page-cart">
<div class="gray-box">
<div class="title"><h2>购物清单</h2></div>
<!--内容-->
<div v-if="cartList.length">
<div class="ui-cart">
<div>
<!--标题-->
<div class="cart-table-title">
<span class="name">商品信息</span> <span class="operation">操作</span> <span
class="subtotal">小计</span> <span class="num">数量</span> <span class="price1">单价</span>
</div>
<!--列表-->
<div class="cart-table" v-for="(item,i) in cartList" :key="i">
<div class="cart-group divide pr" :data-productid="item.productId">
<div class="cart-top-items">
<div class="cart-items clearfix">
<!--勾选-->
<div class="items-choose">
<span class="blue-checkbox-new " :class="{'checkbox-on':item.checked === '1'}"
@click="editCart('check',item)"></span>
</div>
<!--图片-->
<div class="items-thumb fl">
<img :alt="item.productName"
:src="item.productImg">
<a @click="goodsDetails(item.productId)" :title="item.productName" target="_blank"></a>
</div>
<!--信息-->
<div class="name hide-row fl">
<div class="name-table">
<a @click="goodsDetails(item.productId)" :title="item.productName" target="_blank"
v-text="item.productName"></a>
<!-- <ul class="attribute">
<li>白色</li>
</ul> -->
</div>
</div>
<!--删除按钮-->
<div class="operation">
<a class="items-delete-btn" @click="cartdel(item.productId)"></a>
</div>
<!--商品数量-->
<div>
<!--总价格-->
<div class="subtotal" style="font-size: 14px">¥ {{item.salePrice * item.productNum}}</div>
<!--数量-->
<buy-num :num="item.productNum"
:id="item.productId"
:checked="item.checked"
style="height: 140px;
display: flex;
align-items: center;
justify-content: center;"
:limit="item.limitNum"
@edit-num="EditNum"
>
</buy-num>
<!--价格-->
<div class="price1">¥ {{item.salePrice}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cart-bottom-bg fix-bottom">
<div class="fix-bottom-inner">
<div class="cart-bar-operation">
<div>
<div class="choose-all">
<span :class="{'checkbox-on':checkAllFlag}" class="blue-checkbox-new" @click="editCheckAll"></span>
<span @click="editCheckAll">全选</span>
</div>
<div class="delete-choose-goods" @click="delChecked">删除选中的商品</div>
</div>
</div>
<div class="shipping">
<div class="shipping-box">
<div class="shipping-total shipping-num"><h4
class="highlight">已选择 <i v-text="checkNum"></i> 件商品</h4>
<h5>共计 <i v-text="totalNum"></i> 件商品</h5></div>
<div class="shipping-total shipping-price"><h4
class="highlight">应付总额<span></span><i v-text="checkPrice"></i>
</h4>
<h5 class="shipping-tips ng-scope">应付总额不含运费</h5>
</div>
</div>
<y-button :classStyle="checkNum > 0 && submit?'main-btn':'disabled-btn'"
class="big-main-btn"
style="margin: 0;width: 130px;height: 50px;line-height: 50px;font-size: 16px"
:text="checkoutNow" @btnClick="checkout"></y-button>
</div>
</div>
</div>
</div>
<div v-else style="padding:50px">
<div class="cart-e">
</div>
<p style="text-align: center;padding: 20px;color: #8d8d8d">你的购物车空空如也</p>
<div style="text-align: center">
<router-link to="/goods">
<y-button text="现在选购" style="width: 150px;height: 40px;line-height: 38px;color: #8d8d8d"></y-button>
</router-link>
</div>
</div>
</div>
</div>
<y-footer></y-footer>
</div>
</template>
<script>
import { getCartList, cartEdit, editCheckAll, cartDel, delCartChecked } from '/api/goods'
import { mapMutations, mapState } from 'vuex'
import YButton from '/components/YButton'
import YHeader from '/common/header'
import YFooter from '/common/footer'
import BuyNum from '/components/buynum'
import { getStore } from '/utils/storage'
export default {
data () {
return {
userId: 0,
checkoutNow: '现在结算',
submit: true
}
},
computed: {
...mapState(
['cartList']
),
// 是否全选
checkAllFlag () {
return this.checkedCount === this.cartList.length
},
// 勾选的数量
checkedCount () {
var i = 0
this.cartList && this.cartList.forEach((item) => {
if (item.checked === '1') i++
})
return Number(i)
},
// 计算总数量
totalNum () {
var totalNum = 0
this.cartList && this.cartList.forEach(item => {
totalNum += (item.productNum)
})
return Number(totalNum)
},
// 选中的总价格
checkPrice () {
var totalPrice = 0
this.cartList && this.cartList.forEach(item => {
if (item.checked === '1') {
totalPrice += (item.productNum * item.salePrice)
}
})
return totalPrice
},
// 选中的商品数量
checkNum () {
var checkNum = 0
this.cartList && this.cartList.forEach(item => {
if (item.checked === '1') {
checkNum += (item.productNum)
}
})
return checkNum
}
},
methods: {
...mapMutations([
'INIT_BUYCART', 'EDIT_CART'
]),
message (m) {
this.$message.error({
message: m
})
},
goodsDetails (id) {
window.open(window.location.origin + '#/goodsDetails?productId=' + id)
},
// 全选
editCheckAll () {
let checkAll = !this.checkAllFlag
editCheckAll({userId: this.userId, checked: checkAll}).then(res => {
this.EDIT_CART({checked: checkAll})
})
},
// 修改购物车
_cartEdit (userId, productId, productNum, checked) {
cartEdit(
{
userId,
productId,
productNum,
checked
}
).then(res => {
if (res.code === 200) {
this.EDIT_CART(
{
productId,
checked,
productNum
}
)
}
})
},
// 修改购物车
editCart (type, item) {
if (type && item) {
let checked = item.checked
let productId = item.productId
let productNum = item.productNum
// 勾选
if (type === 'check') {
let newChecked = checked === '1' ? '0' : '1'
this._cartEdit(this.userId, productId, productNum, newChecked)
}
} else {
console.log('缺少所需参数')
}
},
EditNum (productNum, productId, checked) { // 数量
this._cartEdit(this.userId, productId, productNum, checked)
},
// 删除整条购物车
cartdel (productId) {
cartDel({userId: this.userId, productId}).then(res => {
this.EDIT_CART({productId})
})
},
checkout () {
this.checkoutNow = '结算中...'
this.submit = false
this.$router.push({path: 'checkout'})
},
delChecked () {
getCartList({userId: getStore('userId')}).then(res => {
if (res.code === 200) {
res.data.forEach(item => {
if (item.checked === '1') {
let productId = item.productId
this.EDIT_CART({productId})
}
})
}
})
delCartChecked({userId: this.userId}).then(res => {
if (res.success !== true) {
this.message('删除失败')
}
})
}
},
mounted () {
this.userId = getStore('userId')
this.INIT_BUYCART()
},
components: {
YButton,
YHeader,
YFooter,
BuyNum
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.store-content {
clear: both;
width: 1220px;
min-height: 600px;
padding: 0 0 25px;
margin: 0 auto;
.gray-box {
position: relative;
margin-bottom: 30px;
overflow: hidden;
background: #fff;
border-radius: 8px;
border: 1px solid #dcdcdc;
border-color: rgba(0, 0, 0, .14);
box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);
.title {
padding-left: 30px;
position: relative;
z-index: 10;
height: 60px;
padding: 0 10px 0 24px;
border-bottom: 1px solid #d4d4d4;
border-radius: 8px 8px 0 0;
box-shadow: rgba(0, 0, 0, .06) 0 1px 7px;
background: #f3f3f3;
background: -webkit-linear-gradient(#fbfbfb, #ececec);
background: linear-gradient(#fbfbfb, #ececec);
line-height: 60px;
font-size: 18px;
color: #333;
}
}
.ui-cart {
padding-bottom: 91px;
.cart-table-title {
position: relative;
z-index: 1;
line-height: 38px;
height: 38px;
padding: 0 0 0 30px;
font-size: 12px;
background: #eee;
border-bottom: 1px solid #dbdbdb;
border-bottom-color: rgba(0, 0, 0, .08);
.name {
float: left;
text-align: left;
}
span {
width: 137px;
float: right;
text-align: center;
color: #838383;
}
}
.cart-group.divide {
.cart-items {
border-top: 1px dashed #eee;
}
}
.cart-items {
position: relative;
height: 140px;
margin-left: 74px;
/*删除*/
.operation {
padding: 58px 0 0;
font-size: 12px;
line-height: 24px;
.items-delete-btn {
background-image: url(../../../static/images/delete-btn-icon_a35bf2437e@2x.jpg);
&:hover {
background-position: 0 -36px;
}
}
.items-delete-btn {
display: block;
width: 24px;
height: 24px;
margin: 0 auto;
color: #C2C2C2;
background: url(../../../static/images/delete-btn-icon_a35bf2437e@2x.jpg);
-webkit-background-size: 100% auto;
background-size: 100% auto;
-moz-transition: none;
-webkit-transition: none;
-o-transition: none;
transition: none;
}
}
.subtotal {
font-weight: 700;
}
.item-cols-num,
.operation,
.price1,
.subtotal {
overflow: hidden;
float: right;
width: 137px;
text-align: center;
color: #666;
line-height: 140px;
}
}
.cart-group.divide .cart-top-items:first-child .cart-items {
border-top: none;
}
.items-choose {
position: absolute;
left: -74px;
top: 0;
width: 74px;
height: 20px;
padding: 60px 0 0 31px;
font-size: 12px;
color: #999;
}
.items-thumb {
position: relative;
margin-top: 30px;
overflow: hidden;
width: 80px;
height: 80px;
}
img {
width: 80px;
height: 80px;
}
.cart-items .items-thumb > a, .ui-cart .cart-items .items-thumb > i {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
border: 1px solid #fff;
border-radius: 3px;
border: 0 solid rgba(255, 255, 255, .1);
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);
}
.name {
width: 380px;
margin-left: 20px;
color: #323232;
display: table;
a {
color: #333;
font-size: 16px;
}
}
.name-table {
display: table-cell;
vertical-align: middle;
height: 140px;
}
.attribute, .name p {
color: #999;
font-size: 12px;
padding-top: 4px;
line-height: 17px;
}
}
}
.page-cart {
padding-top: 40px;
.fix-bottom {
height: 90px;
width: 100%;
position: absolute;
bottom: 0;
z-index: 1;
background-position: center;
background: #fdfdfd;
background: -webkit-linear-gradient(#fdfdfd, #f9f9f9);
background: linear-gradient(#fdfdfd, #f9f9f9);
border-top: 1px solid #e9e9e9;
box-shadow: 0 -3px 8px rgba(0, 0, 0, .04);
.cart-bottom-bg {
height: 80px;
/*background: url(../img/store/library/cart-wrapper-bg_4c8003c76e.jpg) repeat-x;*/
border-top: 1px solid #D9D9D9;
border-radius: 0 0 8px 8px;
}
}
.cart-bar-operation {
float: left;
padding: 35px 26px;
font-size: 12px;
}
.blue-checkbox-new {
float: left;
margin-right: 9px;
}
.choose-all, .delete-choose-goods, .selected-count {
float: left;
height: 20px;
line-height: 20px;
cursor: pointer;
position: relative;
}
.blue-checkbox-new, .blue-checkbox-new.checkbox-disable, .blue-checkbox-new.checkbox-on {
display: inline-block;
position: relative;
width: 20px;
height: 20px;
background: url(../../../static/images/checkbox-new_631a56a4f6.png) no-repeat 0 -20px;
cursor: pointer;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
vertical-align: middle;
}
.blue-checkbox-new.checkbox-on, .choose-checkbox-on .blue-checkbox-new {
background: url(../../../static/images/checkbox-new_631a56a4f6.png) no-repeat 0 0;
}
.delete-choose-goods {
position: relative;
margin-left: 21px;
color: #bbb;
}
.shipping {
float: right;
padding: 20px 30px;
}
.shipping-box {
display: inline-block;
padding-top: 1px;
margin-right: 10px;
}
.shipping-total {
display: inline-block;
border-left: 1px solid #e1e1e1;
padding: 0 20px;
.shipping-price {
width: 155px;
padding-right: 0;
}
&.shipping-num i {
width: 28px;
display: inline-block;
text-align: center;
}
h4 {
color: #323232;
> i {
font-size: 18px;
font-weight: 700;
}
i, span {
color: #d44d44;
}
}
h5 {
color: #959595;
> i {
font-size: 16px;
font-weight: 700;
}
}
}
.shipping-total.shipping-num {
text-align: right;
}
.shipping-total:first-child {
border: none;
}
.big-main-btn {
float: right;
height: 48px;
}
}
.cart-e {
margin: 0 auto;
background: url("/static/images/cart-empty_@2x.png") no-repeat;
width: 275px;
height: 300px;
color: #8d8d8d;
}
</style>

View File

@@ -0,0 +1,698 @@
<template>
<div class="checkout">
<y-header>
<div slot="nav"></div>
</y-header>
<div class="w" style="padding-top: 40px;">
<!-- 收货地址 -->
<y-shelf title="收货信息">
<div slot="content">
<ul class="address-item-list clearfix">
<li v-for="(item,i) in addList"
:key="i"
class="address pr"
:class="{checked:id === item.id}"
@click="chooseAddress(item.id, item.name, item.phoneNumber, item.detailAddress)">
<span v-if="id === item.id" class="pa">
<svg viewBox="0 0 1473 1024" width="17.34375" height="12">
<path
d="M1388.020 57.589c-15.543-15.787-37.146-25.569-61.033-25.569s-45.491 9.782-61.023 25.558l-716.054 723.618-370.578-374.571c-15.551-15.769-37.151-25.537-61.033-25.537s-45.482 9.768-61.024 25.527c-15.661 15.865-25.327 37.661-25.327 61.715 0 24.053 9.667 45.849 25.327 61.715l431.659 436.343c15.523 15.814 37.124 25.615 61.014 25.615s45.491-9.802 61.001-25.602l777.069-785.403c15.624-15.868 25.271-37.66 25.271-61.705s-9.647-45.837-25.282-61.717M1388.020 57.589z"
fill="#6A8FE5" p-id="1025">
</path>
</svg>
</span>
<p>收货人: {{item.name}} {{item.defaultStatus==1 ? '(默认地址)' : ''}}</p>
<p class="street-name ellipsis">收货地址: {{item.detailAddress}}</p>
<p>手机号码: {{item.phoneNumber}}</p>
<div class="operation-section">
<span class="update-btn" style="font-size:12px" @click="update(item)">修改</span>
<span class="delete-btn" style="font-size:12px" :data-id="item.id" @click="del(item.id)">删除</span>
</div>
</li>
<li class="add-address-item" @click="update()">
<img src="../../../static/svg/jia.svg" alt="">
<p>使用新地址</p>
</li>
</ul>
</div>
</y-shelf>
<!-- 购物清单 -->
<y-shelf title="购物清单">
<div slot="content">
<div class="box-inner ui-cart">
<div>
<!--标题-->
<div class="cart-table-title">
<span class="name">商品信息</span>
<span class="subtotal">小计</span>
<span class="num">数量</span>
<span class="price">单价</span>
</div>
<!--列表-->
<div class="cart-table" v-for="(item,i) in cartList" :key="i" >
<div class="cart-group divide pr" :data-productid="item.productId">
<div class="cart-top-items">
<div class="cart-items clearfix">
<!--图片-->
<div class="items-thumb fl">
<img :alt="item.productName"
:src="item.productPic">
<a @click="goodsDetails(item.productId)" :title="item.productName" target="_blank"></a>
</div>
<!--信息-->
<div class="name hide-row fl">
<div class="name-table">
<a @click="goodsDetails(item.productId)" :title="item.productName" target="_blank"
v-text="item.productName"></a>
<ul class="attribute">
<li>{{item.meno}}</li>
</ul>
</div>
</div>
<!--商品数量-->
<div>
<!--总价格-->
<div class="subtotal" style="font-size: 14px">¥ {{item.price * item.quantity}}</div>
<!--数量-->
<div class="item-cols-num">
<span v-text="item.quantity"></span>
</div>
<!--价格-->
<div class="price">¥ {{item.price}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 合计 -->
<div class="cart-bottom-bg fix-bottom">
<div class="fix-bottom-inner">
<div class="shipping">
<div class="shipping-box" style="padding: 0 40px;">
<div class="shipping-total shipping-price"><h4
class="highlight">应付总额<em>{{checkPrice}}</em>
</h4>
</div>
</div>
<y-button class="big-main-btn"
:classStyle="submit?'disabled-btn':'main-btn'"
style="margin: 0;width: 130px;height: 50px;line-height: 50px;font-size: 16px"
:text="submitOrder"
@btnClick="_submitOrder">
</y-button>
</div>
</div>
</div>
</div>
</div>
</y-shelf>
<y-popup :open="popupOpen" @close='popupOpen=false' :title="popupTitle">
<div slot="content" class="md" :data-id="msg.id">
<div>
<input type="text" placeholder="收货人姓名" v-model="msg.name">
</div>
<div>
<input type="number" placeholder="手机号码" v-model="msg.phoneNumber">
</div>
<div>
<input type="text" placeholder="收货地址" v-model="msg.detailAddress">
</div>
<div>
<el-checkbox class="auto-login" v-model="msg.defaultStatus==1">设为默认</el-checkbox>
</div>
<y-button text='保存'
class="btn"
:classStyle="btnHighlight?'main-btn':'disabled-btn'"
@btnClick="save({id:msg.id,name:msg.name,phoneNumber:msg.phoneNumber,detailAddress:msg.detailAddress,defaultStatus:msg.defaultStatus})">
</y-button>
</div>
</y-popup>
</div>
<y-footer></y-footer>
</div>
</template>
<script>
import { getCartList, addressList, addressUpdate, addressAdd, addressDel, productDet, submitOrder ,submitPreview} from '/api/goods'
import YShelf from '/components/shelf'
import YButton from '/components/YButton'
import YPopup from '/components/popup'
import YHeader from '/common/header'
import YFooter from '/common/footer'
import { getStore } from '/utils/storage'
export default {
data () {
return {
orderInfo:null,
totalAmount: 0,
type:1,
address:{
name:'',
phoneNumber:''
},
cartList:[],
cartId:0,
addressList:null,
calcAmount:null,
shoppingCart:[],
goodsCheckList: [],
addList: [],
id: '0',
popupOpen: false,
popupTitle: '管理收货地址',
num: '', // 立刻购买
productId: '',
msg: {
id: '',
name: '',
phoneNumber: '',
detailAddress: '',
defaultStatus: false
},
name: '',
phoneNumber: '',
detailAddress: '',
userId: '',
orderTotal: 0,
submit: false,
content: '',
submitOrder: '提交订单'
}
},
computed: {
btnHighlight () {
let msg = this.msg
return msg.name && msg.phoneNumber && msg.detailAddress
},
// 选中的总价格
checkPrice () {
let totalPrice = 0
this.cartList && this.cartList.forEach(item => {
totalPrice += (item.quantity * item.price)
})
this.orderTotal = totalPrice
return totalPrice
}
},
methods: {
message (m) {
this.$message.error({
message: m
})
},
goodsDetails (id) {
window.open(window.location.origin + '#/goodsDetails?id=' + id)
},
orderPreview (type,cartId,cart_id_list,total) {
let params = {
'type': type,'cartId':cartId ,'cart_id_list': cart_id_list,'total':total
}
submitPreview(params).then(res => {
this.orderInfo = res.data;
if (res.data.address){
this.address = res.data.address;
}
this.calcAmount =res.data.calcAmount;
this.cartList = res.data.cartPromotionItemList;
if (res.data.memberReceiveAddressList.length) {
this.addList = res.data.memberReceiveAddressList;
this.id = this.addList[0].id || '1'
this.name = this.addList[0].name
this.phoneNumber = this.addList[0].phoneNumber
this.detailAddress = this.addList[0].detailAddress
} else {
this.addList = []
}
})
},
_addressList () {
addressList({userId: this.userId}).then(res => {
let data = res.data
if (data.length) {
this.addList = data
this.id = data[0].id || '1'
this.name = data[0].name
this.phoneNumber = data[0].phoneNumber
this.detailAddress = data[0].detailAddress
} else {
this.addList = []
}
})
},
_addressUpdate (params) {
addressUpdate(params).then(res => {
this._addressList()
})
},
_addressAdd (params) {
addressAdd(params).then(res => {
if (res.code === 200) {
this._addressList()
} else {
this.message(res.msg)
}
})
},
_addressDel (params) {
addressDel(params).then(res => {
this._addressList()
})
},
// 提交订单后跳转付款页面
_submitOrder () {
this.submitOrder = '提交订单中...'
this.submit = true
if (this.id === '0') {
this.message('请选择收货地址')
this.submitOrder = '提交订单'
this.submit = false
return
}
if (this.cartList.length === 0) {
this.message('非法操作')
this.submitOrder = '提交订单'
this.submit = false
return
}
var arr = [];
if (this.cartList ) {
this.cartList.forEach(item => {
arr.push(item.id);
});
}
let params = {
offline:0,
addressId: this.address.id,
payType:2,
type:this.type,
cartIds:arr.join(','),
cartId:this.cartId,
content: this.content
}
submitOrder(params).then(res => {
if (res.code === 200) {
this.payment(res.data.order.id)
} else {
this.message(res.msg)
this.submitOrder = '提交订单'
this.submit = false
}
})
},
// 付款
payment (orderId) {
// 需要拿到地址id
this.$router.push({
path: '/order/payment',
query: {
'orderId': orderId
}
})
},
// 选择地址
chooseAddress (id, name, phoneNumber, detailAddress) {
this.id = id
this.name = name
this.phoneNumber = phoneNumber
this.detailAddress = detailAddress
},
// 修改
update (item) {
this.popupOpen = true
if (item) {
this.popupTitle = '管理收货地址'
this.msg.name = item.name
this.msg.phoneNumber = item.phoneNumber
this.msg.detailAddress = item.detailAddress
this.msg.defaultStatus = item.defaultStatus
this.msg.id = item.id
} else {
this.popupTitle = '新增收货地址'
this.msg.name = ''
this.msg.phoneNumber = ''
this.msg.detailAddress = ''
this.msg.defaultStatus = false
this.msg.id = ''
}
},
// 保存
save (p) {
if(p.defaultStatus=='true'|| p.defaultStatus==true){
p.defaultStatus = 1;
}else{
isDefault =0;
}
this.popupOpen = false
if (p.id) {
this._addressUpdate(p)
} else {
delete p.id
this._addressAdd(p)
}
},
// 删除
del (id) {
this._addressDel({id})
},
},
created () {
this.userId = getStore('userId')
let query = this.$route.query
if (query.type==1 ) {
this.type=1;
this.cartId = query.cartId;
this.orderPreview(1,query.cartId,1,query.total);
} else {
this.type=3;
this.orderPreview(3,1,1,query.total);
}
},
components: {
YShelf,
YButton,
YPopup,
YHeader,
YFooter
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
// 收货地址
.address-item-list {
padding: 30px 13px 0;
.address {
padding: 19px 14px 0 19px;
p {
line-height: 26px;
}
}
li.checked {
border-color: #6A8FE5;
position: relative;
background: #fff;
.pa {
right: 15px;
top: 18px;
}
&:hover {
background: #fff;
}
}
li {
position: relative;
overflow: hidden;
float: left;
width: 276px;
height: 158px;
margin: 0 0 30px 16px;
border: 1px solid #E5E5E5;
border-radius: 3px;
background: #FAFAFA;
line-height: 14px;
text-align: left;
word-wrap: break-word;
word-break: normal;
color: #626262;
cursor: pointer;
-moz-user-select: -moz-none;
-webkit-user-select: none;
-o-user-select: none;
user-select: none;
&:hover {
background: #F2F2F2;
.operation-section {
visibility: visible;
transform: translate(0, 0);
}
}
&.add-address-item {
text-align: center;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
p {
margin-top: 5px;
}
}
.operation-section {
visibility: hidden;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 28px;
background: #E1E1E1;
border-top: 1px solid #E1E1E1;
transition: all .2s ease;
transform: translate(0, 29px);
border-top: 1px solid #E1E1E1;
display: flex;
align-items: center;
justify-content: center;
z-index: 11;
span {
background: #fff;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
&:hover {
background: #F2F2F2;
}
}
span + span {
border-left: 1px solid #E1E1E1;
}
}
}
}
.s-content {
.md {
> div {
text-align: left;
margin-bottom: 15px;
> input {
width: 100%;
height: 50px;
font-size: 18px;
padding: 10px 20px;
border: 1px solid #ccc;
border-radius: 6px;
box-shadow: 0 3px 5px -4px rgba(0, 0, 0, .4) inset, -1px 0 3px -2px rgba(0, 0, 0, .1) inset;
line-height: 46px;
}
}
}
.btn {
margin: 0;
width: 100%;
height: 50px;
font-size: 14px;
line-height: 48px
}
}
.ui-cart {
img {
width: 80px;
height: 80px;
}
.cart-table-title {
position: relative;
z-index: 1;
line-height: 38px;
height: 38px;
padding: 0 0 0 30px;
font-size: 12px;
background: #eee;
border-bottom: 1px solid #dbdbdb;
border-bottom-color: rgba(0, 0, 0, .08);
.name {
float: left;
text-align: left;
}
span {
width: 137px;
float: right;
text-align: center;
color: #838383;
}
}
.cart-group.divide {
.cart-items {
border-top: 1px dashed #eee;
}
}
.cart-items {
position: relative;
height: 140px;
margin-left: 74px;
.subtotal {
font-weight: 700;
}
.item-cols-num,
.price,
.subtotal {
overflow: hidden;
float: right;
width: 137px;
text-align: center;
color: #666;
line-height: 140px;
}
/*数量*/
.subtotal,
.item-cols-num {
padding-top: 50px;
line-height: 40px;
}
.select {
width: 112px;
height: 40px;
padding-top: 4px;
margin: 0 auto;
line-height: 40px;
.down {
background-position: 0 -60px;
}
.down.down-disabled:hover {
background-position: 0 -300px;
cursor: not-allowed;
}
.num {
position: relative;
overflow: hidden;
display: inline-block;
width: 36px;
height: 18px;
margin: 7px 0 0;
border: none;
border-radius: 3px;
line-height: 18px;
text-align: center;
font-size: 14px;
transition: all .2s ease-out;
}
}
}
.down.down-disabled {
background-position: 0 -300px;
cursor: not-allowed;
}
}
.cart-group.divide .cart-top-items:first-child .cart-items {
border-top: none;
}
.items-choose {
position: absolute;
left: -74px;
top: 0;
width: 74px;
height: 20px;
padding: 60px 0 0 31px;
font-size: 12px;
color: #999;
}
.items-thumb {
position: relative;
margin-top: 30px;
overflow: hidden;
width: 80px;
height: 80px;
}
.cart-items .items-thumb > a, .ui-cart .cart-items .items-thumb > i {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
border: 1px solid #fff;
border-radius: 3px;
border: 0 solid rgba(255, 255, 255, .1);
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);
}
.name {
width: 380px;
margin-left: 20px;
color: #323232;
display: table;
a {
color: #333;
font-size: 16px;
}
}
.name-table {
display: table-cell;
vertical-align: middle;
height: 140px;
}
.fix-bottom {
padding: 22px 29px 19px 30px;
height: 90px;
width: 100%;
z-index: 1;
background-position: center;
background: #fdfdfd;
background: -webkit-linear-gradient(#fdfdfd, #f9f9f9);
background: linear-gradient(#fdfdfd, #f9f9f9);
border-top: 1px solid #e9e9e9;
box-shadow: 0 -3px 8px rgba(0, 0, 0, .04);
.cart-bottom-bg {
height: 80px;
border-top: 1px solid #D9D9D9;
border-radius: 0 0 8px 8px;
}
.fix-bottom-inner {
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
}
.shipping {
display: flex;
align-items: center;
}
em {
display: inline-block;
position: relative;
top: 3px;
margin-top: -4px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
}
}
.attribute, .name p {
color: #999;
font-size: 12px;
padding-top: 4px;
line-height: 17px;
}
</style>

View File

@@ -0,0 +1,270 @@
<template>
<div class="goods">
<div class="nav">
<div class="w">
<a href="javascript:;" :class="{active:sortType===1}" @click="reset()">综合排序</a>
<a href="javascript:;" @click="sortByPrice(1)" :class="{active:sortType===2}">价格从低到高</a>
<a href="javascript:;" @click="sortByPrice(-1)" :class="{active:sortType===3}">价格从高到低</a>
<div class="price-interval">
<input type="number" class="input" placeholder="价格" v-model="min">
<span style="margin: 0 5px"> - </span>
<input type="number" placeholder="价格" v-model="max">
<y-button text="确定" classStyle="main-btn" @btnClick="reset" style="margin-left: 10px;"></y-button>
</div>
</div>
</div>
<div v-loading="loading" element-loading-text="加载中..." style="min-height: 35vw;">
<div class="img-item" v-if="!noResult">
<!--商品-->
<div class="goods-box w">
<mall-goods v-for="(item,i) in goods" :key="i" :msg="item"></mall-goods>
</div>
<el-pagination
v-if="!noResult&&!error"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[8, 20, 40, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<div class="no-info" v-if="noResult">
<div class="no-data">
<img src="/static/images/no-search.png">
<br> 抱歉暂时还没有商品
</div>
<section class="section">
<y-shelf :title="retitle">
<div slot="content" class="recommend">
<mall-goods :msg="item" v-for="(item,i) in recommendGoods" :key="i"></mall-goods>
</div>
</y-shelf>
</section>
</div>
<div class="no-info" v-if="error">
<div class="no-data">
<img src="/static/images/error.png">
<br> 抱歉出错了...
</div>
<section class="section">
<y-shelf :title="retitle">
<div slot="content" class="recommend">
<mall-goods :msg="item" v-for="(item,i) in recommendGoods" :key="i"></mall-goods>
</div>
</y-shelf>
</section>
</div>
</div>
</div>
</template>
<script>
import { getAllGoods } from '/api/goods.js'
import { recommend } from '/api/index.js'
import mallGoods from '/components/mallGoods'
import YButton from '/components/YButton'
import YShelf from '/components/shelf'
export default {
data () {
return {
goods: [],
retitle:'',
noResult: false,
error: false,
min: '',
max: '',
loading: true,
timer: null,
sortType: 1,
windowHeight: null,
windowWidth: null,
recommendPanel: null,
recommendGoods: null,
sort: 'price asc',
currentPage: 1,
total: 0,
pageSize: 20
}
},
methods: {
handleSizeChange (val) {
this.pageSize = val
this._getAllGoods()
this.loading = true
},
handleCurrentChange (val) {
this.currentPage = val
this._getAllGoods()
this.loading = true
},
_getAllGoods () {
let cid = this.$route.query.cid
if (this.min !== '') {
this.min = Math.floor(this.min)
}
if (this.max !== '') {
this.max = Math.floor(this.max)
}
let params = {
pageNum: this.currentPage,
pageSize: this.pageSize,
productCategoryId: cid
}
getAllGoods(params).then(res => {
if (res.code === 200) {
this.total = res.data.total
this.goods = res.data.records
this.noResult = false
if (this.total === 0) {
this.noResult = true
}
this.error = false
} else {
this.error = true
}
this.loading = false
})
},
// 默认排序
reset () {
this.sortType = 1
this.sort = 'price asc'
this.currentPage = 1
this.loading = true
this._getAllGoods()
},
// 价格排序
sortByPrice (v) {
if (v === 1){
this.sort = 'price asc';
}else{
this.sort = 'price desc';
}
this.currentPage = 1
this.loading = true
this._getAllGoods()
}
},
watch: {
$route (to, from) {
if (to.fullPath.indexOf('/goods?cid=') >= 0) {
this.cId = to.query.cid
this._getAllGoods()
}
}
},
created () {
},
mounted () {
this.windowHeight = window.innerHeight
this.windowWidth = window.innerWidth
this._getAllGoods()
recommend().then(res => {
let datas = res.data
this.recommendGoods = datas;
this.retitle='推荐商品';
// this.recommendPanel = datas[0]
})
},
components: {
mallGoods,
YButton,
YShelf
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "../../assets/style/mixin";
@import "../../assets/style/theme";
.nav {
height: 60px;
line-height: 60px;
> div {
display: flex;
align-items: center;
a {
padding: 0 15px;
height: 100%;
@extend %block-center;
font-size: 12px;
color: #999;
&.active {
color: #5683EA;
}
&:hover {
color: #5683EA;
}
}
input {
@include wh(80px, 30px);
border: 1px solid #ccc;
}
input + input {
margin-left: 10px;
}
}
.price-interval {
padding: 0 15px;
@extend %block-center;
input[type=number] {
border: 1px solid #ccc;
text-align: center;
background: none;
border-radius: 5px;
}
}
}
.goods-box {
> div {
float: left;
border: 1px solid #efefef;
}
}
.no-info {
padding: 100px 0;
text-align: center;
font-size: 30px;
display: flex;
flex-direction: column;
.no-data{
align-self: center;
}
}
.img-item{
display: flex;
flex-direction: column;
}
.el-pagination{
align-self: flex-end;
margin: 3vw 10vw 2vw;
}
.section {
padding-top: 8vw;
margin-bottom: -5vw;
width: 1218px;
align-self: center;
}
.recommend {
display: flex;
> div {
flex: 1;
width: 25%;
}
}
</style>

View File

@@ -0,0 +1,336 @@
<!--商品详情-->
<template>
<div class="w store-content">
<div class="gray-box">
<div class="gallery-wrapper">
<div class="gallery">
<div class="thumbnail">
<ul>
<li v-for="(item,i) in small" :key="i" :class="{on:big===item}" @click="big=item">
<img v-lazy="item" :alt="product.name">
</li>
</ul>
</div>
<div class="thumb">
<div class="big">
<img :src="big" :alt="product.name">
</div>
</div>
</div>
</div>
<!--右边-->
<div class="banner">
<div class="sku-custom-title">
<h4>{{product.name}}</h4>
<h6>
<span>{{product.subTitle}}</span>
<span class="price">
<em>¥</em><i>{{product.price}}</i></span>
</h6>
</div>
<!-- 选择规格 -->
<div class="item-select">
<div class="item-select-title">
<p>规格</p>
</div>
<div class="item-select-column">
<div class="item-select-row" v-for="(item, index) in skuList" :key="index">
<div class="item-select-box" @click="select(item.id)" :class="{'item-select-box-active': index === selectBoxIndex}">
<div class="item-select-img">
<img :src="item.pic" alt="">
</div>
<div class="item-select-intro">
<p>{{item.meno}}</p>
</div>
</div>
</div>
</div>
</div>
<div class="num">
<span class="params-name">数量</span>
<buy-num @edit-num="editNum" ></buy-num>
</div>
<div class="buy">
<y-button text="加入购物车"
@btnClick="addCart(product.id,product.price,product.name,product.pic)"
classStyle="main-btn"
style="width: 145px;height: 50px;line-height: 48px"></y-button>
<y-button text="现在购买"
@btnClick="checkout(product.id)"
style="width: 145px;height: 50px;line-height: 48px;margin-left: 10px"></y-button>
</div>
</div>
</div>
<!--产品信息-->
<div class="item-info">
<y-shelf title="产品信息">
<div slot="content">
<div class="img-item" v-if="productMsg">
<div v-html="productMsg">{{ productMsg }}</div>
</div>
<div class="no-info" v-else>
<img src="/static/images/no-data.png">
<br>
该商品暂无内容数据
</div>
</div>
</y-shelf>
</div>
</div>
</template>
<script>
import { productDet, addCart } from '/api/goods'
import { mapMutations, mapState } from 'vuex'
import YShelf from '/components/shelf'
import BuyNum from '/components/buynum'
import YButton from '/components/YButton'
import { getStore } from '/utils/storage'
export default {
data () {
return {
productMsg: {},
selectBoxIndex:0,
skuList:[],
small: [],
big: '',
product: {
salePrice: 0
},
productNum: 1,
userId: ''
}
},
computed: {
...mapState(['login', 'showMoveImg', 'showCart'])
},
methods: {
...mapMutations(['ADD_CART', 'ADD_ANIMATION', 'SHOW_CART']),
_productDet (id) {
productDet({id: id}).then(res => {
let result = res.data;
this.product = result.goods.goods;
this.skuList = result.goods.skuStockList;
this.productMsg = this.product.detailHtml || ''
var subImages = this.product.albumPics;
this.small = subImages.split(',');
this.big = this.small[0]
})
},
select(index1) {
this.selectBoxIndex = index1 ;
},
addCart (id, price, name, img) {
var userInfo = getStore('userInfo');
if (!userInfo) {
this.$router.push({ path: '/login' })
}
if (!this.showMoveImg) { // 动画是否在运动
let params ;
const skuid = parseInt(this.selectBoxIndex);
if (!skuid){
params = {
goodsId: this.product.id, total: this.productNum
}
}else{
params = {
goodsId: this.product.id, total: this.productNum, skuId:skuid,
}
}
addCart(params).then(res => {
// 并不重新请求数据
this.ADD_CART({
id: id,
salePrice: price,
productName: name,
productImg: img,
productNum: this.productNum
})
})
// 加入购物车动画
var dom = event.target
// 获取点击的坐标
let elLeft = dom.getBoundingClientRect().left + (dom.offsetWidth / 2)
let elTop = dom.getBoundingClientRect().top + (dom.offsetHeight / 2)
// 需要触发
this.ADD_ANIMATION({moveShow: true, elLeft: elLeft, elTop: elTop, img: img})
if (!this.showCart) {
this.SHOW_CART({showCart: true})
}
}
},
checkout (id) {
var userInfo = getStore('userInfo');
if (!userInfo) {
this.$router.push({ path: '/login' })
}
const skuid = parseInt(this.selectBoxIndex);
let params ;
if (!skuid){
params = {
goodsId: this.product.id, total: this.productNum
}
}else{
params = {
goodsId: this.product.id, total: this.productNum, skuId:skuid,
}
}
addCart(params).then(res => {
this.$router.push({path: '/checkout', query: {'cartId':res.data.id, 'total': this.productNum,'type':1}})
})
},
editNum (num) {
this.productNum = num
}
},
components: {
YShelf, BuyNum, YButton
},
created () {
let id = this.$route.query.id
this._productDet(id)
this.userId = getStore('userId')
}
}
</script>
<style lang="scss" scoped>
@import "../../assets/style/mixin";
.store-content {
clear: both;
width: 1220px;
min-height: 600px;
padding: 0 0 25px;
margin: 0 auto;
}
.gray-box {
display: flex;
padding: 60px;
margin: 20px 0;
.gallery-wrapper {
.gallery {
display: flex;
width: 540px;
.thumbnail {
li:first-child {
margin-top: 0px;
}
li {
@include wh(80px);
margin-top: 10px;
padding: 12px;
border: 1px solid #f0f0f0;
border: 1px solid rgba(0, 0, 0, .06);
border-radius: 5px;
cursor: pointer;
&.on {
padding: 10px;
border: 3px solid #ccc;
border: 3px solid rgba(0, 0, 0, .2);
}
img {
display: block;
@include wh(100%);
}
}
}
.thumb {
.big {
margin-left: 20px;
}
img {
display: block;
@include wh(440px)
}
}
}
}
// 右边
.banner {
width: 450px;
margin-left: 10px;
h4 {
font-size: 24px;
line-height: 1.25;
color: #000;
margin-bottom: 13px;
}
h6 {
font-size: 14px;
line-height: 1.5;
color: #bdbdbd;
display: flex;
align-items: center;
justify-content: space-between;
}
.sku-custom-title {
overflow: hidden;
padding: 8px 8px 18px 10px;
position: relative;
}
.params-name {
padding-right: 20px;
font-size: 14px;
color: #8d8d8d;
line-height: 36px;
}
.num {
padding: 29px 0 8px 10px;
border-top: 1px solid #ebebeb;
display: flex;
align-items: center;
}
.buy {
position: relative;
border-top: 1px solid #ebebeb;
padding: 30px 0 0 10px;
}
}
}
.item-info {
.gray-box {
padding: 0;
display: block;
}
.img-item {
width: 1220px;
// padding: 1vw;
text-align: center;
img {
width: 100%;
height: auto;
display: block;
}
}
}
.no-info {
padding: 200px 0;
text-align: center;
font-size: 30px;
}
.price {
display: block;
color: #d44d44;
font-weight: 700;
font-size: 16px;
line-height: 20px;
text-align: right;
i {
padding-left: 2px;
font-size: 24px;
}
}
</style>

View File

@@ -0,0 +1,510 @@
<template>
<div class="home">
<div v-loading="loading" element-loading-text="加载中..." style="min-height: 35vw;" v-if="!error">
<div class="banner" >
<div class="bg" ref="bg"
@mouseover="bgOver($refs.bg)" @mousemove="bgMove($refs.bg,$event)" @mouseout="bgOut($refs.bg)">
<transition name="fade">
<div v-for="(item, i) in banner" v-if="i===mark" :key="i" style="position:absolute" @click="linkTo(item)" @mouseover="stopTimer" @mouseout="startTimer">
<img v-if="item.pic" class="img1" :src="item.pic"/>
</div>
</transition>
</div>
<div class="page">
<ul class="dots">
<li class="dot-active" v-for="(item, i) in banner" :class="{ 'dot':i!=mark }" :key="i" @click="change(i)"></li>
</ul>
</div>
</div>
<div>
<div class="activity-panel" >
<ul class="box">
<li class="content" v-for="(iitemk,k) in home.brandList" :key="k" @click="linkToBrand(iitemk)">
<img class="i" :src="iitemk.logo">
<a class="cover-link"></a>
</li>
</ul>
</div>
<section class="w mt30 clearfix">
<y-shelf >
<div slot="content" class="hot">
<mall-goods :msg="iitem" v-for="(iitem,j) in home.newProductList" :key="j"></mall-goods>
</div>
</y-shelf>
</section>
<section class="w mt30 clearfix" v-for="(cat,i) in home.cat_list" :key="i" v-if="cat.goodsList.length>0">
<y-shelf :title="cat.name">
<div slot="content" class="floors" >
<div class="imgbanner" v-for="(iitem,j) in cat.goodsList" :key="j" v-if="iitem.type === 1 " @click="linkTo(iitem)">
<img v-lazy="iitem.pic">
<a class="cover-link"></a>
</div>
<mall-goods :msg="iitem" v-for="(iitem,j) in cat.goodsList" :key="j+'key'" ></mall-goods>
</div>
</y-shelf>
</section>
</div>
</div>
<div class="no-info" v-if="error">
<div class="no-data">
<img src="/static/images/error.png">
<br> 抱歉出错了...
</div>
</div>
<el-dialog
title="通知"
:visible.sync="dialogVisible"
width="30%"
style="width:70%;margin:0 auto">
<span>首页已升级XPay个人支付收款系统已上线赶快去支付体验吧</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">知道了</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { productHome } from '/api/index.js'
import YShelf from '/components/shelf'
import product from '/components/product'
import mallGoods from '/components/mallGoods'
import { setStore, getStore } from '/utils/storage.js'
export default {
data () {
return {
title:'新品上市',
error: false,
banner: [],
mark: 0,
bgOpt: {
px: 0,
py: 0,
w: 0,
h: 0
},
home: [],
loading: true,
notify: '1',
dialogVisible: false,
timer: ''
}
},
methods: {
autoPlay () {
this.mark++
if (this.mark > this.banner.length - 1) {
// 当遍历到最后一张图片置零
this.mark = 0
}
},
play () {
// 每2.5s自动切换
this.timer = setInterval(this.autoPlay, 2500)
},
change (i) {
this.mark = i
},
startTimer () {
this.timer = setInterval(this.autoPlay, 2500)
},
stopTimer () {
clearInterval(this.timer)
},
linkTo (item) {
// 关联商品
this.$router.push({
path: '/goodsDetails',
query: {
id: item.productId
}
})
},
linkToBrand (item) {
// 关联品牌
this.$router.push({
path: '/goodsDetails',
query: {
id: item.productId
}
})
},
linkToUrl (item) {
// 完整链接
window.location.href = item.fullUrl
},
bgOver (e) {
this.bgOpt.px = e.offsetLeft
this.bgOpt.py = e.offsetTop
this.bgOpt.w = e.offsetWidth
this.bgOpt.h = e.offsetHeight
},
bgMove (dom, eve) {
let bgOpt = this.bgOpt
let X, Y
let mouseX = eve.pageX - bgOpt.px
let mouseY = eve.pageY - bgOpt.py
if (mouseX > bgOpt.w / 2) {
X = mouseX - (bgOpt.w / 2)
} else {
X = mouseX - (bgOpt.w / 2)
}
if (mouseY > bgOpt.h / 2) {
Y = bgOpt.h / 2 - mouseY
} else {
Y = bgOpt.h / 2 - mouseY
}
dom.style['transform'] = `rotateY(${X / 50}deg) rotateX(${Y / 50}deg)`
dom.style.transform = `rotateY(${X / 50}deg) rotateX(${Y / 50}deg)`
},
bgOut (dom) {
dom.style['transform'] = 'rotateY(0deg) rotateX(0deg)'
dom.style.transform = 'rotateY(0deg) rotateX(0deg)'
},
showNotify () {
var value = getStore('notify')
if (this.notify !== value) {
this.dialogVisible = true
setStore('notify', this.notify)
}
}
},
mounted () {
productHome().then(res => {
if (res.success === false) {
this.error = true
return
}
let data = res.data
this.home = data
this.loading = false
this.banner = data.advertiseList
})
this.showNotify()
},
created () {
this.play()
},
components: {
YShelf,
product,
mallGoods
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.home {
display: flex;
flex-direction: column;
}
.no-info {
padding: 100px 0;
text-align: center;
font-size: 30px;
display: flex;
flex-direction: column;
.no-data{
align-self: center;
}
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
.page {
position: absolute;
width: 100%;
top: 470px;
z-index: 30;
.dots {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.dot-active {
display: inline-block;
width: 15px;
height: 15px;
background-color: whitesmoke;
border-radius: 8px;
margin-right: 10px;
cursor: pointer;
}
.dot {
opacity: 0.2;
}
}
}
.activity-panel {
width: 1220px;
margin: 0 auto;
.box {
overflow: hidden;
position: relative;
z-index: 0;
margin-top: 25px;
box-sizing: border-box;
border: 1px solid rgba(0,0,0,.14);
border-radius: 8px;
background: #fff;
box-shadow: 0 3px 8px -6px rgba(0,0,0,.1);
}
.content {
float: left;
position: relative;
box-sizing: border-box;
width: 25%;
height: 200px;
text-align: center;
}
.content ::before{
position: absolute;
top: 0;
left: 0;
z-index: 1;
box-sizing: border-box;
border-left: 1px solid #f2f2f2;
border-left: 1px solid rgba(0,0,0,.1);
width: 100%;
height: 100%;
content: "";
pointer-events: none;
}
.i {
width: 305px;
height: 200px;
}
.cover-link {
cursor: pointer;
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 4;
background: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEHAAEALAAAAAABAAEAAAICTAEAOw==) repeat;
}
a {
color: #5079d9;
cursor: pointer;
transition: all .15s ease-out;
text-decoration: none;
}
a:hover {
box-shadow: inset 0 0 38px rgba(0,0,0,.08);
transition: all .15s ease;
}
}
.banner, .banner span, .banner div {
font-family: "Microsoft YaHei";
transition: all .3s;
transition-timing-function: linear;
}
.banner {
cursor: pointer;
perspective: 3000px;
position: relative;
z-index: 19;
margin: 0 auto;
width: 1220px;
}
.bg {
position: relative;
width: 1220px;
height: 500px;
margin: 20px auto;
background-size: 100% 100%;
border-radius: 10px;
transform-style: preserve-3d;
transform-origin: 50% 50%;
transform: rotateY(0deg) rotateX(0deg);
& div{
position: relative;
height: 100%;
width: 100%;
}
}
.img1 {
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
border-radius: 10px;
}
.img2 {
display: block;
position: absolute;
width: 100%;
height: 100%;
bottom: 5px;
left: 0;
background-size: 95% 100%;
border-radius: 10px;
}
.img3 {
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
border-radius: 10px;
}
.a {
z-index: 20;
transform: translateZ(40px);
}
.b {
z-index: 20;
transform: translateZ(30px);
}
.c {
transform: translateZ(0px);
}
.sk_item {
width: 170px;
height: 225px;
padding: 0 14px 0 15px;
> div {
width: 100%;
}
a {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: all .3s;
&:hover {
transform: translateY(-5px);
}
}
img {
width: 130px;
height: 130px;
margin: 17px 0;
}
.sk_item_name {
color: #999;
display: block;
max-width: 100%;
_width: 100%;
overflow: hidden;
font-size: 12px;
text-align: left;
height: 32px;
line-height: 16px;
word-wrap: break-word;
word-break: break-all;
}
.sk_item_price {
padding: 3px 0;
height: 25px;
}
.price_new {
font-size: 18px;
font-weight: 700;
margin-right: 8px;
color: #f10214;
}
.price_origin {
color: #999;
font-size: 12px;
}
}
.box {
overflow: hidden;
position: relative;
z-index: 0;
margin-top: 29px;
box-sizing: border-box;
border: 1px solid rgba(0, 0, 0, .14);
border-radius: 8px;
background: #fff;
box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);
}
ul.box {
display: flex;
li {
flex: 1;
img {
display: block;
width: 305px;
height: 200px;
}
}
}
.mt30 {
margin-top: 30px;
}
.hot {
display: flex;
> div {
flex: 1;
width: 25%;
}
}
.floors {
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: center;
.imgbanner {
width: 50%;
height: 430px;
.cover-link {
cursor: pointer;
display: block;
position: absolute;
top: 60px;
left: 0;
width: 50%;
height: 430px;
z-index: 4;
background: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEHAAEALAAAAAABAAEAAAICTAEAOw==) repeat;
}
.cover-link:hover {
box-shadow: inset 0 0 38px rgba(0,0,0,.08);
transition: all .15s ease;
}
}
img {
display: block;
width: 100%;
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,426 @@
<template>
<div class="login v2">
<div class="wrapper">
<div class="dialog dialog-shadow" style="display: block; margin-top: -362px;">
<div class="title">
<h4>使用 宇运动 账号 登录官网</h4>
</div>
<div v-if="loginPage" class="content">
<ul class="common-form">
<li class="phone border-1p">
<div class="input">
<input type="text" v-model="ruleForm.phone" placeholder="账号">
</div>
</li>
<li>
<div class="input">
<input type="password" v-model="ruleForm.password" @keyup.enter="login" placeholder="密码">
</div>
</li>
<!--<li>
<div id="captcha">
<p id="wait">正在加载验证码...</p>
</div>
</li>-->
<li style="text-align: right" class="pr">
<el-checkbox class="auto-login" v-model="autoLogin">记住密码</el-checkbox>
<!-- <span class="pa" style="top: 0;left: 0;color: #d44d44">{{ruleForm.errMsg}}</span> -->
<a href="javascript:;" class="register" @click="toRegister">注册 宇运动 账号</a>
<a style="padding: 1px 0 0 10px" @click="open('找回密码','请联系作者邮箱找回密码或使用测试账号登录test | test')">忘记密码 ?</a>
</li>
</ul>
<!--登陆-->
<div style="margin-top: 25px">
<y-button :text="logintxt"
:classStyle="ruleForm.password&& ruleForm.phone&& logintxt === '登录'?'main-btn':'disabled-btn'"
@btnClick="login"
style="margin: 0;width: 100%;height: 48px;font-size: 18px;line-height: 48px"></y-button>
</div>
<!--返回-->
<div>
<y-button text="返回" @btnClick="login_back"
style="marginTop: 10px;marginBottom: 15px;width: 100%;height: 48px;font-size: 18px;line-height: 48px">
</y-button>
</div>
<div class="border"></div>
<div class="footer">
<div class="other">其它账号登录</div>
<a><img @click="open('待开发','此功能开发中...')" style="height: 15px; margin-top: 22px;" src="/static/images/other-login.png"></a>
</div>
</div>
</div>
</div>
</div>
</template>
<script src="../../../static/geetest/gt.js"></script>
<script>
import YFooter from '/common/footer'
import YButton from '/components/YButton'
import { userLogin, geetest } from '/api/index.js'
import { addCart } from '/api/goods.js'
import { setStore, getStore, removeStore } from '/utils/storage.js'
require('../../../static/geetest/gt.js')
var captcha
export default {
data () {
return {
cart: [],
loginPage: true,
ruleForm: {
phone: '13146587722',
password: '123456',
errMsg: ''
},
registered: {
phone: '',
password: '',
password2: '',
errMsg: ''
},
autoLogin: false,
logintxt: '登录',
statusKey: ''
}
},
computed: {
count () {
return this.$store.state.login
}
},
methods: {
open (t, m) {
this.$notify.info({
title: t,
message: m
})
},
messageSuccess () {
this.$message({
message: '恭喜您,注册成功!赶紧登录体验吧',
type: 'success'
})
},
message (m) {
this.$message.error({
message: m
})
},
getRemembered () {
var judge = getStore('remember')
if (judge === 'true') {
this.autoLogin = true
this.ruleForm.phone = getStore('rphone')
this.ruleForm.password = getStore('rpassword')
}
},
rememberPass () {
if (this.autoLogin === true) {
setStore('remember', 'true')
setStore('rphone', this.ruleForm.phone)
setStore('rpassword', this.ruleForm.password)
} else {
setStore('remember', 'false')
removeStore('rphone')
removeStore('rpassword')
}
},
toRegister () {
this.$router.push({
path: '/register'
})
},
// 登录返回按钮
login_back () {
this.$router.go(-1)
},
// 登陆时将本地的添加到用户购物车
login_addCart () {
let cartArr = []
let locaCart = JSON.parse(getStore('buyCart'))
if (locaCart && locaCart.length) {
locaCart.forEach(item => {
cartArr.push({
userId: getStore('userId'),
productId: item.productId,
productNum: item.productNum
})
})
}
this.cart = cartArr
},
login () {
this.logintxt = '登录中...'
this.rememberPass()
if (!this.ruleForm.phone || !this.ruleForm.password) {
// this.ruleForm.errMsg = '账号或者密码不能为空!'
this.message('账号或者密码不能为空!')
return false
}
/*var result = captcha.getValidate()
if (!result) {
this.message('请完成验证')
this.logintxt = '登录'
return false
}*/
let params = {
phone: this.ruleForm.phone,
password: this.ruleForm.password
}
userLogin(params).then(res => {
if (res.code === 200) {
const datas = res.data
const tokenStr = datas.tokenHead+datas.token
setStore('token', tokenStr)
setStore('userInfo', datas.userInfo)
// 登录后添加当前缓存中的购物车
if (this.cart.length) {
for (var i = 0; i < this.cart.length; i++) {
addCart(this.cart[i]).then(res => {
if (res.code === 200) {
}
})
}
removeStore('buyCart')
this.$router.push({
path: '/'
})
} else {
this.$router.push({
path: '/'
})
}
} else {
this.logintxt = '登录'
this.message(res.msg)
// captcha.reset()
return false
}
})
},
init_geetest () {
geetest().then(res => {
this.statusKey = res.statusKey
window.initGeetest({
gt: res.gt,
challenge: res.challenge,
new_captcha: res.new_captcha,
offline: !res.success,
product: 'popup',
width: '100%'
}, function (captchaObj) {
captcha = captchaObj
captchaObj.appendTo('#captcha')
captchaObj.onReady(function () {
document.getElementById('wait').style.display = 'none'
})
})
})
}
},
mounted () {
this.getRemembered()
this.login_addCart()
// this.init_geetest()
this.open('登录提示', '测试体验账号密码13146587722 | 123456')
},
components: {
YFooter,
YButton
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
* {
box-sizing: content-box;
}
.login {
overflow-x: hidden;
overflow-y: hidden;
.input {
height: 50px;
display: flex;
align-items: center;
input {
font-size: 16px;
width: 100%;
height: 100%;
padding: 10px 15px;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 6px;
}
}
.wrapper {
background: url(/static/images/bg_9b9dcb65ff.png) repeat;
background-size: 100px;
min-height: 800px;
min-width: 630px;
}
}
.v2 .dialog {
width: 450px;
border: 1px solid #dadada;
border-radius: 10px;
top: 50%;
left: 50%;
margin-left: -225px;
position: absolute;
.title {
background: linear-gradient(#fff, #f5f5f5);
height: auto;
overflow: visible;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
position: relative;
background-image: url(/static/images/smartisan_4ada7fecea.png);
background-size: 140px;
background-position: top center;
background-repeat: no-repeat;
height: 92px;
margin: 23px 0 50px;
padding: 75px 0 0;
box-shadow: none;
h4 {
padding: 0;
text-align: center;
color: #666;
border-bottom: 1px solid #dcdcdc;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
font-weight: 700;
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
margin: 0;
padding: 0;
border-bottom: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
line-height: 1em;
height: auto;
color: #333;
font-weight: 400;
}
}
.content {
padding: 0 40px 22px;
height: auto;
.common-form {
li {
clear: both;
margin-bottom: 15px;
position: relative;
}
}
}
}
.dialog-shadow,
.v2 .bbs .dialog-shadow,
.v2 .dialog-shadow {
-webkit-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),
0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),
0 10px 20px -10px rgba(0, 0, 0, 0.04);
-moz-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),
0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),
0 10px 20px -10px rgba(0, 0, 0, 0.04);
box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),
0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),
0 10px 20px -10px rgba(0, 0, 0, 0.04);
}
@media screen and (min-width: 737px),
screen and (-webkit-max-device-pixel-ratio: 1.9) and (max-width: 736px) and (min-device-width: 737px) {
.wrapper {
background: url(/static/images/con-bg_04f25dbf8e.jpg) repeat-x;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.dialog {
background: url(/static/images/dialog-gray-bg.png) #fff bottom repeat-x;
border-radius: 12px;
display: none;
margin: -163px 0 0 -218px;
width: 436px;
position: fixed;
left: 50%;
top: 50%;
}
.dialog .title h4 {
border-bottom: #d1d1d1 solid 1px;
box-shadow: 0 2px 6px #d1d1d1;
color: #666;
font-size: 20px;
height: 61px;
line-height: 61px;
padding: 0 0 0 35px;
}
.common-form li {
clear: both;
margin-bottom: 15px;
position: relative;
}
.auto-login {
position: absolute;
top: 0px;
left: 2px;
color: #999;
}
.register {
padding: 1px 10px 0;
border-right: 1px solid #ccc;
}
.border {
margin-top: 10px;
border-bottom: 1px solid #ccc;
}
.other {
margin: 20px 5px 0 0;
width: auto;
color: #bbb;
font-size: 12px;
cursor: default;
color: #999;
}
.footer {
display: flex;
flex-direction: row;
}
.agree {
margin-bottom: 30px;
color: #999;
}
}
.registered {
h4 {
padding: 0;
text-align: center;
color: #666;
border-bottom: 1px solid #dcdcdc;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
font-weight: 700;
font-size: 20px;
height: 60px;
line-height: 60px;
}
}
#wait {
text-align: left;
color: #999;
margin: 0;
}
</style>

View File

@@ -0,0 +1,363 @@
<template>
<div class="login v2">
<div class="wrapper">
<div class="dialog dialog-shadow" style="display: block; margin-top: -362px;">
<div class="registered">
<h4>注册 mallcloud 账号</h4>
<div class="content" style="margin-top: 20px;">
<ul class="common-form">
<li class="phone border-1p">
<div style="margin-top: 40px;" class="input">
<input type="text"
v-model="registered.phone" placeholder="账号"
@keyup="registered.phone=registered.phone.replace(/[^\w\.\/]/ig,'')">
</div>
</li>
<li>
<div class="input">
<input type="password"
v-model="registered.password"
placeholder="密码">
</div>
</li>
<li>
<div class="input">
<input type="password"
v-model="registered.confimpassword"
placeholder="重复密码">
</div>
</li>
<!-- <li>
<div id="captcha">
<p id="wait">正在加载验证码...</p>
</div>
</li>-->
</ul>
<el-checkbox class="agree" v-model="agreement">
我已阅读并同意遵守
<a @click="open('法律声明','此仅为个人练习开源模仿项目,仅供学习参考,承担不起任何法律问题')">法律声明</a>
<a @click="open('隐私条款','本网站将不会严格遵守有关法律法规和本隐私政策所载明的内容收集、使用您的信息')">隐私条款</a>
</el-checkbox>
<div style="margin-bottom: 30px;">
<y-button
:classStyle="registered.password&&registered.confimpassword&&registered.phone&&registxt==='注册'?'main-btn':'disabled-btn'"
:text="registxt"
style="margin: 0;width: 100%;height: 48px;font-size: 18px;line-height: 48px"
@btnClick="regist"
>
</y-button>
</div>
<div class="border" style="margin-bottom: 10px;"></div>
<ul class="common-form pr">
<!-- <li class="pa" style="left: 0;top: 0;margin: 0;color: #d44d44">{{registered.errMsg}}</li> -->
<li style="text-align: center;line-height: 48px;margin-bottom: 0;font-size: 12px;color: #999;">
<span>如果您已拥有 mallcloud 账号则可在此</span>
<a href="javascript:;"
style="margin: 0 5px"
@click="toLogin">登陆</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script src="../../../static/geetest/gt.js"></script>
<script>
import YFooter from '/common/footer'
import YButton from '/components/YButton'
import { register } from '/api/index.js'
var captcha
export default {
data () {
return {
cart: [],
loginPage: true,
ruleForm: {
phone: '',
password: '',
errMsg: ''
},
registered: {
phone: '',
password: '',
confimpassword: '',
errMsg: ''
},
agreement: false,
registxt: '注册',
statusKey: ''
}
},
computed: {
count () {
return this.$store.state.login
}
},
methods: {
open (t, m) {
this.$notify.info({
title: t,
message: m
})
},
messageSuccess () {
this.$message({
message: '恭喜您,注册成功!赶紧登录体验吧',
type: 'success'
})
},
message (m) {
this.$message.error({
message: m
})
},
toLogin () {
this.$router.push({
path: '/login'
})
},
regist () {
this.registxt = '注册中...'
let phone = this.registered.phone
let password = this.registered.password
let confimpassword = this.registered.confimpassword
if (!phone || !password || !confimpassword) {
this.message('账号密码不能为空!')
this.registxt = '注册'
return false
}
if (confimpassword !== password) {
this.message('两次输入的密码不相同!')
this.registxt = '注册'
return false
}
if (!this.agreement) {
this.message('您未勾选同意我们的相关注册协议!')
this.registxt = '注册'
return false
}
let params = {
phone: this.registered.phone,
password: this.registered.password,
confimpassword:this.registered.confimpassword
}
register(params).then(res => {
if (res.code === 200) {
this.messageSuccess()
this.toLogin()
} else {
this.message(res.msg)
// captcha.reset()
this.regist = '注册'
return false
}
})
}
},
mounted () {
},
components: {
YFooter,
YButton
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
* {
box-sizing: content-box;
}
.login {
overflow-x: hidden;
overflow-y: hidden;
.input {
height: 50px;
display: flex;
align-items: center;
input {
font-size: 16px;
width: 100%;
height: 100%;
padding: 10px 15px;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 6px;
}
}
.wrapper {
background: url(/static/images/bg_9b9dcb65ff.png) repeat;
background-size: 100px;
min-height: 800px;
min-width: 630px;
}
}
.v2 .dialog {
width: 450px;
border: 1px solid #dadada;
border-radius: 10px;
top: 50%;
left: 50%;
margin-left: -225px;
position: absolute;
.title {
background: linear-gradient(#fff, #f5f5f5);
height: auto;
overflow: visible;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
position: relative;
background-image: url(/static/images/smartisan_4ada7fecea.png);
background-size: 140px;
background-position: top center;
background-repeat: no-repeat;
height: 92px;
margin: 23px 0 50px;
padding: 75px 0 0;
box-shadow: none;
h4 {
padding: 0;
text-align: center;
color: #666;
border-bottom: 1px solid #dcdcdc;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
font-weight: 700;
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
margin: 0;
padding: 0;
border-bottom: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
line-height: 1em;
height: auto;
color: #333;
font-weight: 400;
}
}
.content {
padding: 0 40px 22px;
height: auto;
.common-form {
li {
clear: both;
margin-bottom: 15px;
position: relative;
}
}
}
}
.dialog-shadow,
.v2 .bbs .dialog-shadow,
.v2 .dialog-shadow {
-webkit-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),
0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),
0 10px 20px -10px rgba(0, 0, 0, 0.04);
-moz-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),
0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),
0 10px 20px -10px rgba(0, 0, 0, 0.04);
box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),
0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),
0 10px 20px -10px rgba(0, 0, 0, 0.04);
}
@media screen and (min-width: 737px),
screen and (-webkit-max-device-pixel-ratio: 1.9) and (max-width: 736px) and (min-device-width: 737px) {
.wrapper {
background: url(/static/images/con-bg_04f25dbf8e.jpg) repeat-x;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.dialog {
background: url(/static/images/dialog-gray-bg.png) #fff bottom repeat-x;
border-radius: 12px;
display: none;
margin: -163px 0 0 -218px;
width: 436px;
position: fixed;
left: 50%;
top: 50%;
}
.dialog .title h4 {
border-bottom: #d1d1d1 solid 1px;
box-shadow: 0 2px 6px #d1d1d1;
color: #666;
font-size: 20px;
height: 61px;
line-height: 61px;
padding: 0 0 0 35px;
}
.common-form li {
clear: both;
margin-bottom: 15px;
position: relative;
}
.auto-login {
position: absolute;
top: 0px;
left: 2px;
color: #999;
}
.register {
padding: 1px 10px 0;
border-right: 1px solid #ccc;
}
.border {
margin-top: 10px;
border-bottom: 1px solid #ccc;
}
.other {
margin: 20px 5px 0 0;
width: auto;
color: #bbb;
font-size: 12px;
cursor: default;
color: #999;
}
.footer {
display: flex;
flex-direction: row;
}
.agree {
margin-bottom: 30px;
color: #999;
}
}
.registered {
h4 {
padding: 0;
text-align: center;
color: #666;
border-bottom: 1px solid #dcdcdc;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
font-weight: 700;
font-size: 20px;
height: 60px;
line-height: 60px;
}
}
#wait {
text-align: left;
color: #999;
margin: 0;
}
</style>

View File

@@ -0,0 +1,364 @@
<template>
<div class="w" style="padding-bottom: 100px;">
<y-shelf title="XPay收银台 收款方: Mallcloud">
<div slot="content">
<div class="box-inner order-info">
<p class="payment-detail">扫一扫付款</p>
<p class="payment-money">{{orderTotal}}</p>
<div class="img-box">
<img id="qr" class="pic" v-bind:src="imgPath" alt="加载失败" width="168px" height="168px"/>
<div class="explain">
<img class="fn-left" src="https://t.alipayobjects.com/images/T1bdtfXfdiXXXXXXXX.png" alt="扫一扫标识">
<div class="fn-right">打开手机支付宝<br>扫一扫继续付款</div>
<div class="timeout" v-if="timeout">二维码已过期</div>
</div>
</div>
<a class="download-alipay" href="https://mobile.alipay.com/index.htm" target="_blank">首次使用请下载手机支付宝</a>
<div class="count">{{timecount}}</div>
<div class="qrguide-area">
<img src="https://t.alipayobjects.com/images/rmsweb/T13CpgXf8mXXXXXXXX.png" :class="show?'show-img':'close-img'" @click="changePic()">
<img src="https://t.alipayobjects.com/images/rmsweb/T1ASFgXdtnXXXXXXXX.png" :class="show?'close-img':'show-img'" @click="changePic()">
</div>
<img src="static/images/red.png" width="50px" height="50px" class="red" title="支付领红包" @click="showRed()">
</div>
<div>
<div class="box-btn">
<div>
<span>
</span>
<em><span>¥</span>{{orderTotal}}</em>
<y-button :text="payNow"
:classStyle="submit?'main-btn':'disabled-btn'"
style="width: 120px;height: 40px;font-size: 16px;line-height: 38px"
@btnClick="paySuc()"
></y-button>
</div>
</div>
</div>
</div>
</y-shelf>
<el-dialog
title="支付红包"
:visible.sync="dialogVisible"
width="30%"
@close="handleClose" style="text-align:center;width:50%;margin:0 auto">
<img src="http://oweupqzdv.bkt.clouddn.com/1512881761970_small.jpg" class="qr-red"/>
<span>支付前领个红包吧(每日可领一次)</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">领取了</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import YShelf from '/components/shelf'
import YButton from '/components/YButton'
import { getStore, setStore } from '/utils/storage'
export default {
data () {
return {
show: true,
count: 25,
userId: '',
orderTotal: '',
userName: '',
tel: '',
streetName: '',
checkPrice: '',
payNow: '等待支付...',
submit: false,
nickName: '',
money: '',
info: '',
email: '',
dialogVisible: true,
isCustom: 0,
imgPath: 'static/qr/alipay/custom.png',
picName: '',
timeout: false,
timecount: ''
}
},
computed: {
},
methods: {
changePic () {
this.show = !this.show
},
toMoney (num) {
num = parseFloat(num)
num = num.toFixed(2)
num = num.toLocaleString()
return num
},
handleClose () {
this.countDown()
this.countTime()
},
showRed () {
this.dialogVisible = true
},
countDown () {
let me = this
if (this.count === 0) {
this.payNow = '确认已支付'
this.submit = true
return
} else {
this.count--
}
setTimeout(function () {
me.countDown()
}, 1000)
},
countTime () {
let me = this
let time = getStore('setTime')
if (time <= 0) {
this.timeout = true
this.timecount = ''
this.count = 10000
return
} else {
time--
this.showTime(time)
setStore('setTime', time)
}
setTimeout(function () {
me.countTime()
}, 1000)
},
showTime (v) {
let m = 0
let s = 0
if (v === null || v === '') {
return ''
}
if (v >= 60) {
m = Math.floor(v / 60)
s = v % 60
} else {
s = v
}
if (m >= 0 && m <= 9) {
m = '0' + m
}
if (s >= 0 && s <= 9) {
s = '0' + s
}
this.timecount = '请于 ' + m + ' 分 ' + s + ' 秒 内支付'
},
paySuc () {
this.$router.push({path: '/order/paysuccess', query: {price: this.orderTotal}})
}
},
mounted () {
let price = getStore('price')
let isCustom = getStore('isCustom')
this.orderTotal = this.toMoney(price)
if (this.orderTotal === 'NaN') {
this.$router.push({path: '/'})
}
if (isCustom !== 'true') {
this.picName = this.orderTotal
this.imgPath = 'static/qr/alipay/' + this.picName + '.png'
}
},
components: {
YShelf,
YButton
}
}
</script>
<style lang="scss" scoped rel="stylesheet/scss">
.w {
padding-top: 39px;
}
.order-info {
padding: 60px 0 55px;
color: #333;
background: #fff !important;
h3 {
padding-bottom: 14px;
line-height: 36px;
text-align: center;
font-size: 36px;
color: #212121;
}
.payment-detail {
text-align: center;
line-height: 24px;
font-size: 14px;
color: #999;
}
}
.box-inner {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
> div {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.box-btn {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
> div {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.payment-money {
text-align: center;
font-size: 30px;
color: #d44d44;
font-weight: 700;
}
.img-box{
position: relative;
width: 180px;
height: auto;
min-height: 168px;
margin: 0 auto;
padding: 6px;
border: 1px solid #d3d3d3;
box-shadow: 1px 1px 1px #ccc;
display: inline-block;
}
.explain {
margin: 5px 0 12px 0;
}
.pic{
margin-top: 3px;
}
.fn-left{
margin-left: -5px;
}
.fn-right{
font-size: 13px;
color: #4D4D4D;
line-height: 18px;
margin: -57px 0 0 33px;
}
.download-alipay {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
margin-top: -5px;
font-size: 12px;
color: #a6a6a6;
text-decoration: underline;
width: 25%;
margin: 0 auto;
}
.qrguide-area {
position: absolute;
top: 113px;
left: 713px;
width: 204px;
height: 183px;
cursor: pointer;
}
.show-img{
display: block;
}
.close-img{
display: none;
}
.red {
position: absolute;
top: 482px;
left: 1151px;
width: 47px;
height: 50px;
cursor: pointer;
}
.el-dialog--small {
width: 30%;
}
.qr-red {
display: block;
margin: 0 auto;
width: 70%;
}
.count {
display: flex;
position: absolute;
text-align: center;
width: 230px;
flex-direction: column;
align-items: center;
margin-left: calc(50% - 115px);
margin-top: 0px;
color: #222;
margin-top: -18px;
}
.timeout{
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(255,255,255,.95);
color: #222;
line-height: 200px;
text-align: center;
z-index: 1;
}
</style>

View File

@@ -0,0 +1,20 @@
<template>
<div>
<y-header>
<div slot="nav">
</div>
</y-header>
<router-view style="margin-top: 40px;"></router-view>
<y-footer></y-footer>
</div>
</template>
<script>
import YHeader from '/common/header'
import YFooter from '/common/footer'
export default {
components: {
YHeader,
YFooter
}
}
</script>

View File

@@ -0,0 +1,476 @@
<template>
<div class="w" style="padding-bottom: 100px;">
<y-shelf title="支付订单">
<div slot="content">
<div class="box-inner order-info">
<h3>提交订单成功请填写捐赠信息</h3>
<p class="payment-detail">请在 <span>24 小时内</span>完成支付超时订单将自动取消</p>
<p class="payment-detail">我们不会在您完成支付后的 72 小时内发货您的支付将用作捐赠</p>
<p class="payment-detail" style="color:red">请仔细填写捐赠信息避免系统审核失败无法在捐赠名单中显示您的数据</p>
</div>
<div class="pay-info">
<span style="color:red">*</span> 昵称<el-input v-model="nickName" placeholder="请输入您的昵称" @change="checkValid" :maxlength="maxLength" class="input"></el-input><br>
<span style="color:red">*</span> 捐赠金额<el-select class="money-select" v-model="moneySelect" placeholder="请选择支付金额" @change="changeSelect">
<el-option label="¥1.00 支付测试" value="1.00"></el-option>
<el-option label="¥5.00 感谢捐赠" value="5.00"></el-option>
<el-option label="¥10.00 感谢大佬" value="10.00"></el-option>
<el-option label="自定义 随意撒币" value="custom"></el-option>
</el-select><br>
<div v-if="moneySelect === 'custom'"><span style="color:red">*</span> 输入金额:<el-input v-model="money" placeholder="请输入捐赠金额(最多2位小数不得低于0.1元)" @change="checkValid" :maxlength="maxLength" class="input" style="margin-left:10px"></el-input><br></div>
<span style="color:red">*</span> 通知邮箱<el-input v-model="email" placeholder="支付审核结果将以邮件方式发送至您的邮箱" @change="checkValid" :maxlength="maxLength" class="input" style="margin-left:10px"></el-input><br>
&nbsp;&nbsp; 留言<el-input v-model="info" placeholder="请输入您的留言内容" :maxlength="maxLength" class="input"></el-input>
</div>
<!--支付方式-->
<div class="pay-type">
<div class="p-title">支付方式</div>
<div class="pay-item">
<div :class="{active:payType==1}" @click="payType=1"><img src="/static/images/alipay@2x.png" alt=""></div>
<div :class="{active:payType==2}" @click="payType=2"><img src="/static/images/weixinpay@2x.png" alt=""></div>
<div :class="{active:payType==3}" @click="payType=3"><img src="/static/images/qqpay.png" alt=""></div>
</div>
</div>
<div>
<div class="box-inner">
<div>
<span>
订单金额
</span>
<em><span>¥</span>{{orderTotal.toFixed(2)}}</em>
<span>
实际应付金额
</span>
<em><span>¥</span>{{money}}</em>
<y-button :text="payNow"
:classStyle="submit?'main-btn':'disabled-btn'"
style="width: 120px;height: 40px;font-size: 16px;line-height: 38px"
@btnClick="paySuc()"
></y-button>
</div>
</div>
</div>
</div>
</y-shelf>
<!--地址信息-->
<div class="p-msg w">
<div class="confirm-detail">
<div class="info-title">收货信息</div>
<p class="info-detail">姓名{{userName}}</p>
<p class="info-detail">联系电话{{tel}}</p>
<p class="info-detail">详细地址{{streetName}}</p></div>
</div>
<div class="confirm-table-title">
<span class="name">商品信息</span>
<div>
<span class="productPrice">单价</span>
<span class="num">数量</span>
<span class="subtotal">小计</span>
</div>
</div>
<!--商品-->
<div class="confirm-goods-table">
<div class="cart-items" v-for="(item,i) in cartList" :key="i">
<div class="name">
<div class="name-cell ellipsis">
<a @click="goodsDetails(item.productId)" title="" target="_blank">{{item.productName}}</a>
</div>
</div>
<div class="n-b">
<div class="productPrice">¥ {{item.productPrice}}</div>
<div class="goods-num">{{item.productQuantity}}</div>
<div class="subtotal">
<div class="subtotal-cell"> ¥ {{item.productPrice * item.productQuantity}}<br></div>
</div>
</div>
</div>
</div>
<!--合计-->
<div class="order-discount-line">
<p style="font-size: 14px;font-weight: bolder;"> <span style="padding-right:47px">商品总计</span>
<span style="font-size: 16px;font-weight: 500;line-height: 32px;">¥ {{orderTotal}}</span>
</p>
<p><span style="padding-right:30px">运费</span><span style="font-weight: 700;">+ ¥ 0.00</span></p>
</div>
</div>
</template>
<script>
import YShelf from '/components/shelf'
import YButton from '/components/YButton'
import { getOrderDet, payMent , scanCode, scanCode2 , wxpay ,micropay } from '/api/goods'
import { getStore, setStore } from '/utils/storage'
export default {
data () {
return {
payType: 1,
addList: {},
cartList: [],
addressId: 0,
productId: '',
num: '',
userId: '',
orderTotal: 0,
userName: '',
tel: '',
streetName: '',
payNow: '立刻支付',
submit: false,
nickName: '',
money: '1.00',
info: '',
email: '',
orderId: '',
type: '',
moneySelect: '1.00',
isCustom: false,
maxLength: 30
}
},
computed: {
// 选中的总价格
checkPrice () {
let totalPrice = 0
this.cartList && this.cartList.forEach(item => {
totalPrice += (item.productQuantity * item.productPrice)
})
return totalPrice
}
},
methods: {
checkValid () {
if (this.nickName !== '' && this.money !== '' && this.isMoney(this.money) && this.email !== '' && this.isEmail(this.email)) {
this.submit = true
} else {
this.submit = false
}
},
messageFail (m) {
this.$message.error({
message: m
})
},
changeSelect (v) {
if (v !== 'custom') {
this.money = v
} else {
this.isCustom = true
this.money = ''
}
this.checkValid()
},
goodsDetails (id) {
window.open(window.location.origin + '#/goodsDetails?id=' + id)
},
_getOrderDet (orderId) {
let params = {
id: this.orderId
}
getOrderDet(params).then(res => {
this.cartList = res.data.orderItemList
this.userName = res.data.receiverName
this.tel = res.data.receiverPhone
this.streetName = res.data.receiverDetailAddress
this.orderTotal = res.data.payAmount
})
},
paySuc () {
this.payNow = '支付中...'
this.submit = false
let params = {
nickName: this.nickName,
money: this.money,
info: this.info,
email: this.email,
orderId: this.orderId,
userId: this.userId,
payType: this.payType
}
payMent(params).then(res => {
if (res.code === 200) {
setStore('setTime', 90)
setStore('price', this.money)
setStore('isCustom', this.isCustom)
if (this.payType === 1) {
this.$router.push({path: '/order/alipay'})
} else if (this.payType === 2) {
} else if (this.payType === 3) {
this.$router.push({path: '/order/qqpay'})
} else {
this.$router.push({path: '/order/alipay'})
}
} else {
this.payNow = '立刻支付'
this.submit = true
this.messageFail(res.msg)
}
})
},
scanCode1(params) {
payMent(params).then(res => {
if (res.code == 200) {
var name = res.data;
console.log(name);
this.showScanCode('#qrcode2', name);
} else {
if (res.code == 2) {
alert(res.message);
} else {
alert("error" + res.message);
}
}
})
},
showScanCode(id, name) {
$(id).attr("src", "#(ctxPath)/" + name);
},
isMoney (v) {
if (v < 0.1) {
return false
}
var regu = /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/
var re = new RegExp(regu)
if (re.test(v)) {
return true
} else {
return false
}
},
isEmail (v) {
var regu = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/
var re = new RegExp(regu)
if (re.test(v)) {
return true
} else {
return false
}
}
},
created () {
this.userId = getStore('userId')
this.orderId = this.$route.query.orderId
if (this.orderId) {
this._getOrderDet(this.orderId)
} else {
this.$router.push({path: '/'})
}
},
components: {
YShelf,
YButton
}
}
</script>
<style lang="scss" scoped rel="stylesheet/scss">
.w {
padding-top: 39px;
}
.order-info {
padding: 60px 0 55px;
color: #333;
background: #fff !important;
h3 {
padding-bottom: 14px;
line-height: 36px;
text-align: center;
font-size: 36px;
color: #212121;
}
.payment-detail {
text-align: center;
line-height: 24px;
font-size: 14px;
color: #999;
}
}
/*支付类型*/
.pay-type {
margin: 0 auto;
width: 90%;
padding-bottom: 30px;
.p-title {
font-size: 18px;
line-height: 40px;
padding: 0 10px;
position: relative;
&:before {
content: ' ';
position: absolute;
bottom: 0;
left: 0;
right: 0;
border-bottom: 1px solid #ccc;
}
}
}
.pay-type {
.pay-item {
display: flex;
align-items: center;
div {
margin-top: 20px;
width: 175px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #E5E5E5;
cursor: pointer;
border-radius: 6px;
margin-right: 10px;
background: #FAFAFA;
&.active {
border-color: #6A8FE5;
background: #fff;
}
img {
display: block;
height: 34px;
margin: 8px auto;
}
}
}
}
.box-inner {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
> div {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.confirm-detail {
padding: 0 30px 25px;
border-top: 1px solid #d5d5d5;
.info-title {
height: 14px;
margin: 30px 0 17px;
line-height: 14px;
font-weight: bolder;
color: #333;
}
.info-detail {
line-height: 24px;
color: #666;
}
}
.confirm-table-title {
padding: 3px 0 0 33px;
border-top: 1px solid #D5D5D5;
line-height: 54px;
font-weight: bolder;
color: #000;
display: flex;
justify-content: space-between;
span {
display: inline-block;
width: 175px;
text-align: left;
}
.productPrice {
padding-left: 80px;
}
.num {
padding-left: 75px;
}
.subtotal {
padding-left: 72px;
}
}
.confirm-goods-table {
border-top: 1px solid #D5D5D5;
.cart-items {
height: 80px;
display: flex;
align-items: center;
justify-content: space-between;
a {
color: #333;
}
}
.n-b {
display: flex;
align-items: center;
justify-content: center;
> div {
color: #626262;
font-weight: 700;
width: 175px;
text-align: center;
}
}
}
.order-discount-line {
padding: 22px 30px 53px;
border-top: 1px solid #D5D5D5;
line-height: 24px;
text-align: right;
font-size: 12px;
&:first-child {
line-height: 32px;
text-align: right;
font-size: 14px;
font-weight: bolder;
}
}
.name {
width: 40%;
}
.name-cell {
padding-left: 33px;
}
.input {
width:30%;
margin:0 0 1vw 38px;
}
.pay-info {
margin-top: -2vw;
text-align: center;
}
.money-select {
width: 31%;
padding-left: 10px;
margin-bottom: 1vw;
}
</style>

View File

@@ -0,0 +1,454 @@
<template>
<div class="w" style="padding-bottom: 100px;">
<y-shelf title="支付订单">
<div slot="content">
<div class="box-inner order-info">
<h3>提交订单成功请填写捐赠信息</h3>
<p class="payment-detail">请在 <span>24 小时内</span>完成支付超时订单将自动取消</p>
<p class="payment-detail">我们不会在您完成支付后的 72 小时内发货您的支付将用作捐赠</p>
<p class="payment-detail" style="color:red">请仔细填写捐赠信息避免系统审核失败无法在捐赠名单中显示您的数据</p>
</div>
<div class="pay-info">
<span style="color:red">*</span> 昵称<el-input v-model="nickName" placeholder="请输入您的昵称" @change="checkValid" :maxlength="maxLength" class="input"></el-input><br>
<span style="color:red">*</span> 捐赠金额<el-select class="money-select" v-model="moneySelect" placeholder="请选择支付金额" @change="changeSelect">
<el-option label="¥1.00 支付测试" value="1.00"></el-option>
<el-option label="¥5.00 感谢捐赠" value="5.00"></el-option>
<el-option label="¥10.00 感谢大佬" value="10.00"></el-option>
<el-option label="自定义 随意撒币" value="custom"></el-option>
</el-select><br>
<div v-if="moneySelect === 'custom'"><span style="color:red">*</span> 输入金额:<el-input v-model="money" placeholder="请输入捐赠金额(最多2位小数不得低于0.1元)" @change="checkValid" :maxlength="maxLength" class="input" style="margin-left:10px"></el-input><br></div>
<span style="color:red">*</span> 通知邮箱<el-input v-model="email" placeholder="支付审核结果将以邮件方式发送至您的邮箱" @change="checkValid" :maxlength="maxLength" class="input" style="margin-left:10px"></el-input><br>
&nbsp;&nbsp; 留言<el-input v-model="info" placeholder="请输入您的留言内容" :maxlength="maxLength" class="input"></el-input>
</div>
<!--支付方式-->
<div class="pay-type">
<div class="p-title">支付方式</div>
<div class="pay-item">
<div :class="{active:payType==1}" @click="payType=1"><img src="/static/images/alipay@2x.png" alt=""></div>
<div :class="{active:payType==2}" @click="payType=2"><img src="/static/images/weixinpay@2x.png" alt=""></div>
<div :class="{active:payType==3}" @click="payType=3"><img src="/static/images/qqpay.png" alt=""></div>
</div>
</div>
<div>
<div class="box-inner">
<div>
<span>
订单金额
</span>
<em><span>¥</span>{{orderTotal.toFixed(2)}}</em>
<span>
实际应付金额
</span>
<em><span>¥</span>{{money}}</em>
<y-button :text="payNow"
:classStyle="submit?'main-btn':'disabled-btn'"
style="width: 120px;height: 40px;font-size: 16px;line-height: 38px"
@btnClick="paySuc()"
></y-button>
</div>
</div>
</div>
</div>
</y-shelf>
<!--地址信息-->
<div class="p-msg w">
<div class="confirm-detail">
<div class="info-title">收货信息</div>
<p class="info-detail">姓名{{userName}}</p>
<p class="info-detail">联系电话{{tel}}</p>
<p class="info-detail">详细地址{{streetName}}</p></div>
</div>
<div class="confirm-table-title">
<span class="name">商品信息</span>
<div>
<span class="productPrice">单价</span>
<span class="num">数量</span>
<span class="subtotal">小计</span>
</div>
</div>
<!--商品-->
<div class="confirm-goods-table">
<div class="cart-items" v-for="(item,i) in cartList" :key="i">
<div class="name">
<div class="name-cell ellipsis">
<a @click="goodsDetails(item.productId)" title="" target="_blank">{{item.productName}}</a>
</div>
</div>
<div class="n-b">
<div class="productPrice">¥ {{item.productPrice}}</div>
<div class="goods-num">{{item.productQuantity}}</div>
<div class="subtotal">
<div class="subtotal-cell"> ¥ {{item.productPrice * item.productQuantity}}<br></div>
</div>
</div>
</div>
</div>
<!--合计-->
<div class="order-discount-line">
<p style="font-size: 14px;font-weight: bolder;"> <span style="padding-right:47px">商品总计</span>
<span style="font-size: 16px;font-weight: 500;line-height: 32px;">¥ {{orderTotal}}</span>
</p>
<p><span style="padding-right:30px">运费</span><span style="font-weight: 700;">+ ¥ 0.00</span></p>
</div>
</div>
</template>
<script>
import YShelf from '/components/shelf'
import YButton from '/components/YButton'
import { getOrderDet, payMent } from '/api/goods'
import { getStore, setStore } from '/utils/storage'
export default {
data () {
return {
payType: 1,
addList: {},
cartList: [],
addressId: 0,
productId: '',
num: '',
userId: '',
orderTotal: 0,
userName: '',
tel: '',
streetName: '',
payNow: '立刻支付',
submit: false,
nickName: '',
money: '1.00',
info: '',
email: '',
orderId: '',
type: '',
moneySelect: '1.00',
isCustom: false,
maxLength: 30
}
},
computed: {
// 选中的总价格
checkPrice () {
let totalPrice = 0
this.cartList && this.cartList.forEach(item => {
totalPrice += (item.productQuantity * item.productPrice)
})
return totalPrice
}
},
methods: {
checkValid () {
if (this.nickName !== '' && this.money !== '' && this.isMoney(this.money) && this.email !== '' && this.isEmail(this.email)) {
this.submit = true
} else {
this.submit = false
}
},
messageFail (m) {
this.$message.error({
message: m
})
},
changeSelect (v) {
if (v !== 'custom') {
this.money = v
} else {
this.isCustom = true
this.money = ''
}
this.checkValid()
},
goodsDetails (id) {
window.open(window.location.origin + '#/goodsDetails?id=' + id)
},
_getOrderDet (orderId) {
let params = {
params: {
id: this.orderId
}
}
getOrderDet(params).then(res => {
this.cartList = res.data.orderItemList
this.userName = res.data.receiverName
this.tel = res.data.receiverPhone
this.streetName = res.data.receiverDetailAddress
this.orderTotal = res.data.payAmount
})
},
paySuc () {
this.payNow = '支付中...'
this.submit = false
let params = {
params: {
nickName: this.nickName,
money: this.money,
info: this.info,
email: this.email,
orderId: this.orderId,
userId: this.userId,
payType: this.payType
}
}
payMent(params).then(res => {
if (res.code === 200) {
setStore('setTime', 90)
setStore('price', this.money)
setStore('isCustom', this.isCustom)
if (this.payType === 1) {
this.$router.push({path: '/order/alipay'})
} else if (this.payType === 2) {
this.$router.push({path: '/order/wechat'})
} else if (this.payType === 3) {
this.$router.push({path: '/order/qqpay'})
} else {
this.$router.push({path: '/order/alipay'})
}
} else {
this.payNow = '立刻支付'
this.submit = true
this.messageFail(res.msg)
}
})
},
isMoney (v) {
if (v < 0.1) {
return false
}
var regu = /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/
var re = new RegExp(regu)
if (re.test(v)) {
return true
} else {
return false
}
},
isEmail (v) {
var regu = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/
var re = new RegExp(regu)
if (re.test(v)) {
return true
} else {
return false
}
}
},
created () {
this.userId = getStore('userId')
this.orderId = this.$route.query.orderId
if (this.orderId) {
this._getOrderDet(this.orderId)
} else {
this.$router.push({path: '/'})
}
},
components: {
YShelf,
YButton
}
}
</script>
<style lang="scss" scoped rel="stylesheet/scss">
.w {
padding-top: 39px;
}
.order-info {
padding: 60px 0 55px;
color: #333;
background: #fff !important;
h3 {
padding-bottom: 14px;
line-height: 36px;
text-align: center;
font-size: 36px;
color: #212121;
}
.payment-detail {
text-align: center;
line-height: 24px;
font-size: 14px;
color: #999;
}
}
/*支付类型*/
.pay-type {
margin: 0 auto;
width: 90%;
padding-bottom: 30px;
.p-title {
font-size: 18px;
line-height: 40px;
padding: 0 10px;
position: relative;
&:before {
content: ' ';
position: absolute;
bottom: 0;
left: 0;
right: 0;
border-bottom: 1px solid #ccc;
}
}
}
.pay-type {
.pay-item {
display: flex;
align-items: center;
div {
margin-top: 20px;
width: 175px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #E5E5E5;
cursor: pointer;
border-radius: 6px;
margin-right: 10px;
background: #FAFAFA;
&.active {
border-color: #6A8FE5;
background: #fff;
}
img {
display: block;
height: 34px;
margin: 8px auto;
}
}
}
}
.box-inner {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
> div {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.confirm-detail {
padding: 0 30px 25px;
border-top: 1px solid #d5d5d5;
.info-title {
height: 14px;
margin: 30px 0 17px;
line-height: 14px;
font-weight: bolder;
color: #333;
}
.info-detail {
line-height: 24px;
color: #666;
}
}
.confirm-table-title {
padding: 3px 0 0 33px;
border-top: 1px solid #D5D5D5;
line-height: 54px;
font-weight: bolder;
color: #000;
display: flex;
justify-content: space-between;
span {
display: inline-block;
width: 175px;
text-align: left;
}
.productPrice {
padding-left: 80px;
}
.num {
padding-left: 75px;
}
.subtotal {
padding-left: 72px;
}
}
.confirm-goods-table {
border-top: 1px solid #D5D5D5;
.cart-items {
height: 80px;
display: flex;
align-items: center;
justify-content: space-between;
a {
color: #333;
}
}
.n-b {
display: flex;
align-items: center;
justify-content: center;
> div {
color: #626262;
font-weight: 700;
width: 175px;
text-align: center;
}
}
}
.order-discount-line {
padding: 22px 30px 53px;
border-top: 1px solid #D5D5D5;
line-height: 24px;
text-align: right;
font-size: 12px;
&:first-child {
line-height: 32px;
text-align: right;
font-size: 14px;
font-weight: bolder;
}
}
.name {
width: 40%;
}
.name-cell {
padding-left: 33px;
}
.input {
width:30%;
margin:0 0 1vw 38px;
}
.pay-info {
margin-top: -2vw;
text-align: center;
}
.money-select {
width: 31%;
padding-left: 10px;
margin-bottom: 1vw;
}
</style>

View File

@@ -0,0 +1,57 @@
<template>
<div class="w">
<y-shelf title="支付成功" style="text-align: center">
<div slot="content" class="content">
<p><i class="el-icon-circle-check icon-success"></i> 恭喜您支付成功请等待5-30分钟系统确认<br>总共花费 <span class="price"><em style="font-size: 18px">¥</em>{{price}}</span> </p>
<div style="margin-top: 20px;">
<router-link to="/user">
<y-button text="查看订单" style="width: 150px;height: 50px;line-height: 48px;font-size: 20px"
classStyle="main-btn"></y-button>
</router-link>
<router-link to="/home">
<y-button text="继续选购" style="width: 150px;height: 50px;line-height: 48px;font-size: 20px"
classStyle="main-btn"></y-button>
</router-link>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import YShelf from '/components/shelf'
import YButton from '/components/YButton'
export default {
data () {
return {
price: 10
}
},
components: {
YShelf,
YButton
},
created () {
this.price = this.$route.query.price
}
}
</script>
<style lang="scss" scoped>
.content {
padding: 150px 0;
font-size: 30px;
}
.icon-success {
font-size: 33px;
color: #01b401;
}
span.price {
color: #d44d44;
font-weight: 700;
line-height: 20px;
text-align: right;
}
</style>

View File

@@ -0,0 +1,297 @@
<template>
<div class="w" style="padding-bottom: 100px;">
<y-shelf title="XPay收银台 收款方: Mallcloud">
<div slot="content">
<div class="box-inner order-info">
<img class="wechat" src="static/images/qqpay.png" alt="扫一扫标识">
<p class="payment-detail">扫一扫付款</p>
<p class="payment-money">{{orderTotal}}</p>
<div class="img-box">
<img class="pic" v-bind:src="imgPath" alt="加载失败" width="168px" height="168px"/>
<div class="explain">
<img class="fn-left" src="static/images/qr.png" width="38px" height="38px" alt="扫一扫标识">
<div class="fn-right">打开手机QQ<br>扫一扫继续付款</div>
<div class="timeout" v-if="timeout">二维码已过期</div>
</div>
</div>
<div class="count">{{timecount}}</div>
</div>
<div>
<div class="box-btn">
<div>
<span>
</span>
<em><span>¥</span>{{orderTotal}}</em>
<y-button :text="payNow"
:classStyle="submit?'main-btn':'disabled-btn'"
style="width: 120px;height: 40px;font-size: 16px;line-height: 38px"
@btnClick="paySuc()"
></y-button>
</div>
</div>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import YShelf from '/components/shelf'
import YButton from '/components/YButton'
import { getStore, setStore } from '/utils/storage'
export default {
data () {
return {
show: true,
num: '',
userId: '',
orderTotal: '',
userName: '',
count: 30,
streetName: '',
checkPrice: '',
payNow: '等待支付...',
submit: false,
nickName: '',
money: '',
info: '',
email: '',
isCustom: 0,
imgPath: 'static/qr/qqpay/custom.png',
picName: '',
timeout: false,
timecount: ''
}
},
computed: {
},
methods: {
toMoney (num) {
num = parseFloat(num)
num = num.toFixed(2)
num = num.toLocaleString()
return num
},
countDown () {
let me = this
if (this.count === 0) {
this.payNow = '确认已支付'
this.submit = true
this.count = 10
return
} else {
this.count--
}
setTimeout(function () {
me.countDown()
}, 1000)
},
countTime () {
let me = this
let time = getStore('setTime')
if (time <= 0) {
this.timeout = true
this.timecount = ''
this.count = 10000
return
} else {
time--
this.showTime(time)
setStore('setTime', time)
}
setTimeout(function () {
me.countTime()
}, 1000)
},
showTime (v) {
let m = 0
let s = 0
if (v === null || v === '') {
return ''
}
if (v >= 60) {
m = Math.floor(v / 60)
s = v % 60
} else {
s = v
}
if (m >= 0 && m <= 9) {
m = '0' + m
}
if (s >= 0 && s <= 9) {
s = '0' + s
}
this.timecount = '请于 ' + m + ' 分 ' + s + ' 秒 内支付'
},
paySuc () {
this.$router.push({path: '/order/paysuccess', query: {price: this.orderTotal}})
}
},
mounted () {
let price = getStore('price')
let isCustom = getStore('isCustom')
this.orderTotal = this.toMoney(price)
if (this.orderTotal === 'NaN') {
this.$router.push({path: '/'})
}
if (isCustom !== 'true') {
this.picName = this.orderTotal
this.imgPath = 'static/qr/qqpay/' + this.picName + '.png'
}
this.countDown()
this.countTime()
},
components: {
YShelf,
YButton
}
}
</script>
<style lang="scss" scoped rel="stylesheet/scss">
.w {
padding-top: 39px;
}
.order-info {
padding: 60px 0 55px;
color: #333;
background: #fff !important;
h3 {
padding-bottom: 14px;
line-height: 36px;
text-align: center;
font-size: 36px;
color: #212121;
}
.payment-detail {
text-align: center;
line-height: 24px;
font-size: 14px;
color: #999;
}
}
.box-inner {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
margin-bottom: 10px;
> div {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.box-btn {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
> div {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.payment-money {
text-align: center;
font-size: 30px;
color: #d44d44;
font-weight: 700;
}
.img-box{
position: relative;
width: 180px;
height: auto;
min-height: 168px;
margin: 0 auto;
padding: 6px;
border: 1px solid #d3d3d3;
box-shadow: 1px 1px 1px #ccc;
display: inline-block;
}
.explain {
margin: 5px 0 12px 0;
}
.pic{
margin-top: 3px;
}
.wechat{
margin: 0 auto;
display: flex;
margin-top: -40px;
width: 220px;
}
.fn-left{
margin-left: -5px;
}
.fn-right{
font-size: 13px;
color: #4D4D4D;
line-height: 18px;
margin: -65px 0 0 40px;
}
.count {
display: flex;
position: absolute;
text-align: center;
width: 230px;
flex-direction: column;
align-items: center;
margin-left: calc(50% - 115px);
margin-top: 0px;
color: #222;
margin-top: 0px;
}
.timeout{
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(255,255,255,.95);
color: #222;
line-height: 200px;
text-align: center;
z-index: 1;
}
</style>

View File

@@ -0,0 +1,285 @@
<template>
<div class="w" style="padding-bottom: 100px;">
<y-shelf title="XPay收银台 收款方: Mallcloud">
<div slot="content">
<div class="box-inner order-info">
<img class="wechat" src="static/images/weixinpay@2x.png" alt="扫一扫标识">
<p class="payment-detail">扫一扫付款</p>
<p class="payment-money">{{orderTotal}}</p>
<div class="img-box">
<img class="pic" v-bind:src="imgPath" alt="加载失败" width="168px" height="168px"/>
<div class="timeout" v-if="timeout">二维码已过期</div>
</div>
</div>
<img class="explain" src="static/images/wechat-explain.png" alt="扫一扫标识">
<div class="count">{{timecount}}</div>
<div>
<div class="box-btn">
<div>
<span>
</span>
<em><span>¥</span>{{orderTotal}}</em>
<y-button :text="payNow"
:classStyle="submit?'main-btn':'disabled-btn'"
style="width: 120px;height: 40px;font-size: 16px;line-height: 38px"
@btnClick="paySuc()"
></y-button>
</div>
</div>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import YShelf from '/components/shelf'
import YButton from '/components/YButton'
import { getStore, setStore } from '/utils/storage'
export default {
data () {
return {
show: true,
num: '',
userId: '',
orderTotal: '',
userName: '',
count: 30,
streetName: '',
checkPrice: '',
payNow: '等待支付...',
submit: false,
nickName: '',
money: '',
info: '',
email: '',
isCustom: 0,
imgPath: 'static/qr/wechat/custom.png',
picName: '',
timeout: false,
timecount: ''
}
},
computed: {
},
methods: {
toMoney (num) {
num = parseFloat(num)
num = num.toFixed(2)
num = num.toLocaleString()
return num
},
countDown () {
let me = this
if (this.count === 0) {
this.payNow = '确认已支付'
this.submit = true
return
} else {
this.count--
}
setTimeout(function () {
me.countDown()
}, 1000)
},
countTime () {
let me = this
let time = getStore('setTime')
if (time <= 0) {
this.timeout = true
this.timecount = ''
this.count = 10000
return
} else {
time--
this.showTime(time)
setStore('setTime', time)
}
setTimeout(function () {
me.countTime()
}, 1000)
},
showTime (v) {
let m = 0
let s = 0
if (v === null || v === '') {
return ''
}
if (v >= 60) {
m = Math.floor(v / 60)
s = v % 60
} else {
s = v
}
if (m >= 0 && m <= 9) {
m = '0' + m
}
if (s >= 0 && s <= 9) {
s = '0' + s
}
this.timecount = '请于 ' + m + ' 分 ' + s + ' 秒 内支付'
},
paySuc () {
this.$router.push({path: '/order/paysuccess', query: {price: this.orderTotal}})
}
},
mounted () {
let price = getStore('price')
let isCustom = getStore('isCustom')
this.orderTotal = this.toMoney(price)
if (this.orderTotal === 'NaN') {
this.$router.push({path: '/'})
}
if (isCustom !== 'true') {
this.picName = this.orderTotal
this.imgPath = 'static/qr/wechat/' + this.picName + '.png'
}
this.countDown()
this.countTime()
},
components: {
YShelf,
YButton
}
}
</script>
<style lang="scss" scoped rel="stylesheet/scss">
.w {
padding-top: 39px;
}
.order-info {
padding: 60px 0 55px;
color: #333;
background: #fff !important;
h3 {
padding-bottom: 14px;
line-height: 36px;
text-align: center;
font-size: 36px;
color: #212121;
}
.payment-detail {
text-align: center;
line-height: 24px;
font-size: 14px;
color: #999;
}
}
.box-inner {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
> div {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.box-btn {
line-height: 60px;
background: #f9f9f9;
border-top: 1px solid #e5e5e5;
box-sizing: border-box;
> div {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 20px;
}
em {
margin-left: 5px;
font-size: 24px;
color: #d44d44;
font-weight: 700;
margin-right: 20px;
span {
margin-right: 4px;
font-size: 16px;
}
}
}
.payment-money {
text-align: center;
font-size: 30px;
color: #d44d44;
font-weight: 700;
}
.img-box{
position: relative;
width: 180px;
height: auto;
min-height: 168px;
margin: 0 auto;
padding: 6px;
border: 1px solid #d3d3d3;
box-shadow: 1px 1px 1px #ccc;
display: inline-block;
}
.explain {
margin: 0 auto;
display: flex;
width: 180px;
margin-top: -42px;
margin-bottom: 70px;
}
.pic{
margin-top: 3px;
}
.wechat{
margin: 0 auto;
display: flex;
margin-top: -40px;
width: 220px;
}
.count {
display: flex;
position: absolute;
text-align: center;
width: 230px;
flex-direction: column;
align-items: center;
margin-left: calc(50% - 115px);
margin-top: 0px;
color: #222;
margin-top: -45px;
}
.timeout{
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(255,255,255,.95);
color: #222;
line-height: 200px;
text-align: center;
z-index: 1;
}
</style>

View File

@@ -0,0 +1,22 @@
<template>
</template>
<script>
export default {
data () {
this.$router.push({
path: '/goods',
query: {
cid: this.$route.query.cid
}
})
return {
}
},
methods: {
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
</style>

View File

@@ -0,0 +1,22 @@
<template>
</template>
<script>
export default {
data () {
this.$router.push({
path: '/search',
query: {
keyword: this.$route.query.keyword
}
})
return {
}
},
methods: {
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
</style>

View File

@@ -0,0 +1,348 @@
<template>
<div class="goods">
<div class="nav-subs">
<div class="nav-sub-bgs"></div>
<div class="nav-sub-wrappers">
<div class="w">
<ul class="nav-lists">
<li>
<router-link to="/">
<a>首页</a>
</router-link>
</li>
<li>
<a class="active">搜索结果</a>
</li>
<li>
<a v-if="searching === true">拼命搜索中...</a>
<a v-if="searching === false">共为您找到 {{total}} 款商品信息</a>
</li>
</ul>
<div></div>
</div>
</div>
</div>
<div class="nav">
<div class="w">
<a href="javascript:;" :class="{active:sortType===1}" @click="reset()">综合排序</a>
<a href="javascript:;" @click="sortByPrice(1)" :class="{active:sortType===2}">价格从低到高</a>
<a href="javascript:;" @click="sortByPrice(-1)" :class="{active:sortType===3}">价格从高到低</a>
<div class="price-interval">
<input type="number" class="input" placeholder="价格" v-model="min">
<span style="margin: 0 5px"> - </span>
<input type="number" placeholder="价格" v-model="max">
<y-button text="确定" classStyle="main-btn" @btnClick="reset" style="margin-left: 10px;"></y-button>
</div>
</div>
</div>
<div v-loading="loading" element-loading-text="加载中..." style="min-height: 35vw;">
<div class="img-item" v-if="!noResult" >
<!--商品-->
<div class="goods-box w">
<mall-goods v-for="(item,i) in goods" :key="i" :msg="item"></mall-goods>
</div>
<el-pagination
v-if="!noResult&&!error"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[8, 20, 40, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<div class="no-info" v-if="noResult" >
<div class="no-data">
<img src="/static/images/no-search.png">
<br> 抱歉没有为您找到相关的商品
</div>
<section class="section">
<y-shelf :title="rectitel">
<div slot="content" class="recommend">
<mall-goods :msg="item" v-for="(item,i) in recommendPanel" :key="i"></mall-goods>
</div>
</y-shelf>
</section>
</div>
<div class="no-info" v-if="error">
<div class="no-data">
<img src="/static/images/error.png">
<br> 抱歉出错了...
</div>
<section class="section">
<y-shelf :title="rectitel">
<div slot="content" class="recommend">
<mall-goods :msg="item" v-for="(item,i) in recommendPanel" :key="i"></mall-goods>
</div>
</y-shelf>
</section>
</div>
</div>
</div>
</template>
<script>
import { getSearch } from '/api/goods.js'
import { recommend } from '/api/index.js'
import mallGoods from '/components/mallGoods'
import YButton from '/components/YButton'
import YShelf from '/components/shelf'
import YHeader from '/common/header'
import YFooter from '/common/footer'
export default {
data () {
return {
goods: [],
noResult: false,
error: false,
min: '',
max: '',
loading: true,
searching: true,
timer: null,
sortType: 1,
rectitel:'',
windowHeight: null,
windowWidth: null,
sort: 'price asc',
recommendPanel: [],
currentPage: 1,
pageSize: 20,
total: 0,
keyword: ''
}
},
methods: {
handleSizeChange (val) {
this.pageSize = val
this._getSearch()
this.loading = true
},
handleCurrentChange (val) {
this.currentPage = val
this._getSearch()
this.loading = true
},
_getSearch () {
let params = {
keyword: this.keyword,
pageSize: this.pageSize,
pageNum: this.currentPage,
sort: this.sort,
priceGt: this.min,
priceLte: this.max
}
getSearch(params).then(res => {
if (res.code === 200) {
this.goods = res.data.records
this.total = res.data.total
this.noResult = false
if (this.total === 0) {
this.noResult = true
}
this.error = false
} else {
this.error = true
}
this.loading = false
this.searching = false
})
},
// 默认排序
reset () {
this.sortType = 1
this.sort = 'price asc'
this.currentPage = 1
this.loading = true
this._getSearch()
},
// 价格排序
sortByPrice (v) {
if (v === 1){
this.sort = 'price asc';
}else{
this.sort = 'price desc';
}
this.currentPage = 1
this.loading = true
this._getSearch()
}
},
created () {
},
mounted () {
this.windowHeight = window.innerHeight
this.windowWidth = window.innerWidth
this.keyword = this.$route.query.keyword
this._getSearch()
recommend().then(res => {
let data = res.data
this.recommendPanel = data
this.rectitel = '推荐商品'
})
},
components: {
mallGoods,
YButton,
YShelf,
YHeader,
YFooter
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "../../assets/style/mixin";
@import "../../assets/style/theme";
.nav {
height: 60px;
line-height: 60px;
> div {
display: flex;
align-items: center;
a {
padding: 0 15px;
height: 100%;
@extend %block-center;
font-size: 12px;
color: #999;
&.active {
color: #5683EA;
}
&:hover {
color: #5683EA;
}
}
input {
@include wh(80px, 30px);
border: 1px solid #ccc;
}
input + input {
margin-left: 10px;
}
}
.price-interval {
padding: 0 15px;
@extend %block-center;
input[type=number] {
border: 1px solid #ccc;
text-align: center;
background: none;
border-radius: 5px;
}
}
}
.goods-box {
> div {
float: left;
border: 1px solid #efefef;
}
}
.nav-subs {
position: relative;
margin-top: -40px;
z-index: 20;
height: 90px;
background: #f7f7f7;
box-shadow: 0 2px 4px rgba(0, 0, 0, .04);
.nav-sub-wrappers {
padding: 31px 0;
height: 90px;
position: relative;
}
.w {
display: flex;
justify-content: space-between;
}
.nav-lists {
height: 28px;
line-height: 28px;
display: flex;
align-items: center;
height: 100%;
li:first-child {
padding-left: 0;
a {
padding-left: 10px;
}
}
li {
position: relative;
float: left;
padding-left: 2px;
a {
display: block;
// cursor: default;
padding: 0 10px;
color: #666;
&.active {
font-weight: bold;
}
}
a:hover {
color: #5683EA;
}
}
li:before {
content: ' ';
position: absolute;
left: 0;
top: 13px;
width: 2px;
height: 2px;
background: #bdbdbd;
}
}
}
.no-info {
padding: 100px 0;
text-align: center;
font-size: 30px;
display: flex;
flex-direction: column;
.no-data{
align-self: center;
}
}
.section {
padding-top: 8vw;
margin-bottom: -5vw;
width: 1218px;
align-self: center;
}
@media (min-width: 1px) {
.nav-subs .nav-sub-wrappers:after {
display: block;
}
}
.recommend {
display: flex;
> div {
flex: 1;
width: 25%;
}
}
.img-item{
display: flex;
flex-direction: column;
}
.el-pagination{
align-self: flex-end;
margin: 3vw 10vw 2vw;
}
</style>

View File

@@ -0,0 +1,260 @@
<template>
<div>
<section class="w mt30 clearfix">
<y-shelf title="捐赠名单">
<div slot="content" class="table" v-loading="loading" element-loading-text="加载中...">
<p>佛祖保佑这些好心人写程序永无BUG工资翻倍长命百岁迎娶白富美走上人生巅峰</p>
<el-table border :data="tableData" :default-sort = "{prop: 'time', order: 'descending'}" stripe style="width: 90%">
<el-table-column sortable prop="nickName" label="昵称" align="center"></el-table-column>
<el-table-column sortable prop="payType" label="捐赠方式" align="center"> </el-table-column>
<el-table-column sortable prop="money" label="捐赠金额(¥)" align="center"></el-table-column>
<el-table-column sortable prop="info" label="捐赠人留言信息" align="center"></el-table-column>
<el-table-column sortable prop="time" label="捐赠时间" align="center"></el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[5, 10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
</div>
</y-shelf>
</section>
<section class="w mt30 clearfix">
<y-shelf title="为什么要捐赠">
<div slot="content" class="donate">
<p>捐赠是国外用来支持开发者和资源贡献者的一种常见的方式</p>
<p>这些开发者不通过加入广告或者进行第三方推广获得收入</p>
<p>仅通过使用的用户自己主动捐赠来表达对开发者的感谢</p>
<p>当一个非盈利项目仅仅依靠兴趣的支撑很难确定它还能走多远</p>
<p>所有的捐赠都将用于提升我的环境配置维持网站的运行和提高我的积极性</p>
<p>这个渠道的存在并不意味着你必须捐赠</p>
<p>你也可以不做任何事你的捐赠意味着你对我过去所做的表示感谢而不是表达对未来的期望</p>
<p>但你的捐赠会提高我的积极性和设备配置让我努力把手头上的事做的更好</p>
<p>我会维护一份名单以感谢所有的捐赠者正如我所说捐赠是一个向我表示感谢的方式</p>
</div>
</y-shelf>
</section>
<section class="w mt30 clearfix">
<y-shelf :title="thankPanel.name">
<div slot="content" class="hot">
<mall-goods :msg="item" v-for="(item,i) in thankPanel.panelContents" :key="i"></mall-goods>
</div>
</y-shelf>
</section>
<div id="comment" style="width: 1220px;margin: 0 auto;"></div>
</div>
</template>
<script>
import { thank, thanksList } from '/api/index.js'
import YShelf from '/components/shelf'
import product from '/components/product'
import mallGoods from '/components/mallGoods'
import 'gitment/style/default.css'
import Gitment from 'gitment'
export default {
data () {
return {
thankPanel: [],
tableData: [],
currentPage: 1,
pageSize: 10,
total: 0,
loading: true
}
},
methods: {
handleSizeChange (val) {
this.pageSize = val
this._thanksList()
this.loading = true
},
handleCurrentChange (val) {
this.currentPage = val
this._thanksList()
this.loading = true
},
_thanksList () {
let params = {
params: {
size: this.pageSize,
page: this.currentPage
}
}
thanksList(params).then(res => {
this.loading = false
this.tableData = res.data.data
this.total = res.data.recordsTotal
})
},
initGitment () {
const gitment = new Gitment({
id: '1',
owner: 'Mallcloud',
repo: 'xmall-comments',
oauth: {
client_id: 'd52e48ce99ee4e8fb412',
client_secret: 'f4154230d52f3a7d6b7695cb0ae89fe76b76121d'
}
})
gitment.render('comment')
}
},
mounted () {
thank().then(res => {
let data = res.data
this.thankPanel = data[0]
})
this._thanksList()
this.initGitment()
},
components: {
YShelf,
product,
mallGoods
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.sk_item {
width: 170px;
height: 225px;
padding: 0 14px 0 15px;
> div {
width: 100%;
}
a {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: all .3s;
&:hover {
transform: translateY(-5px);
}
}
img {
width: 130px;
height: 130px;
margin: 17px 0;
}
.sk_item_name {
color: #999;
display: block;
max-width: 100%;
_width: 100%;
overflow: hidden;
font-size: 12px;
text-align: left;
height: 32px;
line-height: 16px;
word-wrap: break-word;
word-break: break-all;
}
.sk_item_price {
padding: 3px 0;
height: 25px;
}
.price_new {
font-size: 18px;
font-weight: 700;
margin-right: 8px;
color: #f10214;
}
.price_origin {
color: #999;
font-size: 12px;
}
}
.box {
overflow: hidden;
position: relative;
z-index: 0;
margin-top: 29px;
box-sizing: border-box;
border: 1px solid rgba(0, 0, 0, .14);
border-radius: 8px;
background: #fff;
box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);
}
ul.box {
display: flex;
li {
flex: 1;
img {
display: block;
width: 305px;
height: 200px;
}
}
}
.mt30 {
margin-top: 30px;
}
.hot {
display: flex;
> div {
flex: 1;
width: 25%;
}
}
.table {
align-items: center;
display: flex;
flex-direction: column;
p{
font-size: 18px;
margin-top: 2vw;
// color: #5683EA;
}
.el-table{
// margin: 5vw 8vw 2vw 8vw;
margin: 2vw 0 2vw 0vw;
}
.el-pagination{
align-self: flex-end;
margin: 0 3.5vw 2vw;
}
}
.donate {
// align-items: center;
display: flex;
flex-direction: column;
margin: 1vw 3vw 2vw 3vw;
p{
font-size: 16px;
margin-top: 1vw;
}
}
.floors {
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: center;
.imgbanner {
width: 50%;
height: 430px;
}
img {
display: block;
width: 100%;
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,279 @@
<template>
<div>
<y-shelf title="收货地址">
<span slot="right"><y-button text="添加收货地址" style="margin: 0" @btnClick="update()"></y-button></span>
<div slot="content">
<!--标题-->
<div class="table-title">
<span class="name">姓名</span> <span class="address">详细地址</span> <span class="tel">电话</span>
</div>
<div v-if="addList.length">
<div class="address-item" v-for="(item,i) in addList" :key="i">
<div class="name">{{item.name}}</div>
<div class="address-msg">{{item.detailAddress}}</div>
<div class="telephone">{{item.phoneNumber}}</div>
<div class="defalut">
<a @click="changeDef(item)"
href="javascript:;"
v-text="item.defaultStatus==1?'( 默认地址 )':'设为默认'"
:class="{'defalut-address':item.defaultStatus}"></a>
</div>
<div class="operation">
<el-button type="primary" icon="edit" size="small" @click="update(item)"></el-button>
<el-button type="danger" icon="delete" size="small" :data-id="item.id" @click="del(item.id,i)"></el-button>
</div>
</div>
</div>
<div v-else>
<div style="padding: 80px 0;text-align: center">
<div style="font-size: 20px">你还未添加收货地址</div>
<div style="margin: 20px ">
<y-button text="添加地址" @btnClick="update()"></y-button>
</div>
</div>
</div>
</div>
</y-shelf>
<y-popup :open="popupOpen" @close='popupOpen=false' :title="popupTitle">
<div slot="content" class="md" :data-id="msg.id">
<div>
<input type="text" placeholder="收货人姓名" v-model="msg.name">
</div>
<div>
<input type="number" placeholder="手机号码" v-model="msg.phoneNumber">
</div>
<div>
<input type="text" placeholder="收货地址" v-model="msg.detailAddress">
</div>
<div>
<el-checkbox class="auto-login" v-model="msg.defaultStatus==0">设为默认</el-checkbox>
</div>
<y-button text='保存'
class="btn"
:classStyle="btnHighlight?'main-btn':'disabled-btn'"
@btnClick="save({id:msg.id,name:msg.name,phoneNumber:msg.phoneNumber,detailAddress:msg.detailAddress,defaultStatus:msg.defaultStatus})">
</y-button>
</div>
</y-popup>
</div>
</template>
<script>
import { addressList, addressUpdate, addressAdd, addressDel } from '/api/goods'
import YButton from '/components/YButton'
import YPopup from '/components/popup'
import YShelf from '/components/shelf'
import { getStore } from '/utils/storage'
export default {
data () {
return {
addList: [],
popupOpen: false,
popupTitle: '管理收货地址',
msg: {
id: '',
name: '',
phoneNumber: '',
detailAddress: '',
defaultStatus: false
},
userId: ''
}
},
computed: {
btnHighlight () {
let msg = this.msg
return msg.name && msg.phoneNumber && msg.detailAddress
}
},
methods: {
message (m) {
this.$message.error({
message: m
})
},
_addressList () {
addressList({userId: this.userId}).then(res => {
let data = res.data
if (data.length) {
this.addList = res.data
this.id = res.data[0].id || '1'
} else {
this.addList = []
}
})
},
_addressUpdate (params) {
addressUpdate(params).then(res => {
this._addressList()
})
},
_addressAdd (params) {
addressAdd(params).then(res => {
if (res.code === 200) {
this._addressList()
} else {
this.message(res.msg)
}
})
},
changeDef (item) {
if (!item.defaultStatus) {
item.defaultStatus = true
this._addressUpdate(item)
}
return false
},
// 保存
save (p) {
this.popupOpen = false
if (p.id) {
this._addressUpdate(p)
} else {
delete p.id
this._addressAdd(p)
}
},
// 删除
del (id, i) {
addressDel({id: id}).then(res => {
if (res.code === 200) {
this.addList.splice(i, 1)
} else {
this.message('删除失败')
}
})
},
// 修改
update (item) {
this.popupOpen = true
if (item) {
this.popupTitle = '管理收货地址'
this.msg.name = item.name
this.msg.phoneNumber = item.phoneNumber
this.msg.detailAddress = item.detailAddress
this.msg.defaultStatus = item.defaultStatus
this.msg.id = item.id
} else {
this.popupTitle = '新增收货地址'
this.msg.name = ''
this.msg.phoneNumber = ''
this.msg.detailAddress = ''
this.msg.defaultStatus = false
this.msg.id = ''
}
}
},
created () {
var userInfo = getStore('userInfo');
if (!userInfo) {
this.$router.push({ path: '/login' })
}
this.userId = getStore('userId')
this._addressList()
},
components: {
YButton,
YPopup,
YShelf
}
}
</script>
<style scoped lang="scss">
.table-title {
position: relative;
z-index: 1;
line-height: 38px;
height: 38px;
padding: 0 0 0 38px;
font-size: 12px;
background: #eee;
border-bottom: 1px solid #dbdbdb;
border-bottom-color: rgba(0, 0, 0, .08);
.name {
float: left;
text-align: left;
}
span {
width: 137px;
float: left;
text-align: center;
color: #838383;
}
.address {
margin-left: 115px;
}
.tel {
margin-left: 195px;
}
}
.address-item {
display: flex;
align-items: center;
height: 115px;
text-align: center;
.name {
width: 106px;
}
.address-msg {
flex: 1;
}
.telephone {
width: 160px;
}
.defalut {
width: 80px;
> a {
text-align: center;
/*display: none;*/
}
}
.operation {
width: 135px;
a {
padding: 10px 5px;
}
}
&:hover {
.defalut > a {
display: block;
}
}
}
.address-item + .address-item {
border-top: 1px solid #CFCFCF;
}
.defalut-address {
color: #626262;
display: block;
pointer-events: none;
cursor: default;
}
.md {
> div {
text-align: left;
margin-bottom: 15px;
> input {
width: 100%;
height: 50px;
font-size: 18px;
padding: 10px 20px;
border: 1px solid #ccc;
border-radius: 6px;
box-shadow: 0 3px 5px -4px rgba(0, 0, 0, .4) inset, -1px 0 3px -2px rgba(0, 0, 0, .1) inset;
line-height: 46px;
}
}
}
.btn {
margin: 0;
width: 100%;
height: 50px;
font-size: 14px;
line-height: 48px
}
</style>

View File

@@ -0,0 +1,28 @@
<template>
<div>
<y-shelf title="以旧换新">
<div slot="content">
<div style="padding: 100px 0;text-align: center">
<img src="/static/images/smile.png">
<br>
<span class="support">请问你拿什么和我换新</span>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import YShelf from '/components/shelf'
export default {
components: {
YShelf
}
}
</script>
<style lang="scss" scoped>
.support {
line-height: 2em;
font-size: 22px;
color: #999;
}
</style>

View File

@@ -0,0 +1,28 @@
<template>
<div>
<y-shelf title="我的优惠">
<div slot="content">
<div style="padding: 100px 0;text-align: center">
<img src="/static/images/no-search.png">
<br>
<span class="no-discount">您目前还没有优惠券</span>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import YShelf from '/components/shelf'
export default {
components: {
YShelf
}
}
</script>
<style lang="scss" scoped>
.no-discount {
line-height: 2em;
font-size: 22px;
color: #999;
}
</style>

View File

@@ -0,0 +1,332 @@
<template>
<div>
<y-shelf title="账户资料">
<div slot="content">
<div class="avatar-box">
<div class=img-box><img :src="userInfo.icon" alt=""></div>
<div class="r-box">
<h3 style="margin-left: 13px;">修改头像</h3>
<y-button text="上传头像" classStyle="main-btn" style="margin: 0;" @btnClick="editAvatar()"></y-button>
</div>
</div>
<div class="edit-avatar" v-if="editAvatarShow">
<y-shelf title="设置头像">
<span slot="right">
<span class="close" @click="editAvatarShow=false">
<svg t="1501234940517" class="icon" style="" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="3014" xmlns:xlink="http://www.w3.org/1999/xlink"
width="20" height="20"><path
d="M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z"
fill="#cdcdcd" p-id="3015"></path></svg>
</span>
</span>
<div slot="content" class="content">
<div class="edit-l">
<div style="width: 100px;height: 100px;border: 1px solid #ccc;margin-bottom: 20px;overflow: hidden;">
<div class="show-preview"
:style="{'width': previews.w + 'px','height': previews.h + 'px','overflow': 'hidden','zoom':option.zoom}">
<div :style="previews.div">
<img :src="option.img"
:style="previews.img"
>
</div>
</div>
</div>
<div style="padding: 10px 0 ">头像预览</div>
<div class="btn">
<a href="javascript:;">重新选择</a>
<input type="file" value="上传头像" @change="upimg($event)"></div>
</div>
<div class="edit-r">
<div>
<div class="big" id="cropper-target" v-if="option.img">
<vueCropper
:img="option.img"
@realTime="realTime"
ref="cropper"
:outputSize="example2.size"
:info="example2.info"
:canScale="example2.canScale"
:autoCrop="example2.autoCrop"
:autoCropWidth="example2.width"
:autoCropHeight="example2.height"
:fixed="example2.fixed"
></vueCropper>
</div>
</div>
</div>
<div class="bootom-btn pa">
<y-button style="width: 140px;height: 40px;line-height: 40px"
text="取消"
@btnClick="editAvatarShow=false">
</y-button>
<y-button style="width: 140px;height: 40px;line-height: 40px"
text="确定"
classStyle="main-btn"
@btnClick="cropper">
</y-button>
</div>
</div>
</y-shelf>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import YButton from '/components/YButton'
import { upload } from '/api/index'
import YShelf from '/components/shelf'
import vueCropper from 'vue-cropper'
import { mapState, mapMutations } from 'vuex'
import { getStore } from '/utils/storage'
export default {
data () {
return {
userInfo:null,
imgSrc: '',
editAvatarShow: false,
cropContext: '',
cropperImg: '',
previews: {},
option: {
img: '',
zoom: 0
},
fixedNumber: [1, 1],
example2: {
info: true,
size: 1,
canScale: false,
autoCrop: true,
// 只有自动截图开启 宽度高度才生效
autoCropWidth: 300,
autoCropHeight: 250,
// 开启宽度和高度比例
fixed: true
},
userId: '',
token: ''
}
},
methods: {
...mapMutations([
'RECORD_USERINFO'
]),
message (m) {
this.$message(m)
},
messageSuccess (m) {
this.$message({
message: m,
type: 'success'
})
},
messageFail (m) {
this.$message.error({
message: m
})
},
upimg (e) {
var file = e.target.files[0]
if (file.size > 1048576) {
this.messageFail('图片大小不得超过1Mb')
return false
}
if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
this.messageFail('图片类型仅支持.gif,jpeg,jpg,png,bmp')
return false
}
var reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = (e) => {
this.option.img = e.target.result
}
},
cropper () {
this.message('上传中...')
if (this.option.img) {
this.$refs.cropper.getCropData((data) => {
this.imgSrc = data
upload({userId: this.userId, token: this.token, imgData: data}).then(res => {
if (res.code === 200) {
let path = res.data
let info = this.userInfo
info.file = path
this.RECORD_USERINFO({info: info})
this.editAvatarShow = false
this.messageSuccess('上传成功')
} else {
this.messageFail(res.msg)
}
})
})
} else {
this.messageFail('别玩我啊 先选照骗')
}
},
editAvatar () {
this.editAvatarShow = true
},
realTime (data) {
this.previews = data
let w = 100 / data.w
this.option.zoom = w
}
},
created () {
var userInfo = getStore('userInfo');
if (!userInfo) {
this.$router.push({ path: '/login' })
}
this.userInfo=userInfo;
this.token = getStore('token')
},
components: {
YButton,
YShelf,
vueCropper
}
}
</script>
<style lang="scss" scoped>
@import "../../../assets/style/mixin";
.avatar-box {
height: 124px;
display: flex;
margin: 0 30px 30px;
border-bottom: #dadada solid 1px;
line-height: 30px;
display: flex;
align-items: center;
.img-box {
@include wh(80px);
border-radius: 5px;
overflow: hidden;
}
img {
display: block;
@include wh(100%)
}
.r-box {
margin-left: 20px;
h3 {
font-size: 18px;
font-weight: 400;
color: #333;
}
}
}
// 修改头像
.edit-avatar {
z-index: 9999;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
@include wh(100%);
background-color: rgba(0, 0, 0, .5);
@extend %block-center;
.content {
display: flex;
padding: 45px 100px 0;
}
> div {
box-sizing: content-box;
@include wh(700px, 500px);
margin: 0;
}
.btn {
width: 80px;
height: 30px;
margin-left: 10px;
position: relative;
text-align: center;
line-height: 30px;
text-shadow: rgba(255, 255, 255, .496094) 0 1px 0;
border: 1px solid #E6E6E6;
border-radius: 10px;
&:hover {
}
a {
color: #666;
display: block;
@include wh(100%);
}
}
input[type=file] {
position: absolute;
right: 0;
left: 0;
top: 0;
opacity: 0;
width: 80px;
height: 30px;
cursor: pointer;
box-sizing: border-box;
border: 15px solid #000;
overflow: hidden;
}
.edit-l {
width: 100px;
text-align: center;
}
.edit-r {
margin-left: 20px;
flex: 1;
> div {
border: 1px solid #ccc;
width: 320px;
height: 320px;
}
}
}
.image-container {
width: 100px;
height: 100px;
border: 1px solid #ccc;
}
.close {
position: absolute;
right: 10px;
top: 0;
bottom: 0;
padding: 0 10px;
@extend %block-center;
&:hover {
svg {
transition: all 1s;
transform: rotate(360deg);
transform-origin: 50% 50%;
}
path {
fill: #8a8a8a;
}
}
}
.big {
display: block;
width: 320px;
height: 320px;
}
.bootom-btn {
padding: 0 15px;
border-top: 1px solid #E6E6E6;
bottom: 0;
height: 60px;
right: 0;
left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
</style>

View File

@@ -0,0 +1,302 @@
<template>
<div>
<y-shelf title="我的订单">
<div slot="content">
<div v-loading="loading" element-loading-text="加载中..." v-if="orderLists.length>0" style="min-height: 10vw;">
<div v-for="(item,i) in orderLists" :key="i">
<div class="gray-sub-title cart-title">
<div class="first">
<div>
<span class="date" v-text="item.createDate"></span>
<span class="order-id"> 订单号 <a @click="orderDetail(item.id)">{{item.orderSn}}</a> </span>
</div>
<div class="f-bc">
<span class="price">单价</span>
<span class="num">数量</span>
<span class="operation">商品操作</span>
</div>
</div>
<div class="last">
<span class="sub-total">实付金额</span>
<span class="order-detail"> <a @click="orderDetail(item.id)">查看详情 ><em class="icon-font"></em></a> </span>
</div>
</div>
<div class="pr">
<div class="cart" v-for="(good,j) in item.orderItemList" :key="j">
<div class="cart-l" :class="{bt:j>0}">
<div class="car-l-l">
<div class="img-box"><a @click="goodsDetails(good.productId)"><img :src="good.productPic" alt=""></a></div>
<div class="ellipsis"><a style="color: #626262;" @click="goodsDetails(good.productId)">{{good.productName}}</a></div>
</div>
<div class="cart-l-r">
<div>¥ {{Number(good.productPrice).toFixed(2)}}</div>
<div class="num">{{good.productName}}</div>
<div class="type">
<el-button style="margin-left:20px" @click="_delOrder(item.orderId,i)" type="danger" size="small" v-if="j<1" class="del-order">删除此订单</el-button>
<!-- <a @click="_delOrder(item.orderId,i)" href="javascript:;" v-if="j<1" class="del-order">删除此订单</a> -->
</div>
</div>
</div>
<div class="cart-r">
<span></span>
<span></span>
</div>
</div>
<div class="prod-operation pa" style="right: 0;top: 0;">
<div class="total">¥ {{item.totalAmount}}</div>
<div v-if="item.status === '0'">
<el-button @click="orderPayment(item.orderId)" type="primary" size="small">现在付款</el-button>
</div>
<div class="status" v-if="item.status !== '0'"> {{getOrderStatus(item.status)}} </div>
</div>
</div>
</div>
</div>
<div v-loading="loading" element-loading-text="加载中..." class="no-info" v-else>
<div style="padding: 100px 0;text-align: center">
你还未创建过订单
</div>
</div>
</div>
</y-shelf>
<div style="float:right">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[5, 10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
</div>
</div>
</template>
<script>
import { orderList, delOrder } from '/api/goods'
import YShelf from '/components/shelf'
import { getStore } from '/utils/storage'
export default {
data () {
return {
orderLists: [0],
userId: '',
orderStatus: '',
loading: true,
currentPage: 1,
pageSize: 5,
total: 0
}
},
methods: {
message (m) {
this.$message.error({
message: m
})
},
handleSizeChange (val) {
this.pageSize = val
this._orderList()
},
handleCurrentChange (val) {
this.currentPage = val
this._orderList()
},
orderPayment (orderId) {
window.open(window.location.origin + '#/order/payment?orderId=' + orderId)
},
goodsDetails (id) {
window.open(window.location.origin + '#/goodsDetails?id=' + id)
},
orderDetail (orderId) {
this.$router.push({
path: 'orderDetail',
query: {
orderId: orderId
}
})
},
getOrderStatus (status) {
if (status === '1') {
return '支付审核中'
} else if (status === '2') {
return '待发货'
} else if (status === '3') {
return '待收货'
} else if (status === '4') {
return '交易成功'
} else if (status === '5') {
return '交易关闭'
} else if (status === '6') {
return '支付失败'
}
},
_orderList () {
var userInfo = getStore('userInfo');
if (!userInfo) {
this.$router.push({ path: '/login' })
}
let params = {
pageSize: this.pageSize,
pageNum: this.currentPage
}
orderList(params).then(res => {
this.orderLists = res.data.records
this.total = res.data.total
this.loading = false
})
},
_delOrder (orderId, i) {
let params = {
orderId: orderId
}
delOrder(params).then(res => {
if (res.code === 200) {
this.orderLists.splice(i, 1)
} else {
this.message('删除失败')
}
})
}
},
created () {
this.userId = getStore('userId')
this._orderList()
},
components: {
YShelf
}
}
</script>
<style lang="scss" scoped>
@import "../../../assets/style/mixin";
.gray-sub-title {
height: 38px;
padding: 0 24px;
background: #EEE;
border-top: 1px solid #DBDBDB;
border-bottom: 1px solid #DBDBDB;
line-height: 38px;
font-size: 12px;
color: #666;
display: flex;
span {
display: inline-block;
height: 100%;
}
.first {
display: flex;
justify-content: space-between;
flex: 1;
.f-bc {
> span {
width: 112px;
text-align: center;
}
}
}
.last {
width: 230px;
text-align: center;
display: flex;
border-left: 1px solid #ccc;
span {
flex: 1;
}
}
}
.bt {
border-top: 1px solid #EFEFEF;
}
.date {
padding-left: 0px;
}
.order-id {
margin-left: 25px;
}
.cart {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
&:hover {
.del-order {
display: block;
}
}
.del-order {
display: none;
}
.cart-l {
display: flex;
align-items: center;
flex: 1;
padding: 15px 0;
justify-content: space-between;
position: relative;
&:before {
position: absolute;
content: ' ';
right: -1px;
top: 0;
width: 1px;
background-color: #EFEFEF;
height: 100%;
}
.ellipsis {
margin-left: 20px;
width: 220px;
}
.img-box {
border: 1px solid #EBEBEB;
}
img {
display: block;
@include wh(80px);
}
.cart-l-r {
display: flex;
> div {
text-align: center;
width: 112px;
}
}
.car-l-l {
display: flex;
align-items: center;
}
}
.cart-r {
width: 230px;
display: flex;
span {
text-align: center;
flex: 1;
}
}
}
.prod-operation {
height: 110px;
display: flex;
align-items: center;
justify-content: center;
width: 254px;
div {
width: 100%;
text-align: center;
}
div:last-child {
padding-right: 24px;
}
}
</style>

View File

@@ -0,0 +1,462 @@
<template>
<div>
<y-shelf v-bind:title="orderTitle">
<div slot="content">
<div v-loading="loading" element-loading-text="加载中..." style="min-height: 10vw;" v-if="orderList.length">
<div class="status" v-if="status !== -1 && status !== 6">
<el-steps :space="200" :active="status">
<el-step title="下单" v-bind:description="createTime"></el-step>
<el-step title="付款" v-bind:description="payTime"></el-step>
<el-step title="配货" description=""></el-step>
<el-step title="出库" description=""></el-step>
<el-step title="交易成功" v-bind:description="finishTime"></el-step>
</el-steps>
</div>
<div class="status-close" v-if="status === -1">
<el-steps :space="780" :active="2">
<el-step title="下单" v-bind:description="createTime"></el-step>
<el-step title="交易关闭" v-bind:description="closeTime"></el-step>
</el-steps>
</div>
<div class="status-close" v-if="status === 6">
<el-steps :space="780" :active="2">
<el-step title="下单" v-bind:description="createTime"></el-step>
<el-step title="交易关闭" v-bind:description="closeTime"></el-step>
</el-steps>
</div>
<div class="status-now" v-if="status === 1">
<ul>
<li class="status-title"><h3>订单状态待付款</h3></li>
<li class="button">
<el-button @click="orderPayment(orderId)" type="primary" size="small">现在付款</el-button>
<el-button @click="_cancelOrder()" size="small">取消订单</el-button>
</li>
</ul>
<p class="realtime">
<span>您的付款时间还有 </span>
<span class="red"><countDown v-bind:endTime="countTime" endText="已结束"></countDown></span>
<span>超时后订单将自动取消</span>
</p>
</div>
<div class="status-now" v-if="status === 2">
<ul>
<li class="status-title"><h3>订单状态已支付待系统审核确认</h3></li>
</ul>
<p class="realtime">
<span>请耐心等待审核审核结果将发送到您的邮箱并且您所填写的捐赠数据将显示在捐赠表中</span>
</p>
</div>
<div class="status-now" v-if="status === -1 || status === 6">
<ul>
<li class="status-title"><h3>订单状态已关闭</h3></li>
</ul>
<p class="realtime">
<span>您的订单已关闭</span>
</p>
</div>
<div class="status-now" v-if="status === 5">
<ul>
<li class="status-title"><h3>订单状态已完成</h3></li>
</ul>
<p class="realtime">
<span>您的订单已交易成功感谢您的惠顾</span>
</p>
</div>
<div class="gray-sub-title cart-title">
<div class="first">
<div>
<span class="order-id">商品名称</span>
</div>
<div class="f-bc">
<span class="price">单价</span>
<span class="num">数量</span>
<span class="operation">小计</span>
</div>
</div>
</div>
<!--商品-->
<div class="goods-table">
<div class="cart-items" v-for="(item,i) in orderList" :key="i">
<a @click="goodsDetails(item.productId)" class="img-box"><img :src="item.productPic" alt=""></a>
<div class="name-cell ellipsis">
<a @click="goodsDetails(item.productId)" title="" target="_blank">{{item.productName}}</a>
</div>
<div class="n-b">
<div class="price">¥ {{Number(item.productPrice).toFixed(2)}}</div>
<div class="goods-num">{{item.productQuantity}}</div>
<div class="subtotal"> ¥ {{Number(item.productPrice * item.productQuantity).toFixed(2)}}</div>
</div>
</div>
</div>
<!--合计-->
<div class="order-discount-line">
<p style="font-size: 14px;font-weight: bolder;"> <span style="padding-right:47px">商品总计</span>
<span style="font-size: 16px;font-weight: 500;line-height: 32px;">¥ {{orderTotal}}</span>
</p>
<p><span style="padding-right:30px">运费</span><span style="font-weight: 700;">+ ¥ 0.00</span></p>
<p class="price-total"><span>应付金额</span><span class="price-red">¥ {{payTotal}}</span></p>
</div>
<div class="gray-sub-title cart-title">
<div class="first">
<div>
<span class="order-id">收货信息</span>
</div>
</div>
</div>
<div style="height: 155px;padding: 20px 30px;">
<p class="address">姓名{{ userName }}</p>
<p class="address">联系电话{{ tel }}</p>
<p class="address">详细地址{{ streetName }}</p>
</div>
</div>
<div v-loading="loading" element-loading-text="加载中..." v-else>
<div style="padding: 100px 0;text-align: center">
获取该订单信息失败
</div>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import { getOrderDet, cancelOrder } from '/api/goods'
import YShelf from '/components/shelf'
import { getStore } from '/utils/storage'
import countDown from '/components/countDown'
export default {
data () {
return {
orderList: [0],
userId: '',
status: 0,
orderId: '',
userName: '',
tel: '',
streetName: '',
orderTitle: '',
createTime: '',
payTime: '',
closeTime: '',
finishTime: '',
orderTotal: '',
payTotal: '',
loading: true,
countTime: 0
}
},
methods: {
message (m) {
this.$message.error({
message: m
})
},
orderPayment (orderId) {
window.open(window.location.origin + '#/order/payment?orderId=' + orderId)
},
goodsDetails (id) {
window.open(window.location.origin + '#/goodsDetails?id=' + id)
},
_getOrderDet () {
let params = {
id: this.orderId
}
getOrderDet(params).then(res => {
if (res.data.status === '0') {
this.status = 1
} else if (res.data.status === '1') {
this.status = 2
} else if (res.data.status === '4') {
this.status = 5
} else if (res.data.status === '5') {
this.status = -1
} else if (res.data.status === '6') {
this.status = 6
}
this.orderList = res.data.orderItemList
this.payTotal = res.data.payAmount
this.orderTotal = res.data.totalAmount
this.userName = res.data.receiverName
this.tel = res.data.receiverPhone
this.streetName = res.data.receiverDetailAddress
this.createTime = res.data.createTime
this.closeTime = res.data.createTime
this.payTime = res.data.paymentTime
if (this.status === 5) {
this.finishTime = res.data.deliveryTime
} else {
this.countTime = res.data.deliveryTime
}
this.loading = false
})
},
_cancelOrder () {
cancelOrder({orderId: this.orderId}).then(res => {
if (res.code === 200) {
this._getOrderDet()
} else {
this.message('取消失败')
}
})
}
},
created () {
this.userId = getStore('userId')
this.orderId = this.$route.query.orderId
this.orderTitle = '订单号:' + this.orderId
this._getOrderDet()
},
components: {
YShelf,
countDown
}
}
</script>
<style lang="scss" scoped>
@import "../../../assets/style/mixin";
.status {
display: flex;
align-items: center;
flex-direction: row;
margin: 50px -150px 20px 60px;
}
.status-close {
display: flex;
align-items: center;
flex-direction: row;
margin: 50px -800px 20px 60px;
}
.status-now {
background: #F6F6F6;
border: 1px solid #dadada;
border-radius: 5px;
padding: 22px 30px 20px;
margin: 0 30px 30px 30px;
line-height: 38px;
}
.status-title {
font-size: 18px;
color: #666;
}
.button {
float: right;
margin: -37px 0 20px 0;
}
.realtime {
border-top: 1px solid #dcdcdc;
margin-top: 20px;
padding-top: 26px;
}
.red {
color: #d44d44;
}
.address {
line-height: 38px;
word-wrap: break-word;
word-spacing: normal;
word-break: break-all;
color: #626262;
}
.img-box {
border: 1px solid #EBEBEB;
margin-left: -80px;
}
img {
display: block;
@include wh(80px);
}
.goods-table {
.n-b {
display: flex;
align-items: center;
justify-content: center;
> div {
color: #626262;
font-weight: 700;
width: 165px;
text-align: center;
}
}
.cart-items {
display: flex;
align-items: center;
justify-content: space-between;
height: 110px;
padding: 15px 0 15px 111px;
border-bottom: 1px solid #EFEFEF;
a {
color: #333;
}
}
.price {
padding-left: 107px;
}
.goods-num {
padding-left: 60px;
}
}
.order-discount-line {
padding: 22px 30px 20px;
line-height: 24px;
text-align: right;
font-size: 12px;
&:first-child {
line-height: 32px;
text-align: right;
font-size: 14px;
font-weight: bolder;
}
}
.gray-sub-title {
height: 38px;
padding: 0 24px;
background: #EEE;
border-top: 1px solid #DBDBDB;
border-bottom: 1px solid #DBDBDB;
line-height: 38px;
font-size: 12px;
color: #666;
display: flex;
span {
display: inline-block;
height: 100%;
}
.first {
display: flex;
justify-content: space-between;
flex: 1;
.f-bc {
> span {
width: 130px;
text-align: center;
}
}
}
.last {
width: 230px;
text-align: center;
display: flex;
border-left: 1px solid #ccc;
span {
flex: 1;
}
}
}
.bt {
border-top: 1px solid #EFEFEF;
}
.date {
padding-left: 0px;
}
.order-id {
margin-left: 10px;
}
.cart {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
&:hover {
.del-order {
display: block;
}
}
.del-order {
display: none;
}
.cart-l {
display: flex;
align-items: center;
flex: 1;
padding: 15px 0;
justify-content: space-between;
position: relative;
&:before {
position: absolute;
content: ' ';
right: -1px;
top: 0;
width: 1px;
background-color: #EFEFEF;
height: 100%;
}
.ellipsis {
margin-left: 20px;
width: 220px;
}
.img-box {
border: 1px solid #EBEBEB;
}
img {
display: block;
@include wh(80px);
}
.cart-l-r {
display: flex;
> div {
text-align: center;
width: 112px;
}
}
.car-l-l {
display: flex;
align-items: center;
}
}
.cart-r {
width: 230px;
display: flex;
span {
text-align: center;
flex: 1;
}
}
}
.prod-operation {
height: 110px;
display: flex;
align-items: center;
justify-content: center;
width: 254px;
div {
width: 100%;
text-align: center;
}
div:last-child {
padding-right: 24px;
}
}
.price-total {
height: 54px;
line-height: 54px;
font-size: 18px;
}
.price-red {
font-weight: 700;
color: #d44d44;
}
</style>

View File

@@ -0,0 +1,28 @@
<template>
<div>
<y-shelf title="售后服务">
<div slot="content">
<div style="padding: 100px 0;text-align: center">
<img src="/static/images/support.png">
<br>
<span class="support">如有疑问请联系邮箱1012139570@qq.com</span>
</div>
</div>
</y-shelf>
</div>
</template>
<script>
import YShelf from '/components/shelf'
export default {
components: {
YShelf
}
}
</script>
<style lang="scss" scoped>
.support {
line-height: 2em;
font-size: 22px;
color: #999;
}
</style>

View File

@@ -0,0 +1,159 @@
<template>
<div class="layout-container">
<y-header>
<div slot="nav"></div>
</y-header>
<div class="w">
<div class="content">
<div class="account-sidebar">
<div class="avatar gray-box ">
<div>
<img :src="userInfo.icon"> <h5>
{{userInfo.username}}</h5></div>
<div class="box-inner">
<ul class="account-nav">
<li v-for="(item,i) in nav" :key='i' :class="{current:item.name===title}"
@click="tab(item)">
<a href="javascript:;">{{item.name}}</a></li>
</ul>
</div>
</div>
</div>
<div class="account-content">
<router-view></router-view>
</div>
</div>
</div>
<y-footer></y-footer>
</div>
</template>
<script>
import YFooter from '/common/footer'
import YHeader from '/common/header'
import { mapState } from 'vuex'
import { getStore } from '/utils/storage'
export default {
data () {
return {
userInfo:null,
title: '我的订单',
nav: [
{name: '我的订单', path: 'orderList'},
{name: '账户资料', path: 'information'},
{name: '收货地址', path: 'addressList'},
{name: '我的优惠', path: 'coupon'},
{name: '售后服务', path: 'support'},
{name: '以旧换新', path: 'aihuishou'}
],
editAvatar: true
}
},
methods: {
tab (e) {
this.$router.push({path: '/user/' + e.path})
}
},
created () {
var userInfo = getStore('userInfo');
if (!userInfo) {
this.$router.push({ path: '/login' })
}
this.userInfo=userInfo;
let path = this.$route.path.split('/')[2]
this.nav.forEach(item => {
if (item.path === path) {
this.title = item.name
}
})
},
components: {
YFooter,
YHeader
},
watch: {
$route (to) {
let path = to.path.split('/')[2]
this.nav.forEach(item => {
if (item.path === path) {
this.title = item.name
}
})
}
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "../../assets/style/mixin";
.w {
padding-top: 40px;
}
.content {
display: flex;
height: 100%;
}
.account-sidebar {
width: 210px;
border-radius: 6px;
.avatar {
padding-top: 20px;
border-radius: 10px;
text-align: center;
img {
width: 168px;
height: 168px;
}
h5 {
font-size: 18px;
line-height: 48px;
font-weight: 700;
}
}
.account-nav {
padding-top: 15px;
li {
position: relative;
height: 48px;
border-top: 1px solid #EBEBEB;
line-height: 48px;
&:hover {
a {
position: relative;
z-index: 1;
height: 50px;
background-color: #98AFEE;
line-height: 50px;
color: #FFF;
}
}
a {
display: block;
}
&.current {
a {
position: relative;
z-index: 1;
height: 50px;
background-color: #98AFEE;
line-height: 50px;
color: #FFF;
}
}
}
}
}
.account-content {
margin-left: 20px;
flex: 1;
}
</style>

View File

@@ -0,0 +1,98 @@
<template>
<div>
<y-header></y-header>
<router-view class="main"></router-view>
<y-footer></y-footer>
<!--抛物图片-->
<transition @after-enter='afterEnter' @before-enter="beforeEnter">
<!--整张图片-->
<div class="move_img" v-if="showMoveImg"
:style="{left:(cartPositionL-10) + 'px',top:(cartPositionT-10) + 'px'}">
<div><img :src="moveImgUrl"></div>
</div>
</transition>
</div>
</template>
<script>
import YHeader from '/common/header'
import YFooter from '/common/footer'
import { mapState, mapMutations } from 'vuex'
export default {
data () {
return {}
},
computed: {
...mapState(['cartPositionT', 'cartPositionL', 'showMoveImg', 'elLeft', 'elTop', 'moveImgUrl'])
},
methods: {
...mapMutations(['ADD_ANIMATION']),
// 监听图片进入购物车
listenInCart () {
this.ADD_ANIMATION({moveShow: false, receiveInCart: true})
},
beforeEnter (el) {
let elStyle = el.style
let elChild = el.children[0]
let elChildSty = elChild.style
elStyle.transform = `translate3d(0,${this.elTop - this.cartPositionT}px,0)`
elChildSty.transform = `translate3d(${-(this.cartPositionL - this.elLeft)}px,0,0) scale(1.2)`
},
afterEnter (el) {
let elStyle = el.style
let elChild = el.children[0]
let elChildSty = elChild.style
elStyle.transform = `translate3d(0,0,0)`
elChildSty.transform = `translate3d(0,0,0) scale(.2)`
elStyle.transition = 'transform .55s cubic-bezier(.29,.55,.51,1.08)'
elChildSty.transition = 'transform .55s linear'
// 动画结束
elChild.addEventListener('transitionend', () => {
this.listenInCart()
})
elChild.addEventListener('webkitAnimationEnd', () => {
this.listenInCart()
})
}
},
components: {
YHeader,
YFooter
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "../assets/style/mixin";
.main {
min-height: calc(100vh - 454px);
background: #ededed;
overflow: hidden;
width: 100%;
}
.bn {
border-style: none;
border-width: 0;
border: none;
}
.move_img {
position: fixed;
@include wh(40px);
width: 45px;
z-index: 29;
height: 45px;
div {
@extend .bn;
}
img {
border-radius: 50%;
width: 100%;
height: 100%;
display: block;
@extend .bn;
}
}
</style>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

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