Commit 5bca13074e51de1cc5a3289df083f0292f22708d

Authored by 范牧
1 parent fe62536c34
Exists in master

分享功能

1 module.exports = { 1 module.exports = {
2 "env": { 2 "env": {
3 "browser": true, 3 "browser": true,
4 "es6": true 4 "es6": true
5 }, 5 },
6 "extends": [ 6 "extends": [
7 'standard', 7 'standard',
8 "eslint:recommended", 8 "eslint:recommended",
9 "plugin:vue/essential", 9 "plugin:vue/essential",
10 "plugin:@typescript-eslint/eslint-recommended", 10 "plugin:@typescript-eslint/eslint-recommended",
11 ], 11 ],
12 "globals": { 12 "globals": {
13 "Atomics": "readonly", 13 "Atomics": "readonly",
14 "SharedArrayBuffer": "readonly", 14 "SharedArrayBuffer": "readonly",
15 "uni": true, 15 "uni": true,
16 "wx": true,
16 "module": true 17 "module": true
17 }, 18 },
18 "parserOptions": { 19 "parserOptions": {
19 "ecmaVersion": 11, 20 "ecmaVersion": 11,
20 "parser": "@typescript-eslint/parser", 21 "parser": "@typescript-eslint/parser",
21 "sourceType": "module" 22 "sourceType": "module"
22 }, 23 },
23 "plugins": [ 24 "plugins": [
24 "vue", 25 "vue",
25 "@typescript-eslint" 26 "@typescript-eslint"
26 ], 27 ],
27 "rules": { 28 "rules": {
28 quotes: ['error', 'single'], 29 quotes: ['error', 'single'],
29 'space-before-function-paren': 0, 30 'space-before-function-paren': 0,
30 // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号, 31 // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,
31 // always-multiline:多行模式必须带逗号,单行模式不能带逗号 32 // always-multiline:多行模式必须带逗号,单行模式不能带逗号
32 "comma-dangle": [2, "always-multiline"], 33 "comma-dangle": [2, "always-multiline"],
33 // 控制逗号前后的空格 34 // 控制逗号前后的空格
34 "comma-spacing": [2, { "before": false, "after": true }], 35 "comma-spacing": [2, { "before": false, "after": true }],
35 // 控制逗号在行尾出现还是在行首出现 36 // 控制逗号在行尾出现还是在行首出现
36 // http://eslint.org/docs/rules/comma-style 37 // http://eslint.org/docs/rules/comma-style
37 "comma-style": [2, "last"], 38 "comma-style": [2, "last"],
38 } 39 }
39 }; 40 };
40 41
src/components/uni-popup/popup.js
File was created 1 // import message from './message.js'
2 // 定义 type 类型:弹出类型:top/bottom/center
3 const config = {
4 // 顶部弹出
5 top: 'top',
6 // 底部弹出
7 bottom: 'bottom',
8 // 居中弹出
9 center: 'center',
10 // 消息提示
11 message: 'top',
12 // 对话框
13 dialog: 'center',
14 // 分享
15 share: 'bottom',
16 }
17
18 export default {
19 data() {
20 return {
21 config: config,
22 }
23 },
24 // mixins: [message],
25 }
26
src/components/uni-popup/uni-popup-post.vue
File was created 1 <template>
2 <view class="uni-popup-post">
3 <image
4 class="uni_post_img"
5 :src="postUrl"
6 />
7 <view
8 @tap="saveAndClose"
9 class="uni_post_button_box"
10 >
11 保存图片
12 </view>
13 </view>
14 </template>
15
16 <script>
17 export default {
18 name: 'UniPopupPost',
19 props: {
20 postUrl: {
21 type: String,
22 default: 'https://api.glass.xiuyetang.com/adv_pic/428_0_7.png',
23 },
24 },
25 inject: ['popup'],
26 data() {
27 return {}
28 },
29 created() {
30 console.log('dada', this)
31 },
32 methods: {
33 // 保存图片并关闭窗口
34 saveAndClose() {
35 // 获取用户保存相册权限
36 const scope = 'scope.writePhotosAlbum'
37 const that = this
38 uni.getSetting({
39 success(res) {
40 console.log('获取用户保存相册权限', res)
41 if (!res.authSetting[scope]) {
42 uni.authorize({
43 scope,
44 success() {
45 console.log('获取用户保存相册权限---->', '授权成功')
46 // 保存到相册
47 uni.showLoading({
48 title: '保存中',
49 })
50 that.saveImage()
51 },
52 fail() {
53 console.log('获取用户保存相册权限---->', '授权失败')
54 that.secondGetPhoteAuthor()
55 },
56 })
57 } else {
58 console.log('拥有授权权限')
59 // 保存到相册
60 uni.showLoading({
61 title: '保存中',
62 })
63 that.saveImage()
64 }
65
66 that.popup.close()
67 },
68 fail(res) {
69 console.log('授权失败------>', res)
70 uni.showToast({
71 title: '保存失败',
72 icon: 'none',
73 duration: 2000,
74 })
75 },
76 })
77 },
78 // 保存到相册
79 saveImage() {
80 const that = this
81 uni.getImageInfo({
82 src: that.postUrl,
83 success(res) {
84 console.log('图片读取是否可行', res)
85 uni.saveImageToPhotosAlbum({
86 filePath: res.path,
87 success() {
88 uni.showToast({
89 title: '已保存到相册',
90 icon: 'none',
91 duration: 2000,
92 })
93 uni.hideLoading()
94 },
95 fail(err) {
96 console.log('用户拒绝', err)
97 if (err.errMsg === 'saveImageToPhotosAlbum:fail auth deny') {
98 console.log('当用户拒绝,再次发起授权')
99 that.secondGetPhoteAuthor()
100 } else if (err.errMsg === 'saveImageToPhotosAlbum:fail cancel') {
101 uni.showToast({
102 title: '已取消保存',
103 icon: 'none',
104 duration: 2000,
105 })
106 uni.hideLoading()
107 } else {
108 uni.showToast({
109 title: '请截屏保存分享',
110 icon: 'none',
111 duration: 2000,
112 })
113 uni.hideLoading()
114 }
115 },
116 })
117 },
118 fail(res) {
119 console.log('授权失败----->', res)
120 uni.hideLoading()
121 uni.showToast({
122 title: '保存失败',
123 icon: 'none',
124 duration: 2000,
125 })
126 },
127 })
128 },
129 // 二次请求授权
130 secondGetPhoteAuthor() {
131 const that = this
132 uni.showModal({
133 title: '保存海报',
134 content: '需要您提供保存相册权限',
135 success: (res) => {
136 if (res.confirm) {
137 uni.openSetting({
138 success(settingdata) {
139 console.log('settingdata 二次弹窗获取', settingdata)
140 if (settingdata.authSetting['scope.writePhotosAlbum']) {
141 console.log('二次弹窗获取---->', '获取 相册 权限成功,给出再次点击图片保存到相册的提示。')
142 uni.showLoading({
143 title: '保存中',
144 })
145 that.saveImage()
146 } else {
147 uni.showToast({
148 title: '保存失败',
149 icon: 'none',
150 duration: 2000,
151 })
152 console.log('二次弹窗获取', '获取 相册 权限失败,给出不给权限就无法正常使用的提示')
153 }
154 },
155 })
156 } else {
157 uni.showToast({
158 title: '保存失败',
159 icon: 'none',
160 duration: 2000,
161 })
162 }
163 },
164 fail(err) {
165 uni.showToast({
166 title: '保存失败',
167 icon: 'none',
168 duration: 2000,
169 })
170 console.log('再次失败', err)
171 },
172 })
173 },
174 },
175 }
176 </script>
177 <style lang="scss" scoped>
178 .uni-popup-post {
179 border-radius: 8px 8px 0px 0px;
180 display: flex;
181 flex-direction: column;
182 justify-content: space-between;
183 align-items: center;
184 }
185
186 .uni_post_img {
187 width: 690rpx;
188 height: 466.667px;
189 margin-top: -180rpx;
190 }
191
192 .uni_post_button_box {
193 height: 112rpx;
194 line-height: 112rpx;
195 background-color: #ff6b4a;
196 border-radius: 4px;
197 width: 350px;
198 color: #fff;
199 text-align: center;
200 margin-top: 44rpx;
201 font-family: PingFangSC-Medium;
202 font-size: 14px;
203 color: #ffffff;
204 letter-spacing: -0.26px;
205 text-align: center;
206 }
207 </style>
208
src/components/uni-popup/uni-popup-share.vue
File was created 1 <template>
2 <view class="uni-popup-share">
3 <!-- <view class="uni-share-title"><text class="uni-share-title-text">{{title}}</text></view> -->
4 <view class="uni-share-content">
5 <view class="uni-share-content-box">
6 <button
7 class="uni-share-content-item"
8 v-for="(item,index) in bottomData"
9 :key="index"
10 :open-type="item.name === 'friend' ? 'share': ''"
11 @click.stop="select(item,index)"
12 >
13 <image
14 class="uni-share-image"
15 :src="item.icon"
16 mode="aspectFill"
17 ></image>
18 <view class="uni-share-text">{{item.text}}</view>
19 </button>
20 </view>
21 </view>
22 <view
23 @tap="close"
24 class="uni-share-button-box"
25 >
26 取消
27 </view>
28 </view>
29 </template>
30
31 <script>
32 export default {
33 name: 'UniPopupShare',
34 props: {
35 title: {
36 type: String,
37 default: '分享到',
38 },
39 },
40 inject: ['popup'],
41 data() {
42 return {
43 bottomData: [{
44 text: '推荐到好物圈',
45 icon: '/static/img/share/recommend.png',
46 name: 'recommend',
47 }, {
48 text: '转发给朋友/群',
49 icon: '/static/img/share/friend.png',
50 name: 'friend',
51 }, {
52 text: '生成海报',
53 icon: '/static/img/share/poster.png',
54 name: 'poster',
55 },
56 ],
57 }
58 },
59 created() {},
60 methods: {
61 /**
62 * 选择内容
63 */
64 select(item, index) {
65 this.$emit('select', {
66 item,
67 index,
68 }, () => {
69 this.popup.close()
70 })
71 },
72 /**
73 * 关闭窗口
74 */
75 close() {
76 this.popup.close()
77 },
78 },
79 }
80 </script>
81 <style lang="scss" scoped>
82 .uni-popup-share {
83 background-color: #fff;
84 border-radius: 8px 8px 0px 0px;
85 }
86 .uni-share-title {
87 /* #ifndef APP-NVUE */
88 display: flex;
89 /* #endif */
90 flex-direction: row;
91 align-items: center;
92 justify-content: center;
93 height: 40px;
94 }
95 .uni-share-title-text {
96 font-size: 14px;
97 color: #666;
98 }
99 .uni-share-content {
100 /* #ifndef APP-NVUE */
101 display: flex;
102 /* #endif */
103 flex-direction: row;
104 justify-content: center;
105 padding-top: 10px;
106 }
107
108 .uni-share-content-box {
109 /* #ifndef APP-NVUE */
110 display: flex;
111 /* #endif */
112
113 flex-direction: column;
114 justify-content: space-between;
115 width: 360px;
116 }
117
118 .uni-share-content-item {
119 /* #ifndef APP-NVUE */
120 display: flex;
121 /* #endif */
122 flex-direction: row;
123 flex-wrap: wrap;
124 padding: 10px 0;
125 align-items: center;
126 border-bottom: 1px solid #f2f2f2;
127
128 background-color: #fff;
129 font-family: PingFangSC-Regular;
130 font-size: 16px;
131 color: #333333;
132 letter-spacing: -0.3px;
133 margin: 0;
134 &::after {
135 border: 0;
136 }
137 }
138
139 .uni-share-content-item:active {
140 background-color: #f5f5f5;
141 }
142
143 .uni-share-image {
144 width: 84rpx;
145 height: 84rpx;
146 vertical-align: middle;
147 margin-left: 40rpx;
148 }
149
150 .uni-share-text {
151 font-family: PingFangSC-Regular;
152 font-size: 16px;
153 color: #3b4144;
154 margin-left: 20rpx;
155 }
156 // .share_button {
157 // border: none;
158 // }
159
160 .uni-share-button-box {
161 /* #ifndef APP-NVUE */
162 // display: flex;
163 /* #endif */
164 // flex-direction: row;
165 // padding: 10px 15px;
166 height: 100rpx;
167 font-family: PingFangSC-Regular;
168 font-size: 16px;
169 color: #333333;
170 letter-spacing: -0.3px;
171 text-align: center;
172 line-height: 100rpx;
173 }
174
175 .uni-share-button {
176 flex: 1;
177 border-radius: 50px;
178 color: #666;
179 font-size: 16px;
180 }
181
182 .uni-share-button::after {
183 border-radius: 50px;
184 }
185 </style>
186
src/components/uni-popup/uni-popup.vue
File was created 1 <template>
2 <view
3 v-if="showPopup"
4 class="uni-popup"
5 :class="[popupstyle]"
6 @touchmove.stop.prevent="clear"
7 >
8 <uni-transition
9 v-if="maskShow"
10 :mode-class="['fade']"
11 :styles="maskClass"
12 :duration="duration"
13 :show="showTrans"
14 @click="onTap"
15 />
16 <uni-transition
17 :mode-class="ani"
18 :styles="transClass"
19 :duration="duration"
20 :show="showTrans"
21 @click="onTap"
22 >
23 <view
24 class="uni-popup__wrapper-box"
25 @click.stop="clear"
26 >
27 <slot />
28 </view>
29 </uni-transition>
30 </view>
31 </template>
32
33 <script>
34 import uniTransition from '../uni-transition/uni-transition.vue'
35 import popup from './popup.js'
36 /**
37 * PopUp 弹出层
38 * @description 弹出层组件,为了解决遮罩弹层的问题
39 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
40 * @property {String} type = [top|center|bottom] 弹出方式
41 * @value top 顶部弹出
42 * @value center 中间弹出
43 * @value bottom 底部弹出
44 * @value message 消息提示
45 * @value dialog 对话框
46 * @value share 底部分享示例
47 * @property {Boolean} animation = [ture|false] 是否开启动画
48 * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
49 * @event {Function} change 打开关闭弹窗触发,e={show: false}
50 */
51
52 export default {
53 name: 'UniPopup',
54 components: {
55 uniTransition,
56 },
57 props: {
58 // 开启动画
59 animation: {
60 type: Boolean,
61 default: true,
62 },
63 // 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
64 // message: 消息提示 ; dialog : 对话框
65 type: {
66 type: String,
67 default: 'center',
68 },
69 // maskClick
70 maskClick: {
71 type: Boolean,
72 default: true,
73 },
74 },
75 provide() {
76 return {
77 popup: this,
78 }
79 },
80 mixins: [popup],
81 watch: {
82 /**
83 * 监听type类型
84 */
85 type: {
86 handler: function(newVal) {
87 this[this.config[newVal]]()
88 },
89 immediate: true,
90 },
91 /**
92 * 监听遮罩是否可点击
93 * @param {Object} val
94 */
95 maskClick(val) {
96 this.mkclick = val
97 },
98 },
99 data() {
100 return {
101 duration: 300,
102 ani: [],
103 showPopup: false,
104 showTrans: false,
105 maskClass: {
106 position: 'fixed',
107 bottom: 0,
108 top: 0,
109 left: 0,
110 right: 0,
111 backgroundColor: 'rgba(0, 0, 0, 0.4)',
112 },
113 transClass: {
114 position: 'fixed',
115 left: 0,
116 right: 0,
117 },
118 maskShow: true,
119 mkclick: true,
120 popupstyle: 'top',
121 }
122 },
123 created() {
124 this.mkclick = this.maskClick
125 if (this.animation) {
126 this.duration = 300
127 } else {
128 this.duration = 0
129 }
130 },
131 methods: {
132 clear(e) {
133 // TODO nvue 取消冒泡
134 e.stopPropagation()
135 },
136 open() {
137 this.showPopup = true
138 this.$nextTick(() => {
139 new Promise(resolve => {
140 clearTimeout(this.timer)
141 this.timer = setTimeout(() => {
142 this.showTrans = true
143 // fixed by mehaotian 兼容 app 端
144 this.$nextTick(() => {
145 resolve()
146 })
147 }, 50)
148 }).then(res => {
149 // 自定义打开事件
150 clearTimeout(this.msgtimer)
151 this.msgtimer = setTimeout(() => {
152 this.customOpen && this.customOpen()
153 }, 100)
154 this.$emit('change', {
155 show: true,
156 type: this.type,
157 })
158 })
159 })
160 },
161 close(type) {
162 this.showTrans = false
163 this.$nextTick(() => {
164 this.$emit('change', {
165 show: false,
166 type: this.type,
167 })
168 clearTimeout(this.timer)
169 // 自定义关闭事件
170 this.customOpen && this.customClose()
171 this.timer = setTimeout(() => {
172 this.showPopup = false
173 }, 300)
174 })
175 },
176 onTap() {
177 if (!this.mkclick) return
178 this.close()
179 },
180 /**
181 * 顶部弹出样式处理
182 */
183 top() {
184 this.popupstyle = 'top'
185 this.ani = ['slide-top']
186 this.transClass = {
187 position: 'fixed',
188 left: 0,
189 right: 0,
190 }
191 },
192 /**
193 * 底部弹出样式处理
194 */
195 bottom() {
196 this.popupstyle = 'bottom'
197 this.ani = ['slide-bottom']
198 this.transClass = {
199 position: 'fixed',
200 left: 0,
201 right: 0,
202 bottom: 0,
203 }
204 },
205 /**
206 * 中间弹出样式处理
207 */
208 center() {
209 this.popupstyle = 'center'
210 this.ani = ['zoom-out', 'fade']
211 this.transClass = {
212 position: 'fixed',
213 /* #ifndef APP-NVUE */
214 display: 'flex',
215 flexDirection: 'column',
216 /* #endif */
217 bottom: 0,
218 left: 0,
219 right: 0,
220 top: 0,
221 justifyContent: 'center',
222 alignItems: 'center',
223 }
224 },
225 },
226 }
227 </script>
228 <style lang="scss" scoped>
229 .uni-popup {
230 position: fixed;
231 /* #ifndef APP-NVUE */
232 z-index: 99;
233 /* #endif */
234 }
235
236 .uni-popup__mask {
237 position: absolute;
238 top: 0;
239 bottom: 0;
240 left: 0;
241 right: 0;
242 background-color: $uni-bg-color-mask;
243 opacity: 0;
244 }
245
246 .mask-ani {
247 transition-property: opacity;
248 transition-duration: 0.2s;
249 }
250
251 .uni-top-mask {
252 opacity: 1;
253 }
254
255 .uni-bottom-mask {
256 opacity: 1;
257 }
258
259 .uni-center-mask {
260 opacity: 1;
261 }
262
263 .uni-popup__wrapper {
264 /* #ifndef APP-NVUE */
265 display: block;
266 /* #endif */
267 position: absolute;
268 }
269
270 .top {
271 /* #ifdef H5 */
272 top: var(--window-top);
273 /* #endif */
274 /* #ifndef H5 */
275 top: 0;
276 /* #endif */
277 }
278
279 .bottom {
280 bottom: 0;
281 }
282
283 .uni-popup__wrapper-box {
284 /* #ifndef APP-NVUE */
285 display: block;
286 /* #endif */
287 position: relative;
288 /* iphonex 等安全区设置,底部安全区适配 */
289 /* #ifndef APP-NVUE */
290 padding-bottom: constant(safe-area-inset-bottom);
291 padding-bottom: env(safe-area-inset-bottom);
292 /* #endif */
293 }
294
295 .content-ani {
296 // transition: transform 0.3s;
297 transition-property: transform, opacity;
298 transition-duration: 0.2s;
299 }
300
301 .uni-top-content {
302 transform: translateY(0);
303 }
304
305 .uni-bottom-content {
306 transform: translateY(0);
307 }
308
309 .uni-center-content {
310 transform: scale(1);
311 opacity: 1;
312 }
313 </style>
314
src/pages/details/components/Introduce.vue
1 <template> 1 <template>
2 <view class="introduce"> 2 <view class="introduce">
3 <!-- 迭代时建议配合接口修改 为数组 --> 3 <!-- 迭代时建议配合接口修改 为数组 -->
4 <view v-if="tag.prod_tag_age && tag.prod_tag_age.length !== 0"> 4 <view v-if="tag.prod_tag_age && tag.prod_tag_age.length !== 0">
5 <view> 5 <view>
6 年龄:<view 6 年龄:<view
7 v-for="(item,index) in tag.prod_tag_age" 7 v-for="(item,index) in tag.prod_tag_age"
8 :key="index" 8 :key="index"
9 > 9 >
10 {{item.label}}<text v-if="index !== tag.prod_tag_age.length - 1">/</text> 10 {{item.label}}<text v-if="index !== tag.prod_tag_age.length - 1">/</text>
11 </view> 11 </view>
12 </view> 12 </view>
13 </view> 13 </view>
14 <view v-if="tag.prod_tag_color && tag.prod_tag_color.length !== 0"> 14 <view v-if="tag.prod_tag_color && tag.prod_tag_color.length !== 0">
15 <view> 15 <view>
16 颜色:<view 16 颜色:<view
17 v-for="(item,index) in tag.prod_tag_color" 17 v-for="(item,index) in tag.prod_tag_color"
18 :key="index" 18 :key="index"
19 > 19 >
20 {{item.label}}<text v-if="index !== tag.prod_tag_color.length - 1">/</text> 20 {{item.label}}<text v-if="index !== tag.prod_tag_color.length - 1">/</text>
21 </view> 21 </view>
22 </view> 22 </view>
23 </view> 23 </view>
24 <view v-if="tag.prod_tag_face && tag.prod_tag_face.length !== 0"> 24 <view v-if="tag.prod_tag_face && tag.prod_tag_face.length !== 0">
25 <view> 25 <view>
26 脸型:<view 26 脸型:<view
27 v-for="(item,index) in tag.prod_tag_face" 27 v-for="(item,index) in tag.prod_tag_face"
28 :key="index" 28 :key="index"
29 > 29 >
30 {{item.label}}<text v-if="index !== tag.prod_tag_face.length - 1">/</text> 30 {{item.label}}<text v-if="index !== tag.prod_tag_face.length - 1">/</text>
31 </view> 31 </view>
32 </view> 32 </view>
33 </view> 33 </view>
34 <view v-if="tag.prod_tag_freesend && tag.prod_tag_freesend.length !== 0"> 34 <view v-if="tag.prod_tag_freesend && tag.prod_tag_freesend.length !== 0">
35 <view> 35 <view>
36 赠品:<view 36 赠品:<view
37 v-for="(item,index) in tag.prod_tag_freesend" 37 v-for="(item,index) in tag.prod_tag_freesend"
38 :key="index" 38 :key="index"
39 > 39 >
40 {{item.label}}<text v-if="index !== tag.prod_tag_freesend.length - 1">/</text> 40 {{item.label}}<text v-if="index !== tag.prod_tag_freesend.length - 1">/</text>
41 </view> 41 </view>
42 </view> 42 </view>
43 </view> 43 </view>
44 <view v-if="tag.prod_tag_insurance && tag.prod_tag_insurance.length !== 0"> 44 <view v-if="tag.prod_tag_insurance && tag.prod_tag_insurance.length !== 0">
45 <view> 45 <view>
46 保险:<view 46 保险:<view
47 v-for="(item,index) in tag.prod_tag_insurance" 47 v-for="(item,index) in tag.prod_tag_insurance"
48 :key="index" 48 :key="index"
49 > 49 >
50 {{item.label}}<text v-if="index !== tag.prod_tag_insurance.length - 1">/</text> 50 {{item.label}}<text v-if="index !== tag.prod_tag_insurance.length - 1">/</text>
51 </view> 51 </view>
52 </view> 52 </view>
53 </view> 53 </view>
54 <view v-if="tag.prod_tag_metal && tag.prod_tag_metal.length !== 0"> 54 <view v-if="tag.prod_tag_metal && tag.prod_tag_metal.length !== 0">
55 <view> 55 <view>
56 材质:<view 56 材质:<view
57 v-for="(item,index) in tag.prod_tag_metal" 57 v-for="(item,index) in tag.prod_tag_metal"
58 :key="index" 58 :key="index"
59 > 59 >
60 {{item.label}}<text v-if="index !== tag.prod_tag_metal.length - 1">/</text> 60 {{item.label}}<text v-if="index !== tag.prod_tag_metal.length - 1">/</text>
61 </view> 61 </view>
62 </view> 62 </view>
63 </view> 63 </view>
64 <view v-if="tag.prod_tag_personal && tag.prod_tag_personal.length !== 0"> 64 <view v-if="tag.prod_tag_personal && tag.prod_tag_personal.length !== 0">
65 <view> 65 <view>
66 个性:<view 66 个性:<view
67 v-for="(item,index) in tag.prod_tag_personal" 67 v-for="(item,index) in tag.prod_tag_personal"
68 :key="index" 68 :key="index"
69 > 69 >
70 {{item.label}}<text v-if="index !== tag.prod_tag_personal.length - 1">/</text> 70 {{item.label}}<text v-if="index !== tag.prod_tag_personal.length - 1">/</text>
71 </view> 71 </view>
72 </view> 72 </view>
73 </view> 73 </view>
74 <view v-if="tag.prod_tag_sense && tag.prod_tag_sense.length !== 0"> 74 <view v-if="tag.prod_tag_sense && tag.prod_tag_sense.length !== 0">
75 <view> 75 <view>
76 场景:<view 76 场景:<view
77 v-for="(item,index) in tag.prod_tag_sense" 77 v-for="(item,index) in tag.prod_tag_sense"
78 :key="index" 78 :key="index"
79 > 79 >
80 {{item.label}}<text v-if="index !== tag.prod_tag_sense.length - 1">/</text> 80 {{item.label}}<text v-if="index !== tag.prod_tag_sense.length - 1">/</text>
81 </view> 81 </view>
82 </view> 82 </view>
83 </view> 83 </view>
84 <view v-if="tag.prod_tag_sex && tag.prod_tag_sex.length !== 0"> 84 <view v-if="tag.prod_tag_sex && tag.prod_tag_sex.length !== 0">
85 <view> 85 <view>
86 性别:<view 86 性别:<view
87 v-for="(item,index) in tag.prod_tag_sex" 87 v-for="(item,index) in tag.prod_tag_sex"
88 :key="index" 88 :key="index"
89 > 89 >
90 {{item.label}}<text v-if="index !== tag.prod_tag_sex.length - 1">/</text> 90 {{item.label}}<text v-if="index !== tag.prod_tag_sex.length - 1">/</text>
91 </view> 91 </view>
92 </view> 92 </view>
93 </view> 93 </view>
94 <view v-if="tag.prod_tag_style && tag.prod_tag_style.length !== 0"> 94 <view v-if="tag.prod_tag_style && tag.prod_tag_style.length !== 0">
95 <view> 95 <view>
96 风格:<view 96 风格:<view
97 v-for="(item,index) in tag.prod_tag_style" 97 v-for="(item,index) in tag.prod_tag_style"
98 :key="index" 98 :key="index"
99 > 99 >
100 {{item.label}}<text v-if="index !== tag.prod_tag_style.length - 1">/</text> 100 {{item.label}}<text v-if="index !== tag.prod_tag_style.length - 1">/</text>
101 </view> 101 </view>
102 </view> 102 </view>
103 </view> 103 </view>
104 <view v-if="tag.prod_tag_weight && tag.prod_tag_weight.length !== 0"> 104 <view v-if="tag.prod_tag_weight && tag.prod_tag_weight.length !== 0">
105 <view> 105 <view>
106 重量:<view 106 重量:<view
107 v-for="(item,index) in tag.prod_tag_weight" 107 v-for="(item,index) in tag.prod_tag_weight"
108 :key="index" 108 :key="index"
109 > 109 >
110 {{item.label}}<text v-if="index !== tag.prod_tag_weight.length - 1">/</text> 110 {{item.label}}<text v-if="index !== tag.prod_tag_weight.length - 1">/</text>
111 </view> 111 </view>
112 </view> 112 </view>
113 </view> 113 </view>
114 </view> 114 </view>
115 </template> 115 </template>
116 116
117 <script> 117 <script>
118 export default { 118 export default {
119 props: { 119 props: {
120 tag: Object, 120 tag: Object,
121 }, 121 },
122 created() { 122 created() {
123 console.log('lalal')
124 console.log('tag', this)
125 }, 123 },
126 updated() { 124 updated() {
127 console.log('lalal-2')
128 console.log('tag-2', this.tag)
129 }, 125 },
130 } 126 }
131 </script> 127 </script>
132 128
133 <style lang="scss" scoped> 129 <style lang="scss" scoped>
134 .introduce { 130 .introduce {
135 margin-bottom: 4px; 131 margin-bottom: 4px;
136 view { 132 view {
137 display: flex; 133 display: flex;
138 align-content: center; 134 align-content: center;
139 font-size: 14px; 135 font-size: 14px;
140 color: #333333; 136 color: #333333;
141 } 137 }
142 span { 138 span {
143 margin-left: 6px; 139 margin-left: 6px;
144 margin-right: 5px; 140 margin-right: 5px;
145 font-family: "PingFangSC-Regular"; 141 font-family: "PingFangSC-Regular";
146 } 142 }
147 } 143 }
148 </style> 144 </style>
149 145
src/pages/details/details.vue
1 <template> 1 <template>
2 <view class="container"> 2 <view class="container">
3 <!-- 基础信息 --> 3 <!-- 基础信息 -->
4 <view class="basic_info"> 4 <view class="basic_info">
5 <!-- 轮播图 --> 5 <!-- 轮播图 -->
6 <swiper 6 <swiper
7 class="swiperImage" 7 class="swiperImage"
8 :indicator-dots="true" 8 :indicator-dots="true"
9 :autoplay="true" 9 :autoplay="true"
10 :interval="4000" 10 :interval="4000"
11 :duration="500" 11 :duration="500"
12 > 12 >
13 <swiper-item 13 <swiper-item
14 v-for="(item, index) in carousel" 14 v-for="(item, index) in carousel"
15 :key="index" 15 :key="index"
16 > 16 >
17 <image 17 <image
18 :src="item" 18 :src="item"
19 mode="scaleToFill" 19 mode="scaleToFill"
20 ></image> 20 ></image>
21 </swiper-item> 21 </swiper-item>
22 </swiper> 22 </swiper>
23 <!-- 产品价格及购买人数 --> 23 <!-- 产品价格及购买人数 -->
24 <view class="info_pay"> 24 <view class="info_pay">
25 <view>¥{{goodsInfo.price || '暂无'}}<span 25 <view>¥{{goodsInfo.price || '暂无'}}<span
26 v-if="goodsInfo.discountPrice" 26 v-if="goodsInfo.discountPrice"
27 class="info_pay_discount" 27 class="info_pay_discount"
28 >¥{{goodsInfo.discountPrice}}</span></view> 28 >¥{{goodsInfo.discountPrice}}</span></view>
29 <span class="info_pay_number">{{goodsInfo.tradeNumber || '暂无'}}人购买过</span> 29 <span class="info_pay_number">{{goodsInfo.tradeNumber || '暂无'}}人购买过</span>
30 </view> 30 </view>
31 <!-- 产品名称 --> 31 <!-- 产品名称 -->
32 <view class="info_name"> 32 <view class="info_name">
33 <text class="info_name_name">{{goodsInfo.name || '暂无'}}</text> 33 <text class="info_name_name">{{goodsInfo.name || '暂无'}}</text>
34 <view class="info_name_share"> 34 <view
35 @tap="confirmShare"
36 class="info_name_share"
37 >
35 <image src="/static/img/detail/share-icon.png"></image> 38 <image src="/static/img/detail/share-icon.png"></image>
36 <text>分享</text> 39 <text>分享</text>
37 </view> 40 </view>
38 </view> 41 </view>
39 <!-- 产品售后信息 --> 42 <!-- 产品售后信息 -->
40 <view class="info_after"> 43 <view class="info_after">
41 <span>支持7天无理由退货</span> 44 <span>支持7天无理由退货</span>
42 <span>顺丰发货</span> 45 <span>顺丰发货</span>
43 <span>30天质量保证</span> 46 <span>30天质量保证</span>
44 </view> 47 </view>
45 </view> 48 </view>
46 <!-- 详细信息 --> 49 <!-- 详细信息 -->
47 <view class="detail_info"> 50 <view class="detail_info">
48 <!-- 详细信息菜单 --> 51 <!-- 详细信息菜单 -->
49 <view class="screen_bar"> 52 <view class="screen_bar">
50 <view 53 <view
51 v-for="(item, index) in screenItems" 54 v-for="(item, index) in screenItems"
52 :key="index" 55 :key="index"
53 @click="tabChange(index)" 56 @click="tabChange(index)"
54 > 57 >
55 <view 58 <view
56 class="screen_item" 59 class="screen_item"
57 v-bind:class="{ item_active: item_current === index }" 60 v-bind:class="{ item_active: item_current === index }"
58 >{{ screenItems[index] || '暂无' }}</view> 61 >{{ screenItems[index] || '暂无' }}</view>
59 </view> 62 </view>
60 </view> 63 </view>
61 <!-- 商品介绍 --> 64 <!-- 商品介绍 -->
62 <view 65 <view
63 class="screen_item" 66 class="screen_item"
64 v-if="item_current === 0" 67 v-if="item_current === 0"
65 > 68 >
66 <Introduce :tag="tag" /> 69 <Introduce :tag="tag" />
67 </view> 70 </view>
68 <!-- 规格参数 --> 71 <!-- 规格参数 -->
69 <view 72 <view
70 class="screen_item" 73 class="screen_item"
71 v-if="item_current === 1" 74 v-if="item_current === 1"
72 > 75 >
73 <view class="specification"> 76 <view class="specification">
74 <view 77 <view
75 class="spe_item" 78 class="spe_item"
76 v-for="(item, index) in specification" 79 v-for="(item, index) in specification"
77 :key="index" 80 :key="index"
78 > 81 >
79 <image 82 <image
80 class="spe_image" 83 class="spe_image"
81 v-bind:src="item.img" 84 v-bind:src="item.img"
82 ></image> 85 ></image>
83 <span>{{item.standard || '暂无'}}</span> 86 <span>{{item.standard || '暂无'}}</span>
84 <span>{{item.slength || '暂无'}}</span> 87 <span>{{item.slength || '暂无'}}</span>
85 </view> 88 </view>
86 </view> 89 </view>
87 </view> 90 </view>
88 <!-- 售后保障 --> 91 <!-- 售后保障 -->
89 <view 92 <view
90 class="screen_item" 93 class="screen_item"
91 v-if="item_current === 2" 94 v-if="item_current === 2"
92 > 95 >
93 <AfterSails /> 96 <AfterSails />
94 </view> 97 </view>
95 </view> 98 </view>
96 <!-- 评价 --> 99 <!-- 评价 -->
97 <template v-if="item_current !== 2"> 100 <template v-if="item_current !== 2">
98 <view class="evaluate"> 101 <view class="evaluate">
99 <!-- 标题 --> 102 <!-- 标题 -->
100 <view class="evaluate_title"> 103 <view class="evaluate_title">
101 <view><span>宝贝好评率</span><span class="title_rate">{{evaluate.rate}}</span></view> 104 <view><span>宝贝好评率</span><span class="title_rate">{{evaluate.rate}}</span></view>
102 <!-- 星星 --> 105 <!-- 星星 -->
103 <view class="evaluate_star"> 106 <view class="evaluate_star">
104 <view 107 <view
105 class="star" 108 class="star"
106 v-for="(item, index) in evaluate.star" 109 v-for="(item, index) in evaluate.star"
107 :key="index" 110 :key="index"
108 > 111 >
109 <image 112 <image
110 src="../../static/img/detail/d_star.png" 113 src="../../static/img/detail/d_star.png"
111 mode="aspectFill" 114 mode="aspectFill"
112 style="height: 26rpx; width: 28rpx;" 115 style="height: 26rpx; width: 28rpx;"
113 ></image> 116 ></image>
114 </view> 117 </view>
115 </view> 118 </view>
116 </view> 119 </view>
117 <!-- 标签 --> 120 <!-- 标签 -->
118 <view class="evaluate_tag"> 121 <view class="evaluate_tag">
119 <view 122 <view
120 v-for="(item, index) in evaluate.tag" 123 v-for="(item, index) in evaluate.tag"
121 :key="index" 124 :key="index"
122 >{{item.name}}</view> 125 >{{item.name}}</view>
123 </view> 126 </view>
124 </view> 127 </view>
125 </template> 128 </template>
126 <!-- 商品详情页 --> 129 <!-- 商品详情页 -->
127 <template v-if="current !==2"> 130 <template v-if="current !==2">
128 <view class="more_info"> 131 <view class="more_info">
129 <view 132 <view
130 class="more_fixed1" 133 class="more_fixed1"
131 @click="consolg(goodInfo.prodIntro1)" 134 @click="consolg(goodInfo.prodIntro1)"
132 > 135 >
133 <image src="/static/img/detail/hr.png"></image> 136 <image src="/static/img/detail/hr.png"></image>
134 <view>商品详情</view> 137 <view>商品详情</view>
135 <image src="/static/img/detail/hr.png"></image> 138 <image src="/static/img/detail/hr.png"></image>
136 </view> 139 </view>
137 <view 140 <view
138 class="more_all" 141 class="more_all"
139 v-html="more" 142 v-html="more"
140 > 143 >
141 </view> 144 </view>
142 </view> 145 </view>
143 </template> 146 </template>
144 <!-- 底部菜单 --> 147 <!-- 底部菜单 -->
145 <view class="menu"> 148 <view class="menu">
146 <view 149 <view
147 @tap="toCart()" 150 @tap="toCart()"
148 class="menu_1" 151 class="menu_1"
149 > 152 >
150 <view class="cart_icon"> 153 <view class="cart_icon">
151 <image src="/static/tab-cart.png" /> 154 <image src="/static/tab-cart.png" />
152 <text>{{cartNumber}}</text> 155 <text>{{cartNumber}}</text>
153 </view> 156 </view>
154 <view class="menu_image">购物车</view> 157 <view class="menu_image">购物车</view>
155 </view> 158 </view>
156 <view class="menu_2"> 159 <view class="menu_2">
157 <view 160 <view
158 class="menu_input" 161 class="menu_input"
159 @tap="showBottom(1)" 162 @tap="showBottom(1)"
160 >加入购物车</view> 163 >加入购物车</view>
161 <view 164 <view
162 class="menu_now" 165 class="menu_now"
163 @click="showBottom(2)" 166 @click="showBottom(2)"
164 >立即购买</view> 167 >立即购买</view>
165 </view> 168 </view>
166 </view> 169 </view>
170 <!-- 参数选择 -->
171 <!-- <BottomSheet
172 :isCart="isCart"
173 @addCart="addCart"
174 :pid="pid"
175 :goodInfo="goodInfo"
176 :isShowBottom="isShowBottom"
177 @closeBottom="closeBottom"
178 ></BottomSheet> -->
179 <!-- 分享 -->
180 <template>
181 <uni-popup
182 ref="popupShare"
183 type="share"
184 >
185 <uni-popup-share @select="selectShare"></uni-popup-share>
186 </uni-popup>
187 </template>
188 <!-- 分享海报 -->
189 <template>
190 <uni-popup
191 ref="uniPopupPost"
192 type="center"
193 >
194 <uni-popup-post :postUrl="postUrl"></uni-popup-post>
195 </uni-popup>
196 </template>
167 </view> 197 </view>
168 </template> 198 </template>
169 199
170 <script> 200 <script>
171 import store from '@/store' 201 import store from '@/store'
172 import Introduce from './components/Introduce' // 商品介绍基本信息 202 import Introduce from './components/Introduce' // 商品介绍基本信息组件
173 import AfterSails from './components/AfterSails' // 售后保障组件 203 import AfterSails from './components/AfterSails' // 售后保障组件
174 // import BottomSheet from '@/components/BottomSheet.vue' 204 import uniPopupShare from '@/components/uni-popup/uni-popup-share.vue' // 分享组件
205 import uniPopupPost from '@/components/uni-popup/uni-popup-post.vue' // 分享组件
206 // import BottomSheet from '@/components/BottomSheet/BottomSheet.vue' // 参数选择组件
175 207
176 export default { 208 export default {
177 components: { 209 components: {
178 Introduce, 210 Introduce,
179 AfterSails, 211 AfterSails,
212 // BottomSheet,
213 uniPopupShare,
214 uniPopupPost,
180 }, 215 },
181 data () { 216 data () {
182 return { 217 return {
183 pid: 7, // 产品ID 218 pid: 7, // 产品ID
184 skId: undefined, // skuId 219 skId: undefined, // skuId
185 // 详细信息菜单 220 // 详细信息菜单
186 item_current: 0, 221 item_current: 0,
187 screenItems: [ 222 screenItems: [
188 '商品介绍', 223 '商品介绍',
189 '规格参数', 224 '规格参数',
190 '售后保障', 225 '售后保障',
191 ], 226 ],
227 showPostImg: false, // 是否展示分享海报
192 } 228 }
193 }, 229 },
194 onLoad({ pid = this.pid, sk_id: skId }) { 230 onLoad({ pid = this.pid, sk_id: skId }) {
195 // 根据页面传参请求页面数据 231 // 根据页面传参请求页面数据
196 this.pid = pid 232 this.pid = pid
197 this.skId = skId 233 this.skId = skId
198 234
199 // 获取产品详情 235 // 获取产品详情
200 this.getDetails({ pid, skId }) 236 this.getDetails({ pid, skId })
201 // 获取购物车数据 237 // 获取购物车数据
202 this.getCartNum() 238 this.getCartNum()
203 }, 239 },
204 computed: { 240 computed: {
205 // 获取轮播图数据 241 // 获取轮播图数据
206 carousel() { 242 carousel() {
207 return this.$store.state.details.carousel 243 return this.$store.state.details.carousel
208 }, 244 },
209 // 商品基本信息 245 // 商品基本信息
210 goodsInfo() { 246 goodsInfo() {
211 return this.$store.state.details.goodsInfo 247 return this.$store.state.details.goodsInfo
212 }, 248 },
213 // 商品介绍商品标签 249 // 商品介绍商品标签
214 tag() { 250 tag() {
215 return this.$store.state.details.tag 251 return this.$store.state.details.tag
216 }, 252 },
217 // 规格参数 253 // 规格参数
218 specification() { 254 specification() {
219 return this.$store.state.details.specification 255 return this.$store.state.details.specification
220 }, 256 },
221 // 评价 257 // 评价
222 evaluate() { 258 evaluate() {
223 return this.$store.state.details.evaluate 259 return this.$store.state.details.evaluate
224 }, 260 },
225 // 商品详情 261 // 商品详情
226 more() { 262 more() {
227 return this.$store.state.details.more 263 return this.$store.state.details.more
228 }, 264 },
229 // 购物车数目 265 // 购物车数目
230 cartNumber() { 266 cartNumber() {
231 return this.$store.state.details.cartNumber 267 return this.$store.state.details.cartNumber
232 }, 268 },
269 // 购物车数目
270 skuList() {
271 return this.$store.state.details.skuList
272 },
273 // 分享海报
274 postUrl() {
275 return this.$store.state.details.postUrl
276 },
233 }, 277 },
234 methods: { 278 methods: {
235 // 获取产品详情 279 // 获取产品详情
236 getDetails({ pid, skId }) { 280 getDetails({ pid, skId }) {
237 store.dispatch('details/details', { 281 store.dispatch('details/details', {
238 pid, 282 pid,
239 sk_id: skId, 283 sk_id: skId,
240 }) 284 })
241 }, 285 },
242 // 获取购物车数目 286 // 获取购物车数目
243 getCartNum() { 287 getCartNum() {
244 store.dispatch('details/getCartNumber') 288 store.dispatch('details/getCartNumber')
245 }, 289 },
246 // 切换详细信息菜单 290 // 切换详细信息菜单
247 tabChange (e) { 291 tabChange (e) {
248 if (this.current !== e) { 292 if (this.current !== e) {
249 this.item_current = e 293 this.item_current = e
250 } 294 }
251 }, 295 },
296 // 打开分享界面
297 confirmShare() {
298 this.$refs.popupShare.open()
299 },
300 // 选择分享
301 selectShare(e, done) {
302 switch (e.item.name) {
303 // 分享到好物圈
304 case 'recommend':
305 this.shareRecommend()
306 break
307 // 分享到朋友圈
308 case 'friend':
309 break
310 // 生成海报
311 case 'poster':
312 uni.showLoading({
313 title: '生成图片中',
314 })
315 this.sharePost()
316 break
317 default:
318 break
319 }
320 done()
321 },
322 // 分享到好物圈
323 shareRecommend() {
324 if (wx.openBusinessView) {
325 wx.openBusinessView({
326 businessType: 'friendGoodsRecommend',
327 extraData: {
328 product: {
329 item_code: '58_68',
330 title: this.goodsInfo.name,
331 image_list: this.carousel,
332 },
333 },
334 success: function (res) {
335 uni.showToast({
336 title: '好物圈分享成功!',
337 icon: 'none',
338 duration: 2000,
339 })
340 // 向服务器报告这个事情
341 // TODO:::记录这个用户的推广过程。
342 console.log('好物圈分享成功!', res)
343 },
344 fail: function (res) {
345 console.log('好物圈分享失败!', res)
346 },
347 })
348 }
349 },
350 // 分享到朋友/圈
351 shareFriend() {
352 this.onShareAppMessage()
353 },
354 // 朋友圈设置页面
355 onShareAppMessage() {
356 let myName = this.$store.state.user.userInfo.nickName
357 if (myName === '' || myName.length < 1 || myName === '匿名用户' || typeof myName === 'undefined') {
358 myName = '【神秘人】'
359 } else {
360 myName = '【' + myName + '】'
361 }
362 const uid = uni.getStorageSync('uid')
363 return {
364 title: 'Hi,' + myName + '送你300元来试戴最新潮流眼镜!', // 默认是小程序的名称(可以写slogan等)
365 path: '/pages/index/detail/index?uid=' + uid + '&sid=0&pid=' + this.pid,
366 imageUrl: this.skuList[0].pic, // 不传入 imageUrl 则使用默认截图。显示图片长宽比是 5:4
367 success: function (res) {
368 if (res.errMsg === 'shareAppMessage:ok') {
369 console.log('分享成功!', res)
370 }
371 },
372 fail: function (res) {
373 if (res.errMsg === 'shareAppMessage:fail cancel') {
374 console.log('fail', '放弃分享')
375 } else if (res.errMsg === 'shareAppMessage:fail') {
376 console.log('fail', '分享失败')
377 }
378 },
379 }
380 },
381 // 生成海报
382 sharePost() {
383 const fromsid = this.$store.state.user.fromInfo.fromsid || 'undefined'
384
385 store.dispatch('details/post', {
386 pid: this.pid,
387 sid: fromsid === 'undefined' ? 0 : fromsid,
388 }).then((data) => {
389 uni.hideLoading()
390 this.$refs.uniPopupPost.open()
391 })
392 },
252 }, 393 },
253 } 394 }
254 </script> 395 </script>
255 396
256 <style lang="scss"> 397 <style lang="scss">
257 .container { 398 .container {
258 background-color: #f8f8f8; 399 background-color: #f8f8f8;
259 font-family: "PingFangSC-Regular"; 400 font-family: "PingFangSC-Regular";
260 // 板块样式 401 // 板块样式
261 > view { 402 > view {
262 background: #ffffff; 403 background: #ffffff;
263 margin-bottom: 10px; 404 margin-bottom: 10px;
264 padding: 8px 20px 8px 20px; 405 padding: 8px 20px 8px 20px;
265 box-sizing: border-box; 406 box-sizing: border-box;
266 } 407 }
267 // 基础信息板块 408 // 基础信息板块
268 .basic_info { 409 .basic_info {
269 // 轮播图 410 // 轮播图
270 .swiperImage { 411 .swiperImage {
271 width: 684rpx; 412 width: 684rpx;
272 height: 480rpx; 413 height: 480rpx;
273 image { 414 image {
274 max-width: 100%; 415 max-width: 100%;
275 max-height: 100%; 416 max-height: 100%;
276 border-radius: 16rpx; 417 border-radius: 16rpx;
277 } 418 }
278 } 419 }
279 // 产品价格及购买人数 420 // 产品价格及购买人数
280 .info_pay { 421 .info_pay {
281 color: #eb5d3b; 422 color: #eb5d3b;
282 font-size: 18px; 423 font-size: 18px;
283 margin-top: 5px; 424 margin-top: 5px;
284 font-family: "PingFangSC-Semibold"; 425 font-family: "PingFangSC-Semibold";
285 display: flex; 426 display: flex;
286 justify-content: space-between; 427 justify-content: space-between;
287 .info_pay_discount { 428 .info_pay_discount {
288 text-decoration: line-through; 429 text-decoration: line-through;
289 margin-left: 8rpx; 430 margin-left: 8rpx;
290 color: #999; 431 color: #999;
291 font-size: 14px; 432 font-size: 14px;
292 } 433 }
293 .info_pay_number { 434 .info_pay_number {
294 color: #999; 435 color: #999;
295 font-size: 14px; 436 font-size: 14px;
437 font-family: PingFangSC-Regular;
296 } 438 }
297 } 439 }
298 // 产品名称 440 // 产品名称
299 .info_name { 441 .info_name {
300 margin-top: 5px; 442 margin-top: 5px;
301 display: flex; 443 display: flex;
302 justify-content: space-between; 444 justify-content: space-between;
303 .info_name_name { 445 .info_name_name {
304 margin-right: 10px; 446 margin-right: 10px;
305 font-size: 16px; 447 font-size: 16px;
306 font-family: "PingFangSC-Semibold"; 448 font-family: "PingFangSC-Semibold";
307 max-width: 592rpx; 449 max-width: 592rpx;
308 } 450 }
309 .info_name_share { 451 .info_name_share {
310 display: flex; 452 display: flex;
311 flex-direction: column; 453 flex-direction: column;
312 justify-content: space-between; 454 justify-content: space-between;
313 align-items: center; 455 align-items: center;
314 margin-top: 14rpx; 456 margin-top: 14rpx;
315 > image { 457 > image {
316 height: 40rpx; 458 height: 40rpx;
317 width: 40rpx; 459 width: 40rpx;
318 } 460 }
319 > text { 461 > text {
320 font-family: PingFangSC-Regular; 462 font-family: PingFangSC-Regular;
321 font-size: 12px; 463 font-size: 12px;
322 color: #999; 464 color: #999;
323 letter-spacing: -0.23px; 465 letter-spacing: -0.23px;
324 } 466 }
325 } 467 }
326 } 468 }
327 // 售后服务 469 // 售后服务
328 .info_after { 470 .info_after {
329 font-size: 10px; 471 font-size: 10px;
330 color: #999; 472 color: #999;
331 margin-top: 20rpx; 473 margin-top: 20rpx;
332 > span { 474 > span {
333 height: 14px; 475 height: 14px;
334 margin-right: 10px; 476 margin-right: 10px;
335 } 477 }
336 } 478 }
337 } 479 }
338 // 详细信息 480 // 详细信息
339 .detail_info { 481 .detail_info {
340 margin-bottom: 20rpx; 482 margin-bottom: 20rpx;
341 .screen_bar { 483 .screen_bar {
342 width: 670rpx; 484 width: 670rpx;
343 margin-top: 20rpx; 485 margin-top: 20rpx;
344 margin-bottom: 24rpx; 486 margin-bottom: 24rpx;
345 display: flex; 487 display: flex;
346 flex-direction: row; 488 flex-direction: row;
347 justify-content: space-between; 489 justify-content: space-between;
348 align-items: center; 490 align-items: center;
349 font-size: 14px; 491 font-size: 14px;
350 color: #333333; 492 color: #333333;
351 transition: all 0.2s; 493 transition: all 0.2s;
352 } 494 }
353 .item_active { 495 .item_active {
354 border-bottom: 4rpx solid #ff6b4a; 496 border-bottom: 4rpx solid #ff6b4a;
355 } 497 }
356 .screen_item { 498 .screen_item {
357 font-size: 32rpx; 499 font-size: 32rpx;
358 color: #333333; 500 color: #333333;
359 display: flex; 501 display: flex;
360 transition: all 0.2s; 502 transition: all 0.2s;
361 // 规格参数 503 // 规格参数
362 .specification { 504 .specification {
363 margin-bottom: 4px; 505 margin-bottom: 4px;
364 .spe_item { 506 .spe_item {
365 image { 507 image {
366 width: 50px; 508 width: 50px;
367 height: 25px; 509 height: 25px;
368 margin-right: 6px; 510 margin-right: 6px;
369 vertical-align: middle; 511 vertical-align: middle;
370 } 512 }
371 span { 513 span {
372 margin-left: 24rpx; 514 margin-left: 24rpx;
373 } 515 }
374 } 516 }
375 } 517 }
376 } 518 }
377 // 519 //
378 } 520 }
379 // 宝贝好评率 521 // 宝贝好评率
380 .evaluate { 522 .evaluate {
381 .evaluate_title { 523 .evaluate_title {
382 font-size: 14px; 524 font-size: 14px;
383 color: #333333; 525 color: #333333;
384 display: flex; 526 display: flex;
385 justify-content: space-between; 527 justify-content: space-between;
386 .title_rate { 528 .title_rate {
387 margin-left: 10rpx; 529 margin-left: 10rpx;
388 } 530 }
389 .evaluate_star { 531 .evaluate_star {
390 width: 90px; 532 width: 90px;
391 display: flex; 533 display: flex;
392 align-items: center; 534 align-items: center;
393 justify-content: space-between; 535 justify-content: space-between;
394 } 536 }
395 view { 537 view {
396 font-size: 14px; 538 font-size: 14px;
397 color: #333333; 539 color: #333333;
398 font-weight: bold; 540 font-weight: bold;
399 } 541 }
400 } 542 }
401 .evaluate_tag { 543 .evaluate_tag {
402 view { 544 view {
403 display: inline-block; 545 display: inline-block;
404 margin-right: 20rpx; 546 margin-right: 20rpx;
405 min-width: 180rpx; 547 min-width: 180rpx;
406 margin-top: 10px; 548 margin-top: 10px;
407 height: 48rpx; 549 height: 48rpx;
408 background: #f2f2f2; 550 background: #f2f2f2;
409 border-radius: 2px; 551 border-radius: 2px;
410 font-family: PingFangSC-Regular; 552 font-family: PingFangSC-Regular;
411 font-size: 12px; 553 font-size: 12px;
412 color: #666666; 554 color: #666666;
413 letter-spacing: -0.23px; 555 letter-spacing: -0.23px;
414 text-align: center; 556 text-align: center;
415 padding: 0 48rpx; 557 padding: 0 48rpx;
416 line-height: 48rpx; 558 line-height: 48rpx;
417 } 559 }
418 } 560 }
419 } 561 }
420 // 商品详情 562 // 商品详情
421 .more_info { 563 .more_info {
422 .more_fixed1 { 564 .more_fixed1 {
423 display: flex; 565 display: flex;
424 justify-content: space-between; 566 justify-content: space-between;
425 align-content: center; 567 align-content: center;
426 margin-bottom: 12px; 568 margin-bottom: 12px;
427 view { 569 view {
428 font-size: 14px; 570 font-size: 14px;
429 color: #333333; 571 color: #333333;
430 font-weight: bold; 572 font-weight: bold;
431 font-family: "PingFangSC-Medium"; 573 font-family: "PingFangSC-Medium";
432 line-height: 24px; 574 line-height: 24px;
433 } 575 }
434 image { 576 image {
435 width: 240rpx; 577 width: 240rpx;
436 height: 3px; 578 height: 3px;
437 margin-top: 10px; 579 margin-top: 10px;
438 } 580 }
439 } 581 }
440 .more_all { 582 .more_all {
441 width: 100%; 583 width: 100%;
442 margin-top: 30rpx; 584 margin-top: 30rpx;
443 margin-right: 30rpx; 585 margin-right: 30rpx;
444 margin-bottom: 180rpx; 586 margin-bottom: 180rpx;
445 font-family: "PingFangSC-Regular"; 587 font-family: "PingFangSC-Regular";
446 } 588 }
447 } 589 }
448 // 菜单 590 // 菜单
449 .menu { 591 .menu {
450 position: fixed; 592 position: fixed;
451 bottom: 0; 593 bottom: 0;
452 height: 74px; 594 height: 74px;
453 width: 100%; 595 width: 100%;
454 background: #ffffff; 596 background: #ffffff;
455 padding: 20px 20px 8px 20px; 597 padding: 20px 20px 8px 20px;
456 font-family: "PingFangSC-Regular"; 598 font-family: "PingFangSC-Regular";
457 box-sizing: border-box; 599 box-sizing: border-box;
458 display: flex; 600 display: flex;
459 justify-content: space-between; 601 justify-content: space-between;
460 align-content: center; 602 align-content: center;
461 margin: 0; 603 margin: 0;
604 /* iphonex 等安全区设置,底部安全区适配 */
605 /* #ifndef APP-NVUE */
606 padding-bottom: constant(safe-area-inset-bottom);
607 padding-bottom: env(safe-area-inset-bottom);
462 .menu_1 { 608 .menu_1 {
463 width: 20%; 609 width: 20%;
464 height: 100%; 610 height: 100%;
465 text-align: center; 611 text-align: center;
466 color: #989898; 612 color: #989898;
467 .cart_icon { 613 .cart_icon {
468 position: relative; 614 position: relative;
469 text { 615 text {
470 position: absolute; 616 position: absolute;
471 color: white; 617 color: white;
472 font-size: 17px; 618 font-size: 17px;
473 background-color: red; 619 background-color: red;
474 min-height: 24px; 620 min-height: 24px;
475 min-width: 24px; 621 min-width: 24px;
476 line-height: 24px; 622 line-height: 24px;
477 right: -12%; 623 right: -12%;
478 top: -12px; 624 top: -12px;
479 text-align: center; 625 text-align: center;
480 border-radius: 24px; 626 border-radius: 24px;
481 padding: 2px; 627 padding: 2px;
482 } 628 }
483 } 629 }
484 } 630 }
485 image { 631 image {
486 width: 42%; 632 width: 42%;
487 height: 26px; 633 height: 26px;
488 } 634 }
489 .menu_image { 635 .menu_image {
490 font-size: 12px; 636 font-size: 12px;
491 text-align: center; 637 text-align: center;
492 } 638 }
493 .menu_2 { 639 .menu_2 {
494 width: 74%; 640 width: 74%;
495 height: 86%; 641 height: 86%;
496 display: grid; 642 display: grid;
497 grid-template-columns: 50% 50%; 643 grid-template-columns: 50% 50%;
498 } 644 }
499 .menu_input { 645 .menu_input {
500 display: inline-flex; 646 display: inline-flex;
501 align-items: center; 647 align-items: center;
502 justify-content: space-around; 648 justify-content: space-around;
503 background: #fff0ec; 649 background: #fff0ec;
504 font-size: 16px; 650 font-size: 16px;
505 color: #ff6b4a; 651 color: #ff6b4a;
506 border-radius: 20px 0 0 20px; 652 border-radius: 20px 0 0 20px;
507 } 653 }
508 .menu_now { 654 .menu_now {
509 display: inline-flex; 655 display: inline-flex;
510 align-items: center; 656 align-items: center;
511 justify-content: space-around; 657 justify-content: space-around;
512 background: #ff6b4a; 658 background: #ff6b4a;
513 font-size: 16px; 659 font-size: 16px;
514 color: #ffffff; 660 color: #ffffff;
515 border-radius: 0 20px 20px 0; 661 border-radius: 0 20px 20px 0;
516 } 662 }
517 } 663 }
518 } 664 }
519 </style> 665 </style>
520 666
src/static/img/share/friend.png

6.4 KB

src/static/img/share/poster.png

6.92 KB

src/static/img/share/recommend.png

7.38 KB

src/store/modules/details.js
1 import urlAlias from '../url' 1 import urlAlias from '../url'
2 import request from '../request' 2 import request from '../request'
3 3
4 const { 4 const {
5 read, 5 read,
6 cartList, 6 cartList,
7 makePost,
7 } = urlAlias 8 } = urlAlias
8 9
9 const state = { 10 const state = {
10 // 轮播图 11 // 轮播图
11 carousel: [ 12 carousel: [
12 '/static/img/detail/d9.png', 13 '/static/img/detail/d9.png',
13 ], 14 ],
14 // 商品基本信息 15 // 商品基本信息
15 goodsInfo: { 16 goodsInfo: {
16 name: '暂无名称', 17 name: '暂无名称',
17 price: '暂无价格', 18 price: '暂无价格',
18 discountPrice: undefined, 19 discountPrice: undefined,
19 tradeNumber: undefined, 20 tradeNumber: undefined,
20 }, 21 },
21 // 商品介绍 22 // 商品介绍
22 tag: { 23 tag: {
23 prod_tag_style: [{ 24 prod_tag_style: [{
24 label: '青春学子风', 25 label: '青春学子风',
25 value: '54', 26 value: '54',
26 }], 27 }],
27 }, 28 },
28 // 规格参数 29 // 规格参数
29 specification: [ 30 specification: [
30 { key: 'frame_width', img: '/static/img/detail/d2.png', standard: '框架宽', slength: '139mm' }, 31 { key: 'frame_width', img: '/static/img/detail/d2.png', standard: '框架宽', slength: '139mm' },
31 { key: 'glass_width', img: '/static/img/detail/d3.png', standard: '镜片宽', slength: '51mm' }, 32 { key: 'glass_width', img: '/static/img/detail/d3.png', standard: '镜片宽', slength: '51mm' },
32 { key: 'glass_height', img: '/static/img/detail/d4.png', standard: '镜片高', slength: '45mm' }, 33 { key: 'glass_height', img: '/static/img/detail/d4.png', standard: '镜片高', slength: '45mm' },
33 { key: 'nose_width', img: '/static/img/detail/d5.png', standard: '鼻架宽', slength: '19mm' }, 34 { key: 'nose_width', img: '/static/img/detail/d5.png', standard: '鼻架宽', slength: '19mm' },
34 { key: 'leg_long', img: '/static/img/detail/d6.png', standard: '框架耳长', slength: '138mm' }, 35 { key: 'leg_long', img: '/static/img/detail/d6.png', standard: '框架耳长', slength: '138mm' },
35 { key: 'weight', img: '/static/img/detail/d7.png', standard: '框架重', slength: '19克(grams)' }, 36 { key: 'weight', img: '/static/img/detail/d7.png', standard: '框架重', slength: '19克(grams)' },
36 ], 37 ],
37 // 评价 38 // 评价
38 evaluate: { 39 evaluate: {
39 rate: '100%', 40 rate: '100%',
40 star: 5, 41 star: 5,
41 tag: [{ name: '价格实惠' }], 42 tag: [{ name: '价格实惠' }],
42 }, 43 },
43 // 商品详情 44 // 商品详情
44 more: '', 45 more: '',
45 // 购物车数目 46 // 购物车数目
46 cartNumber: 0, 47 cartNumber: 0,
48 // skuList
49 skuList: [],
50 postUrl: 'https://api.glass.xiuyetang.com/adv_pic/428_0_7.png',
47 } 51 }
48 52
49 const mutations = { 53 const mutations = {
50 INIT: (state, { carousel, goodsInfo, tag, specification, evaluate, more }) => { 54 INIT: (state, { carousel, goodsInfo, tag, specification, evaluate, more, skuList }) => {
51 state.carousel = carousel 55 state.carousel = carousel
52 state.goodsInfo = goodsInfo 56 state.goodsInfo = goodsInfo
53 state.tag = tag 57 state.tag = tag
54 state.specification = specification 58 state.specification = specification
55 state.evaluate = evaluate 59 state.evaluate = evaluate
56 state.more = more 60 state.more = more
61 state.skuList = skuList
57 }, 62 },
58 CART: (state, number) => { 63 CART: (state, number) => {
59 state.cartNumber = number 64 state.cartNumber = number
60 }, 65 },
66 POST: (state, url) => {
67 state.postUrl = url
68 },
61 } 69 }
62 70
63 const actions = { 71 const actions = {
64 // 获取详情 72 // 获取详情
65 details({ commit, rootState }, param) { 73 details({ commit, rootState }, param) {
66 return new Promise((resolve, reject) => request({ 74 return new Promise((resolve, reject) => request({
67 url: read, 75 url: read,
68 data: param, 76 data: param,
69 success: ({ data: { data } }) => { 77 success: ({ data: { data } }) => {
70 console.log('data.tag', data.tag) 78 console.log('data.tag', data.tag)
71 // 规格参数设置 79 // 规格参数设置
72 const specification = rootState.details.specification 80 const specification = rootState.details.specification
73 const parameter = { 81 const parameter = {
74 frame_width: data.frame_width, 82 frame_width: data.frame_width,
75 glass_width: data.glass_width, 83 glass_width: data.glass_width,
76 glass_height: data.glass_height, 84 glass_height: data.glass_height,
77 nose_width: data.nose_width, 85 nose_width: data.nose_width,
78 leg_long: data.leg_long, 86 leg_long: data.leg_long,
79 weight: data.weight, 87 weight: data.weight,
80 } 88 }
81 for (let index = 0; index < specification.length; index++) { 89 for (let index = 0; index < specification.length; index++) {
82 if (specification[index].key !== 'weight') { 90 if (specification[index].key !== 'weight') {
83 specification[index].slength = `${parameter[specification[index].key]}mm` 91 specification[index].slength = `${parameter[specification[index].key]}mm`
84 } else { 92 } else {
85 specification[index].slength = `${parameter[specification[index].key]}克(grams)` 93 specification[index].slength = `${parameter[specification[index].key]}克(grams)`
86 } 94 }
87 } 95 }
88 96
89 commit('INIT', { 97 commit('INIT', {
98 skuList: data.skuList,
90 carousel: data.pics, 99 carousel: data.pics,
91 goodsInfo: { 100 goodsInfo: {
92 name: data.p_name, 101 name: data.p_name,
93 price: data.priceArea.Min_Price, 102 price: data.priceArea.Min_Price,
94 discountPrice: data.priceArea.Min_Price - Number(data.priceArea.discount), 103 discountPrice: data.priceArea.Min_Price - Number(data.priceArea.discount),
95 tradeNumber: data.trade_num, 104 tradeNumber: data.trade_num,
96 }, 105 },
97 tag: data.tag, 106 tag: data.tag,
98 specification, 107 specification,
99 evaluate: { 108 evaluate: {
100 rate: data.judgeInfo.good, 109 rate: data.judgeInfo.good,
101 tag: data.judge_tag, 110 tag: data.judge_tag,
102 star: parseInt(5 * Number(data.judgeInfo.good.slice(0, -1)) / 100), 111 star: parseInt(5 * Number(data.judgeInfo.good.slice(0, -1)) / 100),
103 }, 112 },
113 // eslint-disable-next-line
104 more: data.prodIntro1.replace(/\<img/gi, '<img style="max-width:100%;height:auto"'), 114 more: data.prodIntro1.replace(/\<img/gi, '<img style="max-width:100%;height:auto"'),
105 }) 115 })
106 resolve(data) 116 resolve(data)
107 }, 117 },
108 fail: (res) => { 118 fail: (res) => {
109 console.log('fail status ===>', res) 119 console.log('fail status ===>', res)
110 }, 120 },
111 })) 121 }))
112 }, 122 },
113 // 获取购物车列表 123 // 获取购物车列表
114 getCartNumber({ commit }, param) { 124 getCartNumber({ commit }, param) {
115 return new Promise((resolve) => request({ 125 return new Promise((resolve) => request({
116 url: cartList, 126 url: cartList,
117 data: param, 127 data: param,
118 success: ({ data: { data } }) => { 128 success: ({ data: { data } }) => {
119 console.log('cartData', data)
120 let number = 0 129 let number = 0
121 for (let index = 0; index < data.length; index++) { 130 for (let index = 0; index < data.length; index++) {
122 number += Number(data[index].num) 131 number += Number(data[index].num)
123 } 132 }
124 commit('CART', number) 133 commit('CART', number)
125 }, 134 },
126 })) 135 }))
127 }, 136 },
137 // 生成分享海报
138 post({ commit }, param) {
139 return new Promise((resolve) => request({
140 url: makePost,
141 data: param,
142 success: ({ data }) => {
143 commit('POST', data.data)
144 resolve()
145 },
146 }))
147 },
128 } 148 }
129 149
130 export default { 150 export default {
131 namespaced: true, 151 namespaced: true,
132 state, 152 state,
133 mutations, 153 mutations,
134 actions, 154 actions,
135 } 155 }
1 const urlAlias = { 1 const urlAlias = {
2 // 详情 2 // 详情
3 read: '/app/prod/read', // 获取商品信息 3 read: '/app/prod/read', // 获取商品信息
4 4
5 // 首页 5 // 首页
6 shopList: '/app/prod/list', // 获取首页商品列表 6 shopList: '/app/prod/list', // 获取首页商品列表
7 category: '/app/prod/category2', // 获取首页商品分类 7 category: '/app/prod/category2', // 获取首页商品分类
8 search: '/app/prod/search', // 首页搜索商品 8 search: '/app/prod/search', // 首页搜索商品
9 9
10 // 登陆 10 // 登陆
11 login: '/app/glass/getOpenId', // 登陆 11 login: '/app/glass/getOpenId', // 登陆
12 getUserInfo: '/app/glass/userinfo', // 获取用户信息 12 getUserInfo: '/app/glass/userinfo', // 获取用户信息
13 13
14 // 我的订单 14 // 我的订单
15 orderList: '/app/order/list', // 获取订单列表 15 orderList: '/app/order/list', // 获取订单列表
16 myOrderList: '/app/order/list3', // 获取订单列表 16 myOrderList: '/app/order/list3', // 获取订单列表
17 orderRead: '/app/order/read', // 获取订单详情 17 orderRead: '/app/order/read', // 获取订单详情
18 cancelOrder: '/app/order/wait/del', // 取消订单 18 cancelOrder: '/app/order/wait/del', // 取消订单
19 statusConfirm: '/app/order/statusConfirm', // 订单操作 19 statusConfirm: '/app/order/statusConfirm', // 订单操作
20 payLog: '/app/pay/log', // 调起支付 20 payLog: '/app/pay/log', // 调起支付
21 orderBuild: '/app/order/build', // 加购后生成订单 21 orderBuild: '/app/order/build', // 加购后生成订单
22 buyNow: '/app/order/buynow', // 立即购买生成订单 22 buyNow: '/app/order/buynow', // 立即购买生成订单
23 pay: '/app/pay/log', // 支付接口 23 pay: '/app/pay/log', // 支付接口
24 24
25 // 购物车 25 // 购物车
26 cartList: '/app/cart/list', // 获取购物车列表 26 cartList: '/app/cart/list', // 获取购物车列表
27 cartModi: '/app/cart/modi', // 修改购物车 27 cartModi: '/app/cart/modi', // 修改购物车
28 cartDel: '/app/cart/del', // 删除购物车 28 cartDel: '/app/cart/del', // 删除购物车
29 cartAdd: '/app/cart/add', // 添加购物车 29 cartAdd: '/app/cart/add', // 添加购物车
30 30
31 // 我的 31 // 我的
32 recommandList: '/app/prod/recommand', // 获取用户个性化推荐商品 32 recommandList: '/app/prod/recommand', // 获取用户个性化推荐商品
33 33
34 // 镜框选购页 34 // 镜框选购页
35 detailStandardList: '/app/prod/read', // 获取商品的详细信息 35 detailStandardList: '/app/prod/read', // 获取商品的详细信息
36 // 选购页 36 // 选购页
37 detailStandardUrl: '/app/prod/read', // 获取商品的详细信息 37 detailStandardUrl: '/app/prod/read', // 获取商品的详细信息
38 makePost: '/app/glass/makeProdAdvPic', // 生成分享海报
38 39
39 // 地址管理 40 // 地址管理
40 editAddress: '/app/address/edit_address', // 编辑地址 41 editAddress: '/app/address/edit_address', // 编辑地址
41 addressList: '/app/address/get_address_list', // 获取用户地址列表 42 addressList: '/app/address/get_address_list', // 获取用户地址列表
42 getAddress: '/app/address/get_address_by_id', // 获取用户某一地址信息 43 getAddress: '/app/address/get_address_by_id', // 获取用户某一地址信息
43 getDefaultAddress: '/app/address/get_default_address', // 获取用户默认地址信息 44 getDefaultAddress: '/app/address/get_default_address', // 获取用户默认地址信息
44 45
45 // 用户数据 46 // 用户数据
46 mylovelist: '/app/user/mylovelist', // 关心的人的数据 47 mylovelist: '/app/user/mylovelist', // 关心的人的数据
47 myloveadd: '/app/user/myloveadd', // 添加关心的人 48 myloveadd: '/app/user/myloveadd', // 添加关心的人
48 myloveupdate: '/app/user/myloveupdate', // 更新关心人的数据 49 myloveupdate: '/app/user/myloveupdate', // 更新关心人的数据
49 } 50 }
50 51
51 export default urlAlias 52 export default urlAlias
52 53