index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. <template>
  2. <view class="pre-store-popup popup" catchtouchmove="true" :class="(value && complete) ? 'show' : 'none'"
  3. @touchmove.stop.prevent="moveHandle">
  4. <!-- 页面内容开始 -->
  5. <view class="mask" @click="close('mask')"></view>
  6. <!-- 页面开始 -->
  7. <view class="layer attr-content" :style="'border-radius: 10rpx 10rpx 0 0;'">
  8. <view class="specification-wrapper">
  9. <scroll-view class="specification-wrapper-content" scroll-y="true">
  10. <view class="specification-header">
  11. <view class="specification-name">{{couponInfo.name}}</view>
  12. </view>
  13. <view class="specification-content">
  14. <view v-for="(item, index) in storeRule" :key="index" class="store-item">
  15. <view style="flex: 4;">
  16. <view class="item-rule">预存¥{{ item.store }} 到账 ¥{{ item.upStore }}</view>
  17. </view>
  18. <view style="flex: 1;text-align: right;">
  19. <number-box :min="minBuyNum" :max="maxBuyNum" :step="stepBuyNum" v-model="selectNum[index]"
  20. :positive-integer="true">
  21. </number-box>
  22. </view>
  23. </view>
  24. </view>
  25. </scroll-view>
  26. <view class="close" @click="close('close')" v-if="showClose">
  27. <image class="close-item" :src="closeImage"></image>
  28. </view>
  29. </view>
  30. <view v-if="noStock" class="btn-wrapper">
  31. <view class="sure" style="color:#ffffff;background-color:#cccccc">库存没有了</view>
  32. </view>
  33. <view class="btn-wrapper">
  34. <view class="sure" @click="buyNow">立即预存</view>
  35. </view>
  36. <!-- 页面结束 -->
  37. </view>
  38. <!-- 页面内容结束 -->
  39. </view>
  40. </template>
  41. <script>
  42. import NumberBox from './number-box'
  43. var that; // 当前页面对象
  44. var vk; // 自定义函数集
  45. export default {
  46. name: 'CouponPopup',
  47. components: {
  48. NumberBox
  49. },
  50. props: {
  51. // true 组件显示 false 组件隐藏
  52. value: {
  53. Type: Boolean,
  54. default: false
  55. },
  56. // vk云函数路由模式参数开始-----------------------------------------------------------
  57. // 卡券信息
  58. couponInfo: {
  59. Type: Object,
  60. default: {}
  61. },
  62. // 预存规则
  63. storeRule: {
  64. type: Array,
  65. default: []
  66. },
  67. // vk云函数路由模式参数结束-----------------------------------------------------------
  68. // 点击遮罩是否关闭组件 true 关闭 false 不关闭 默认true
  69. maskCloseAble: {
  70. Type: Boolean,
  71. default: true
  72. },
  73. // 最小购买数量
  74. minBuyNum: {
  75. Type: Number,
  76. default: 0
  77. },
  78. // 最大购买数量
  79. maxBuyNum: {
  80. Type: Number,
  81. default: 1000
  82. },
  83. // 每次点击后的数量
  84. stepBuyNum: {
  85. Type: Number,
  86. default: 1
  87. },
  88. // 是否显示右上角关闭按钮
  89. showClose: {
  90. Type: Boolean,
  91. default: true
  92. },
  93. // 关闭按钮的图片地址
  94. closeImage: {
  95. Type: String,
  96. default: "https://img.alicdn.com/imgextra/i1/121022687/O1CN01ImN0O11VigqwzpLiK_!!121022687.png"
  97. }
  98. },
  99. data() {
  100. return {
  101. complete: false, // 组件是否加载完成
  102. isShow: false, // true 显示 false 隐藏
  103. noStock: false,
  104. selectNum: [], // 选中数量
  105. };
  106. },
  107. mounted() {
  108. that = this;
  109. },
  110. created() {
  111. const app = this
  112. this.storeRule.forEach(function(){
  113. app.selectNum.push(0)
  114. })
  115. },
  116. methods: {
  117. // 初始化
  118. init() {
  119. //empty
  120. },
  121. async open() {
  122. that.complete = true;
  123. that.$emit("open", true);
  124. that.$emit("input", true);
  125. },
  126. // 监听 - 弹出层收起
  127. close(s) {
  128. if (s == "close") {
  129. that.$emit("input", false);
  130. that.$emit("close", "close");
  131. } else if (s == "mask") {
  132. if (that.maskCloseAble) {
  133. that.$emit("input", false);
  134. that.$emit("close", "mask");
  135. }
  136. }
  137. },
  138. moveHandle() {
  139. //禁止父元素滑动
  140. },
  141. // 立即预存
  142. buyNow() {
  143. let selected = "";
  144. let allZero = true;
  145. this.selectNum.forEach(function(num) {
  146. if (num > 0) {
  147. allZero = false;
  148. }
  149. if (selected.length === 0) {
  150. selected = num
  151. } else {
  152. selected = selected + "," + num;
  153. }
  154. })
  155. if (allZero) {
  156. this.$error("预存数量必须大于1");
  157. return false
  158. }
  159. this.$navTo('pages/settlement/index', { couponId: this.couponInfo.id, selectNum: selected })
  160. },
  161. // 弹窗
  162. toast(title, icon) {
  163. uni.showToast({
  164. title: title,
  165. icon: icon
  166. });
  167. }
  168. },
  169. // 计算属性
  170. computed: {
  171. // empty
  172. },
  173. watch: {
  174. value: function(val) {
  175. if (val) {
  176. that.open();
  177. }
  178. },
  179. }
  180. };
  181. </script>
  182. <style lang="scss" scoped>
  183. .pre-store-popup {
  184. position: fixed;
  185. left: 0;
  186. top: 0;
  187. right: 0;
  188. bottom: 0;
  189. z-index: 21;
  190. overflow: hidden;
  191. &.show {
  192. display: block;
  193. .mask {
  194. animation: showPopup 0.2s linear both;
  195. }
  196. .layer {
  197. animation: showLayer 0.2s linear both;
  198. padding-bottom: 50rpx;
  199. }
  200. }
  201. &.hide {
  202. .mask {
  203. animation: hidePopup 0.2s linear both;
  204. }
  205. .layer {
  206. animation: hideLayer 0.2s linear both;
  207. }
  208. }
  209. &.none {
  210. display: none;
  211. }
  212. .mask {
  213. position: fixed;
  214. top: 0;
  215. width: 100%;
  216. height: 100%;
  217. z-index: 1;
  218. background-color: rgba(0, 0, 0, 0.65);
  219. }
  220. .layer {
  221. display: flex;
  222. width: 100%;
  223. flex-direction: column;
  224. position: fixed;
  225. z-index: 99;
  226. bottom: 0;
  227. border-radius: 10rpx 10rpx 0 0;
  228. background-color: #fff;
  229. .specification-wrapper {
  230. width: 100%;
  231. padding: 30rpx 25rpx;
  232. box-sizing: border-box;
  233. background: #ffffff;
  234. .specification-wrapper-content {
  235. width: 100%;
  236. max-height: 900rpx;
  237. min-height: 300rpx;
  238. &::-webkit-scrollbar {
  239. /*隐藏滚轮*/
  240. display: none;
  241. }
  242. .specification-header {
  243. width: 100%;
  244. display: flex;
  245. flex-direction: row;
  246. position: relative;
  247. margin-bottom: 40rpx;
  248. .specification-name{
  249. font-weight: bold;
  250. }
  251. }
  252. .specification-content {
  253. font-weight: 500;
  254. font-size: 26rpx;
  255. .store-item {
  256. display: flex;
  257. height: 100rpx;
  258. padding-top:30rpx;
  259. cursor:pointer;
  260. .item-rule {
  261. padding: 10rpx;
  262. border: solid 1px #f03c3c;
  263. border-radius: 10rpx;
  264. width: 400rpx;
  265. text-align: center;
  266. background: #f9211c;
  267. color: #ffffff;
  268. }
  269. }
  270. }
  271. }
  272. .close {
  273. position: absolute;
  274. top: 30rpx;
  275. right: 25rpx;
  276. width: 50rpx;
  277. height: 50rpx;
  278. text-align: center;
  279. line-height: 50rpx;
  280. .close-item {
  281. width: 40rpx;
  282. height: 40rpx;
  283. }
  284. }
  285. }
  286. .btn-wrapper {
  287. display: flex;
  288. width: 100%;
  289. height: 120rpx;
  290. flex: 0 0 120rpx;
  291. align-items: center;
  292. justify-content: space-between;
  293. padding: 0 26rpx;
  294. box-sizing: border-box;
  295. .layer-btn {
  296. width: 335rpx;
  297. height: 76rpx;
  298. border-radius: 38rpx;
  299. color: #fff;
  300. line-height: 76rpx;
  301. text-align: center;
  302. font-weight: 500;
  303. font-size: 28rpx;
  304. &.add-cart {
  305. background: #ffbe46;
  306. }
  307. &.buy {
  308. background: #fe560a;
  309. }
  310. }
  311. .sure {
  312. width: 698rpx;
  313. height: 80rpx;
  314. border-radius: 40rpx;
  315. color: #fff;
  316. line-height: 80rpx;
  317. text-align: center;
  318. font-weight: 500;
  319. font-size: 28rpx;
  320. background:linear-gradient(to right, #f9211c, #ff6335)
  321. }
  322. .sure.add-cart {
  323. background: #ff9402;
  324. }
  325. }
  326. }
  327. @keyframes showPopup {
  328. 0% {
  329. opacity: 0;
  330. }
  331. 100% {
  332. opacity: 1;
  333. }
  334. }
  335. @keyframes hidePopup {
  336. 0% {
  337. opacity: 1;
  338. }
  339. 100% {
  340. opacity: 0;
  341. }
  342. }
  343. @keyframes showLayer {
  344. 0% {
  345. transform: translateY(120%);
  346. }
  347. 100% {
  348. transform: translateY(0%);
  349. }
  350. }
  351. @keyframes hideLayer {
  352. 0% {
  353. transform: translateY(0);
  354. }
  355. 100% {
  356. transform: translateY(120%);
  357. }
  358. }
  359. }
  360. </style>