index.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <template>
  2. <ele-page flex-table :bodyStyle="{ padding: 0 }">
  3. <div class="common-section p-6 bg-white rounded-lg">
  4. <div class="text-lg font-bold mb-6">降价营销规则</div>
  5. <div class="flex">
  6. <div class="flex-1 max-w-3xl">
  7. <el-form :model="form" label-width="200px" class="rules-form" v-loading="loading">
  8. <el-form-item label="分享一人降价比例:">
  9. <div class="flex items-center">
  10. <el-input-number v-model="form.reduceRate" :min="0" :max="100" />
  11. <span class="ml-2">(%)</span>
  12. </div>
  13. </el-form-item>
  14. <el-form-item label="降价限制时间:">
  15. <div class="flex items-center">
  16. <el-input-number v-model="form.inviteExpireHour" :min="0" />
  17. <span class="ml-2">(小时)</span>
  18. <span class="ml-4 text-gray-400">以助力成功计算</span>
  19. </div>
  20. </el-form-item>
  21. <el-form-item label="每单每本书可降价次数:">
  22. <div class="flex items-center">
  23. <el-input-number v-model="form.reduceTimesPerIsbn" :min="0" />
  24. <span class="ml-2">(次)</span>
  25. </div>
  26. </el-form-item>
  27. <el-form-item label="每个ID每天助力限制:">
  28. <div class="flex items-center">
  29. <el-input-number v-model="form.assistTimesEveryDay" :min="0" />
  30. <span class="ml-2">(次)</span>
  31. </div>
  32. </el-form-item>
  33. <el-form-item label="分享一人最高降价:">
  34. <div class="flex items-center">
  35. <el-input-number v-model="form.maxPerHelp" :min="0" :precision="2" />
  36. <span class="ml-2">(元)</span>
  37. </div>
  38. </el-form-item>
  39. <el-form-item label="分享一人最低降价:">
  40. <div class="flex items-center">
  41. <el-input-number v-model="form.minPerHelp" :min="0" :precision="2" />
  42. <span class="ml-2">(元)</span>
  43. </div>
  44. </el-form-item>
  45. <el-form-item label="降价取消场景:">
  46. <div class="flex items-center w-full">
  47. <dict-data v-model="form.upsellValidScenario" code="upsell_valid_scenario"
  48. type="multipleSelect" style="width:300px" />
  49. </div>
  50. </el-form-item>
  51. <el-form-item label="预留手机号:">
  52. <div class="flex items-center">
  53. <el-input v-model="form.mobile" placeholder="请输入手机号" style="width: 300px" />
  54. </div>
  55. </el-form-item>
  56. <el-form-item label="验证码:" v-if="needVerification">
  57. <div class="flex items-center">
  58. <el-input v-model="form.code" placeholder="请输入验证码" style="width: 200px" />
  59. <el-button type="primary" link class="ml-4" @click="handleResendCode"
  60. :disabled="cooldown > 0">
  61. {{ cooldown > 0 ? `${cooldown}秒后重发` : '获取验证码' }}
  62. </el-button>
  63. </div>
  64. </el-form-item>
  65. <el-form-item label="营销降价书单:">
  66. <div class="flex items-center">
  67. <dict-data v-model="form.reduceScope" code="reduce_scope" style="width:300px" />
  68. </div>
  69. </el-form-item>
  70. <el-form-item>
  71. <el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
  72. </el-form-item>
  73. </el-form>
  74. </div>
  75. <!-- Right Side Note -->
  76. <div class="w-64 ml-8">
  77. <div class="bg-yellow-50 border border-yellow-200 p-4 rounded text-sm text-gray-600">
  78. <p class="mb-2 font-bold">注意事项:</p>
  79. <p class="mb-2">单本金额不能为负,最低为0</p>
  80. <p>
  81. 降价金额为一般品金额,不管用户选择什么品相
  82. </p>
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. </ele-page>
  88. </template>
  89. <script setup>
  90. import { reactive, ref, onMounted, onUnmounted } from 'vue';
  91. import { EleMessage } from 'ele-admin-plus/es';
  92. import request from '@/utils/request';
  93. defineOptions({ name: 'ShareDiscountRules' });
  94. const loading = ref(false);
  95. const saving = ref(false);
  96. const needVerification = ref(false);
  97. const cooldown = ref(0);
  98. let timer = null;
  99. const form = reactive({
  100. reduceRate: void 0,
  101. inviteExpireHour: void 0,
  102. reduceTimesPerIsbn: void 0,
  103. assistTimesEveryDay: void 0,
  104. maxPerHelp: void 0,
  105. minPerHelp: void 0,
  106. upsellValidScenario: [],
  107. mobile: '',
  108. reduceScope: void 0,
  109. code: ''
  110. });
  111. const startCooldown = () => {
  112. cooldown.value = 60;
  113. if (timer) clearInterval(timer);
  114. timer = setInterval(() => {
  115. if (cooldown.value > 0) {
  116. cooldown.value--;
  117. } else {
  118. clearInterval(timer);
  119. timer = null;
  120. }
  121. }, 1000);
  122. };
  123. const fetchRules = async () => {
  124. loading.value = true;
  125. try {
  126. const res = await request.get('/activity/reduce/manage/rule/get');
  127. if (res.data.code === 0 || res.data.code === 200) {
  128. const data = res.data.data;
  129. Object.assign(form, data);
  130. form.upsellValidScenario = data.upsellValidScenario.map(v => v.toString());
  131. form.reduceScope = data.reduceScope?.toString();
  132. if(form.mobile){
  133. needVerification.value = true;
  134. }
  135. }
  136. } catch (error) {
  137. console.error(error);
  138. } finally {
  139. loading.value = false;
  140. }
  141. };
  142. const updateRule = async () => {
  143. try {
  144. const res = await request.post('/activity/reduce/manage/rule/update', form);
  145. if (res.data.code === 0 || res.data.code === 200) {
  146. EleMessage.success('保存成功');
  147. form.code = '';
  148. } else {
  149. EleMessage.error(res.data.msg || '保存失败');
  150. }
  151. } catch (error) {
  152. console.error(error);
  153. EleMessage.error('保存失败');
  154. }
  155. };
  156. const handleResendCode = async () => {
  157. try {
  158. const res = await request.post('/activity/reduce/manage/rule/getCode');
  159. if (res.data.code === 0 || res.data.code === 200) {
  160. if (res.data.data === 1) {
  161. EleMessage.success('验证码已发送');
  162. startCooldown();
  163. } else {
  164. EleMessage.info('无需验证码');
  165. needVerification.value = false;
  166. }
  167. } else {
  168. EleMessage.error(res.data.msg || '获取验证码失败');
  169. }
  170. } catch (error) {
  171. console.error(error);
  172. EleMessage.error('获取验证码失败');
  173. }
  174. };
  175. const handleSave = async () => {
  176. saving.value = true;
  177. try {
  178. if (form.code) {
  179. await updateRule();
  180. } else {
  181. // Check if verification is needed
  182. const res = await request.post('/activity/reduce/manage/rule/getCode');
  183. if (res.data.code === 0 || res.data.code === 200) {
  184. if (res.data.data === 1) {
  185. needVerification.value = true;
  186. EleMessage.success('验证码已发送,请输入验证码');
  187. startCooldown();
  188. } else {
  189. await updateRule();
  190. }
  191. } else {
  192. EleMessage.error(res.data.msg || '获取验证码失败');
  193. }
  194. }
  195. } catch (error) {
  196. console.error(error);
  197. EleMessage.error('操作失败');
  198. } finally {
  199. saving.value = false;
  200. }
  201. };
  202. onMounted(() => {
  203. fetchRules();
  204. });
  205. onUnmounted(() => {
  206. if (timer) {
  207. clearInterval(timer);
  208. timer = null;
  209. }
  210. });
  211. </script>
  212. <style scoped>
  213. .rules-form :deep(.el-form-item__label) {
  214. font-weight: 500;
  215. }
  216. </style>