Commit 5bca13074e51de1cc5a3289df083f0292f22708d
1 parent
fe62536c34
Exists in
master
分享功能
Showing
12 changed files
with
903 additions
and
9 deletions
Show diff stats
.eslintrc.js
src/components/uni-popup/popup.js
... | ... | @@ -0,0 +1,25 @@ |
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 | +} | ... | ... |
src/components/uni-popup/uni-popup-post.vue
... | ... | @@ -0,0 +1,207 @@ |
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> | ... | ... |
src/components/uni-popup/uni-popup-share.vue
... | ... | @@ -0,0 +1,185 @@ |
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> | ... | ... |
src/components/uni-popup/uni-popup.vue
... | ... | @@ -0,0 +1,313 @@ |
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> | ... | ... |
src/pages/details/components/Introduce.vue
src/pages/details/details.vue
... | ... | @@ -31,7 +31,10 @@ |
31 | 31 | <!-- 产品名称 --> |
32 | 32 | <view class="info_name"> |
33 | 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 | 38 | <image src="/static/img/detail/share-icon.png"></image> |
36 | 39 | <text>分享</text> |
37 | 40 | </view> |
... | ... | @@ -164,19 +167,51 @@ |
164 | 167 | >立即购买</view> |
165 | 168 | </view> |
166 | 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 | 197 | </view> |
168 | 198 | </template> |
169 | 199 | |
170 | 200 | <script> |
171 | 201 | import store from '@/store' |
172 | -import Introduce from './components/Introduce' // 商品介绍基本信息 | |
202 | +import Introduce from './components/Introduce' // 商品介绍基本信息组件 | |
173 | 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 | 208 | export default { |
177 | 209 | components: { |
178 | 210 | Introduce, |
179 | 211 | AfterSails, |
212 | + // BottomSheet, | |
213 | + uniPopupShare, | |
214 | + uniPopupPost, | |
180 | 215 | }, |
181 | 216 | data () { |
182 | 217 | return { |
... | ... | @@ -189,6 +224,7 @@ export default { |
189 | 224 | '规格参数', |
190 | 225 | '售后保障', |
191 | 226 | ], |
227 | + showPostImg: false, // 是否展示分享海报 | |
192 | 228 | } |
193 | 229 | }, |
194 | 230 | onLoad({ pid = this.pid, sk_id: skId }) { |
... | ... | @@ -230,6 +266,14 @@ export default { |
230 | 266 | cartNumber() { |
231 | 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 | 278 | methods: { |
235 | 279 | // 获取产品详情 |
... | ... | @@ -249,6 +293,103 @@ export default { |
249 | 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 | 395 | </script> |
... | ... | @@ -293,6 +434,7 @@ export default { |
293 | 434 | .info_pay_number { |
294 | 435 | color: #999; |
295 | 436 | font-size: 14px; |
437 | + font-family: PingFangSC-Regular; | |
296 | 438 | } |
297 | 439 | } |
298 | 440 | // 产品名称 |
... | ... | @@ -459,6 +601,10 @@ export default { |
459 | 601 | justify-content: space-between; |
460 | 602 | align-content: center; |
461 | 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 | 608 | .menu_1 { |
463 | 609 | width: 20%; |
464 | 610 | height: 100%; | ... | ... |
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
... | ... | @@ -4,6 +4,7 @@ import request from '../request' |
4 | 4 | const { |
5 | 5 | read, |
6 | 6 | cartList, |
7 | + makePost, | |
7 | 8 | } = urlAlias |
8 | 9 | |
9 | 10 | const state = { |
... | ... | @@ -44,20 +45,27 @@ const state = { |
44 | 45 | more: '', |
45 | 46 | // 购物车数目 |
46 | 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 | 53 | const mutations = { |
50 | - INIT: (state, { carousel, goodsInfo, tag, specification, evaluate, more }) => { | |
54 | + INIT: (state, { carousel, goodsInfo, tag, specification, evaluate, more, skuList }) => { | |
51 | 55 | state.carousel = carousel |
52 | 56 | state.goodsInfo = goodsInfo |
53 | 57 | state.tag = tag |
54 | 58 | state.specification = specification |
55 | 59 | state.evaluate = evaluate |
56 | 60 | state.more = more |
61 | + state.skuList = skuList | |
57 | 62 | }, |
58 | 63 | CART: (state, number) => { |
59 | 64 | state.cartNumber = number |
60 | 65 | }, |
66 | + POST: (state, url) => { | |
67 | + state.postUrl = url | |
68 | + }, | |
61 | 69 | } |
62 | 70 | |
63 | 71 | const actions = { |
... | ... | @@ -87,6 +95,7 @@ const actions = { |
87 | 95 | } |
88 | 96 | |
89 | 97 | commit('INIT', { |
98 | + skuList: data.skuList, | |
90 | 99 | carousel: data.pics, |
91 | 100 | goodsInfo: { |
92 | 101 | name: data.p_name, |
... | ... | @@ -101,6 +110,7 @@ const actions = { |
101 | 110 | tag: data.judge_tag, |
102 | 111 | star: parseInt(5 * Number(data.judgeInfo.good.slice(0, -1)) / 100), |
103 | 112 | }, |
113 | + // eslint-disable-next-line | |
104 | 114 | more: data.prodIntro1.replace(/\<img/gi, '<img style="max-width:100%;height:auto"'), |
105 | 115 | }) |
106 | 116 | resolve(data) |
... | ... | @@ -116,7 +126,6 @@ const actions = { |
116 | 126 | url: cartList, |
117 | 127 | data: param, |
118 | 128 | success: ({ data: { data } }) => { |
119 | - console.log('cartData', data) | |
120 | 129 | let number = 0 |
121 | 130 | for (let index = 0; index < data.length; index++) { |
122 | 131 | number += Number(data[index].num) |
... | ... | @@ -125,6 +134,17 @@ const actions = { |
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 | 150 | export default { | ... | ... |
src/store/url.js
... | ... | @@ -35,6 +35,7 @@ const urlAlias = { |
35 | 35 | detailStandardList: '/app/prod/read', // 获取商品的详细信息 |
36 | 36 | // 选购页 |
37 | 37 | detailStandardUrl: '/app/prod/read', // 获取商品的详细信息 |
38 | + makePost: '/app/glass/makeProdAdvPic', // 生成分享海报 | |
38 | 39 | |
39 | 40 | // 地址管理 |
40 | 41 | editAddress: '/app/address/edit_address', // 编辑地址 | ... | ... |