CouponList.mjs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { withDirectives as _withDirectives, vShow as _vShow, createVNode as _createVNode } from "vue";
  2. import { ref, watch, computed, nextTick, onMounted, defineComponent } from "vue";
  3. import { truthProp, windowHeight, makeArrayProp, makeStringProp, makeNumberProp, createNamespace } from "../utils/index.mjs";
  4. import { useRefs } from "../composables/use-refs.mjs";
  5. import { Tab } from "../tab/index.mjs";
  6. import { Tabs } from "../tabs/index.mjs";
  7. import { Empty } from "../empty/index.mjs";
  8. import { Field } from "../field/index.mjs";
  9. import { Button } from "../button/index.mjs";
  10. import { Coupon } from "../coupon/index.mjs";
  11. import { useRect } from "@vant/use";
  12. const [name, bem, t] = createNamespace("coupon-list");
  13. const couponListProps = {
  14. code: makeStringProp(""),
  15. coupons: makeArrayProp(),
  16. currency: makeStringProp("\xA5"),
  17. showCount: truthProp,
  18. emptyImage: String,
  19. chosenCoupon: makeNumberProp(-1),
  20. enabledTitle: String,
  21. disabledTitle: String,
  22. disabledCoupons: makeArrayProp(),
  23. showExchangeBar: truthProp,
  24. showCloseButton: truthProp,
  25. closeButtonText: String,
  26. inputPlaceholder: String,
  27. exchangeMinLength: makeNumberProp(1),
  28. exchangeButtonText: String,
  29. displayedCouponIndex: makeNumberProp(-1),
  30. exchangeButtonLoading: Boolean,
  31. exchangeButtonDisabled: Boolean
  32. };
  33. var stdin_default = defineComponent({
  34. name,
  35. props: couponListProps,
  36. emits: ["change", "exchange", "update:code"],
  37. setup(props, {
  38. emit,
  39. slots
  40. }) {
  41. const [couponRefs, setCouponRefs] = useRefs();
  42. const root = ref();
  43. const barRef = ref();
  44. const activeTab = ref(0);
  45. const listHeight = ref(0);
  46. const currentCode = ref(props.code);
  47. const buttonDisabled = computed(() => !props.exchangeButtonLoading && (props.exchangeButtonDisabled || !currentCode.value || currentCode.value.length < props.exchangeMinLength));
  48. const updateListHeight = () => {
  49. const TABS_HEIGHT = 44;
  50. const rootHeight = useRect(root).height;
  51. const headerHeight = useRect(barRef).height + TABS_HEIGHT;
  52. listHeight.value = (rootHeight > headerHeight ? rootHeight : windowHeight.value) - headerHeight;
  53. };
  54. const onExchange = () => {
  55. emit("exchange", currentCode.value);
  56. if (!props.code) {
  57. currentCode.value = "";
  58. }
  59. };
  60. const scrollToCoupon = (index) => {
  61. nextTick(() => {
  62. var _a;
  63. return (_a = couponRefs.value[index]) == null ? void 0 : _a.scrollIntoView();
  64. });
  65. };
  66. const renderEmpty = () => _createVNode(Empty, {
  67. "image": props.emptyImage
  68. }, {
  69. default: () => [_createVNode("p", {
  70. "class": bem("empty-tip")
  71. }, [t("noCoupon")])]
  72. });
  73. const renderExchangeBar = () => {
  74. if (props.showExchangeBar) {
  75. return _createVNode("div", {
  76. "ref": barRef,
  77. "class": bem("exchange-bar")
  78. }, [_createVNode(Field, {
  79. "modelValue": currentCode.value,
  80. "onUpdate:modelValue": ($event) => currentCode.value = $event,
  81. "clearable": true,
  82. "border": false,
  83. "class": bem("field"),
  84. "placeholder": props.inputPlaceholder || t("placeholder"),
  85. "maxlength": "20"
  86. }, null), _createVNode(Button, {
  87. "plain": true,
  88. "type": "danger",
  89. "class": bem("exchange"),
  90. "text": props.exchangeButtonText || t("exchange"),
  91. "loading": props.exchangeButtonLoading,
  92. "disabled": buttonDisabled.value,
  93. "onClick": onExchange
  94. }, null)]);
  95. }
  96. };
  97. const renderCouponTab = () => {
  98. const {
  99. coupons
  100. } = props;
  101. const count = props.showCount ? ` (${coupons.length})` : "";
  102. const title = (props.enabledTitle || t("enable")) + count;
  103. return _createVNode(Tab, {
  104. "title": title
  105. }, {
  106. default: () => {
  107. var _a;
  108. return [_createVNode("div", {
  109. "class": bem("list", {
  110. "with-bottom": props.showCloseButton
  111. }),
  112. "style": {
  113. height: `${listHeight.value}px`
  114. }
  115. }, [coupons.map((coupon, index) => _createVNode(Coupon, {
  116. "key": coupon.id,
  117. "ref": setCouponRefs(index),
  118. "coupon": coupon,
  119. "chosen": index === props.chosenCoupon,
  120. "currency": props.currency,
  121. "onClick": () => emit("change", index)
  122. }, null)), !coupons.length && renderEmpty(), (_a = slots["list-footer"]) == null ? void 0 : _a.call(slots)])];
  123. }
  124. });
  125. };
  126. const renderDisabledTab = () => {
  127. const {
  128. disabledCoupons
  129. } = props;
  130. const count = props.showCount ? ` (${disabledCoupons.length})` : "";
  131. const title = (props.disabledTitle || t("disabled")) + count;
  132. return _createVNode(Tab, {
  133. "title": title
  134. }, {
  135. default: () => {
  136. var _a;
  137. return [_createVNode("div", {
  138. "class": bem("list", {
  139. "with-bottom": props.showCloseButton
  140. }),
  141. "style": {
  142. height: `${listHeight.value}px`
  143. }
  144. }, [disabledCoupons.map((coupon) => _createVNode(Coupon, {
  145. "disabled": true,
  146. "key": coupon.id,
  147. "coupon": coupon,
  148. "currency": props.currency
  149. }, null)), !disabledCoupons.length && renderEmpty(), (_a = slots["disabled-list-footer"]) == null ? void 0 : _a.call(slots)])];
  150. }
  151. });
  152. };
  153. watch(() => props.code, (value) => {
  154. currentCode.value = value;
  155. });
  156. watch(windowHeight, updateListHeight);
  157. watch(currentCode, (value) => emit("update:code", value));
  158. watch(() => props.displayedCouponIndex, scrollToCoupon);
  159. onMounted(() => {
  160. updateListHeight();
  161. scrollToCoupon(props.displayedCouponIndex);
  162. });
  163. return () => _createVNode("div", {
  164. "ref": root,
  165. "class": bem()
  166. }, [renderExchangeBar(), _createVNode(Tabs, {
  167. "active": activeTab.value,
  168. "onUpdate:active": ($event) => activeTab.value = $event,
  169. "class": bem("tab")
  170. }, {
  171. default: () => [renderCouponTab(), renderDisabledTab()]
  172. }), _createVNode("div", {
  173. "class": bem("bottom")
  174. }, [_withDirectives(_createVNode(Button, {
  175. "round": true,
  176. "block": true,
  177. "type": "danger",
  178. "class": bem("close"),
  179. "text": props.closeButtonText || t("close"),
  180. "onClick": () => emit("change", -1)
  181. }, null), [[_vShow, props.showCloseButton]])])]);
  182. }
  183. });
  184. export {
  185. stdin_default as default
  186. };