ソースを参照

ip营销活动的规则和书单列表接口对接

Alex 9 ヶ月 前
コミット
84021d7ef2

+ 0 - 14
.editorconfig

@@ -1,14 +0,0 @@
-# https://editorconfig.org
-root = true
-
-[*]
-charset = utf-8
-indent_style = space
-indent_size = 2
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.md]
-insert_final_newline = false
-trim_trailing_whitespace = false

+ 67 - 0
src/views/marketing/ipMrakup/booklist/components/booklist-add.vue

@@ -0,0 +1,67 @@
+<!-- 新建营销书籍弹窗 -->
+<template>
+    <ele-modal form :width="460" v-model="visible" title="新建营销书籍" @open="handleOpen">
+        <SimpleForm :items="items" labelWidth="80px" ref="formRef" :initKeys="form"></SimpleForm>
+        <template #footer>
+            <el-button @click="handleCancel">取消</el-button>
+            <el-button type="primary" @click="handleSumbit">确定</el-button>
+        </template>
+    </ele-modal>
+</template>
+
+<script setup>
+import { ref, reactive, nextTick } from 'vue';
+import SimpleForm from '@/components/CommonPage/SimpleForm.vue';
+import validators from '@/utils/validators';
+import request from '@/utils/request';
+
+/** 弹窗是否打开 */
+const visible = defineModel({ type: Boolean });
+
+/** 关闭弹窗 */
+const handleCancel = () => {
+    visible.value = false;
+    nextTick(() => {
+        formRef.value?.resetForm();
+    });
+};
+
+const form = ref({
+    isbn: ''
+});
+
+/** 弹窗打开事件 */
+const handleOpen = () => {
+    visible.value = true;
+    nextTick(() => {
+        formRef.value?.resetForm();
+    });
+};
+
+const items = reactive([
+    {
+        label: 'ISBN',
+        prop: 'isbn',
+        type: 'input',
+        required: true,
+        placeholder: '请输入'
+    }
+]);
+
+const formRef = ref();
+
+const emit = defineEmits(['refresh']);
+const handleSumbit = () => {
+    formRef.value?.submitForm().then((data) => {
+        request.post('/activity/activityUpsellBook/activity/upsell/book/add', data).then(() => {
+            visible.value = false;
+            ElMessage.success('添加成功');
+            emit('done');
+        });
+    });
+};
+
+defineExpose({
+    handleOpen
+});
+</script>

+ 54 - 0
src/views/marketing/ipMrakup/booklist/components/page-search.vue

@@ -0,0 +1,54 @@
+<!-- 搜索表单 -->
+<template>
+  <ProSearch
+    :items="formItems"
+    ref="searchRef"
+    @search="search"
+    :initKeys="initKeys"
+  >
+  </ProSearch>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits, getCurrentInstance } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+  import { colProps } from 'element-plus';
+
+  const emit = defineEmits(['search']);
+
+  const formItems = reactive([
+    {
+      type: 'input',
+      label: 'ISBN',
+      prop: 'isbn',
+      placeholder: '请输入ISBN',
+      colProps: {
+        span: 14,
+      }
+    }
+  ]);
+
+  const initKeys = reactive({
+    isbn: ''
+  });
+
+  const searchRef = ref(null);
+
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data });
+  };
+
+  defineExpose({
+    search
+  });
+</script>
+<style lang="scss" scoped>
+  :deep(.el-form-item) {
+    width: 100%;
+    margin-bottom: 0;
+    .el-input {
+      width: 300px !important;
+    }
+  }
+</style>

+ 66 - 69
src/views/marketing/ipMrakup/booklist/index.vue

@@ -7,42 +7,46 @@
       :bodyStyle="{ padding: 0 }"
     >
       <template #toolbar>
-        <el-button
-          type="primary"
-          plain
-          :icon="PlusOutlined"
-          v-permission="'ipMrakup:booklist:add'"
-          @click="handleUpdate()"
-        >
-          新建
-        </el-button>
-        <el-button
-          type="danger"
-          plain
-          :icon="DeleteOutlined"
-          v-permission="'ipMrakup:booklist:batchDelete'"
-          @click="handleBatchDelete()"
-        >
-          批量删除
-        </el-button>
-        <el-button
-          type="primary"
-          plain
-          v-permission="'ipMrakup:booklist:import'"
-          @click="handleImportExcel"
-          :icon="UploadOutlined"
-        >
-          导入
-        </el-button>
-        <el-button
-          type="success"
-          plain
-          v-permission="'ipMrakup:booklist:export'"
-          @click="handleExportExcel"
-          :icon="DownloadOutlined"
-        >
-          导出
-        </el-button>
+        <div class="flex items-center">
+          <el-button
+            type="primary"
+            plain
+            :icon="PlusOutlined"
+            v-permission="'ipMrakup:booklist:add'"
+            @click="handleUpdate()"
+          >
+            新建
+          </el-button>
+          <el-button
+            type="danger"
+            plain
+            :icon="DeleteOutlined"
+            v-permission="'ipMrakup:booklist:batchDelete'"
+            @click="handleBatchDelete()"
+          >
+            批量删除
+          </el-button>
+          <el-button
+            type="primary"
+            plain
+            v-permission="'ipMrakup:booklist:import'"
+            @click="handleImportExcel"
+            :icon="UploadOutlined"
+          >
+            导入
+          </el-button>
+          <el-button
+            type="success"
+            plain
+            v-permission="'ipMrakup:booklist:export'"
+            @click="handleExportExcel"
+            :icon="DownloadOutlined"
+          >
+            导出
+          </el-button>
+
+          <page-search style="margin-left: 30px" ref="searchRef" @search="reload" />
+        </div>
       </template>
       <template #cover="{ row }">
         <el-image
@@ -58,10 +62,10 @@
       <template #action="{ row }">
         <div>
           <el-button
-            type="warning"
+            type="danger"
             link
             v-permission="'ipMrakup:booklist:delete'"
-            @click="handleDetail(row)"
+            @click="handleBatchDelete(row)"
           >
             [删除]
           </el-button>
@@ -73,6 +77,7 @@
       v-model="showImport"
       @done="reload()"
     ></booklist-import>
+    <booklist-add ref="editRef" @done="reload()"></booklist-add>
   </ele-page>
 </template>
 
@@ -86,6 +91,9 @@
   } from '@/components/icons';
   import CommonTable from '@/components/CommonPage/CommonTable.vue';
   import booklistImport from './components/booklist-import.vue';
+  import booklistAdd from './components/booklist-add.vue';
+  import { ElMessage, ElMessageBox } from 'element-plus';
+  import pageSearch from './components/page-search.vue';
 
   defineOptions({ name: 'ipMarkupBooklist' });
 
@@ -103,7 +111,7 @@
       prop: 'cover',
       slot: 'cover',
       align: 'center',
-      width: 100
+      width: 110
     },
     {
       label: 'ISBN',
@@ -120,49 +128,43 @@
     {
       label: '作者',
       prop: 'author',
-      align: 'center',
-      width: 120
+      align: 'center'
     },
     {
       label: '出版社',
-      prop: 'publisher',
-      align: 'center',
-      width: 150
+      prop: 'publish',
+      align: 'center'
     },
     {
       label: '出版时间',
-      prop: 'publishTime',
-      align: 'center',
-      width: 120
+      prop: 'pubDate',
+      align: 'center'
     },
     {
       label: '定价',
       prop: 'price',
-      align: 'center',
-      width: 80
+      align: 'center'
     },
     {
       label: '回收折扣',
-      prop: 'discount',
-      align: 'center',
-      width: 80
+      prop: 'recycleDiscount',
+      align: 'center'
     },
     {
       label: '加价金额',
-      prop: 'addPrice',
-      align: 'center',
-      width: 80
+      prop: 'upsellPrice',
+      align: 'center'
     },
     {
       label: '添加时间',
-      prop: 'addTime',
+      prop: 'createTime',
       align: 'center',
-      width: 160
+      width: 120
     },
     {
       columnKey: 'action',
       label: '操作',
-      width: 150,
+      width: 90,
       align: 'center',
       slot: 'action'
     }
@@ -172,8 +174,8 @@
   const pageRef = ref(null);
 
   const pageConfig = reactive({
-    pageUrl: '/marketing/ipMrakup/booklist/list',
-    exportUrl: '/marketing/ipMrakup/booklist/export',
+    pageUrl: '/activity/activityUpsellBook/activity/upsell/book/pagelist',
+    exportUrl: '/activity/activityUpsellBook/activity/upsell/book/export',
     fileName: 'IP营销书单',
     cacheKey: 'ip-markup-booklist'
   });
@@ -201,13 +203,14 @@
       ElMessage.warning('请选择要删除的记录');
       return;
     }
-    let ids = selections.map((item) => item.id).join(',');
-    let url = `/marketing/ipMrakup/booklist/removeById/${ids}`;
+    let isbnList = selections.map((item) => item.isbn);
+    let url = `/activity/activityUpsellBook/activity/upsell/book/delete`;
     pageRef.value?.operatBatch({
       title: '确认删除?',
       method: 'post',
       url,
-      row
+      row,
+      data: { isbnList }
     });
   }
 
@@ -216,10 +219,4 @@
   function handleUpdate(row) {
     editRef.value?.handleOpen(row);
   }
-
-  // 详情
-  const detailRef = ref(null);
-  function handleDetail(row) {
-    detailRef.value?.handleOpen(row);
-  }
 </script>

+ 137 - 43
src/views/marketing/ipMrakup/rules/index.vue

@@ -5,14 +5,14 @@
       <el-form :model="form" class="common-form" label-width="auto">
         <el-form-item label="加价比例:">
           <ele-input
-            v-model="form.markupRatio"
+            v-model="form.upsellRate"
             placeholder="请输入"
             suffixStr="(%)"
           />
         </el-form-item>
         <el-form-item label="加价限制时间:">
           <ele-input
-            v-model="form.markupTimeLimit"
+            v-model="form.inviteExpireHour"
             placeholder="请输入"
             suffixStr="(小时)"
           />
@@ -20,55 +20,65 @@
         </el-form-item>
         <el-form-item label="每人每种书可加价次数:">
           <ele-input
-            v-model="form.markupTimesPerBook"
+            v-model="form.upsellTimesPerIsbn"
             placeholder="请输入"
             suffixStr="(次)"
           />
         </el-form-item>
         <el-form-item label="每个ID每天助力限制:">
           <ele-input
-            v-model="form.dailyAssistLimit"
+            v-model="form.assistTimesEveryDay"
             placeholder="请输入"
             suffixStr="(次)"
           />
         </el-form-item>
         <el-form-item label="预留手机号:">
-          <ele-input v-model="form.reservedPhone" placeholder="请输入" />
+          <ele-input v-model="form.mobile" placeholder="请输入" />
+          <el-button
+            v-if="requireMobileVerification"
+            type="primary"
+            size="default"
+            class="ml-2"
+            @click="getVerificationCode"
+            :disabled="cooldown > 0"
+          >
+            {{ cooldown > 0 ? `${cooldown}秒后重试` : '获取验证码' }}
+          </el-button>
+        </el-form-item>
+        <el-form-item label="验证码:" v-if="needVerification">
+          <ele-input v-model="form.code" placeholder="请输入验证码" />
         </el-form-item>
         <el-form-item label="单本最高加价:">
           <ele-input
-            v-model="form.maxPriceMarkup"
+            v-model="form.maxPerIsbn"
             placeholder="请输入"
             suffixStr="(元)"
           />
         </el-form-item>
         <el-form-item label="单本最低加价:">
           <ele-input
-            v-model="form.minPriceMarkup"
+            v-model="form.minPerIsbn"
             placeholder="请输入"
             suffixStr="(元)"
           />
         </el-form-item>
         <el-form-item label="加价结算场景:">
           <el-select
-            v-model="form.settlementScenarios"
+            v-model="form.upsellValidScenario"
             multiple
             collapse-tags
             style="width: 500px"
             placeholder="请选择加价结算场景"
           >
-            <el-option
-              label="验货不合格(其他原因)"
-              value="verification_failed_other"
-            />
-            <el-option label="验货合格" value="verification_passed" />
+            <el-option label="验货不合格(其他原因)" :value="2" />
+            <el-option label="验货合格" :value="1" />
+            <el-option label="验货不合格(无此书)" :value="3" />
           </el-select>
-          <el-button type="success" plain link class="ml-10">[修改]</el-button>
         </el-form-item>
         <el-form-item>
           <el-button
             type="success"
-            style="width: 100px"
+            style="width: 100px;margin-top: 100px;margin-left: 50px;"
             plain
             @click="onSubmit"
             v-permission="'marketing:ipMarkup:rules:update'"
@@ -81,57 +91,133 @@
 </template>
 
 <script setup>
-  import { reactive, ref, onMounted } from 'vue';
+  import { reactive, ref, onMounted, onUnmounted } from 'vue';
   import EleInput from '@/components/CommonPage/EleInput.vue';
   import { ElMessage } from 'element-plus';
   import request from '@/utils/request';
 
   const form = reactive({
-    markupRatio: '10',
-    markupTimeLimit: '24',
-    markupTimesPerBook: '1',
-    dailyAssistLimit: '1',
-    reservedPhone: '18888888888',
-    maxPriceMarkup: '5',
-    minPriceMarkup: '0.5',
-    settlementScenarios: ['verification_failed_other', 'verification_passed']
+    upsellRate: '',
+    inviteExpireHour: '',
+    upsellTimesPerIsbn: '',
+    assistTimesEveryDay: '',
+    mobile: '',
+    maxPerIsbn: '',
+    minPerIsbn: '',
+    upsellValidScenario: [],
+    code: ''
   });
 
+  const cooldown = ref(0);
+  const needVerification = ref(false);
+  const requireMobileVerification = ref(true);
+  let timer = null;
+
   // 获取当前设置
   function getRules() {
-    request.get('/marketing/ipMarkup/rules/get').then((res) => {
+    request.get('/activity/upsell/manage/rule/get').then((res) => {
       if (res.data.code === 200) {
         const data = res.data.data;
-        form.markupRatio = data.markupRatio;
-        form.markupTimeLimit = data.markupTimeLimit;
-        form.markupTimesPerBook = data.markupTimesPerBook;
-        form.dailyAssistLimit = data.dailyAssistLimit;
-        form.reservedPhone = data.reservedPhone;
-        form.maxPriceMarkup = data.maxPriceMarkup;
-        form.minPriceMarkup = data.minPriceMarkup;
-        form.settlementScenarios = data.settlementScenarios;
+        form.upsellRate = data.upsellRate;
+        form.inviteExpireHour = data.inviteExpireHour;
+        form.upsellTimesPerIsbn = data.upsellTimesPerIsbn;
+        form.assistTimesEveryDay = data.assistTimesEveryDay;
+        form.maxPerIsbn = data.maxPerIsbn;
+        form.minPerIsbn = data.minPerIsbn;
+        form.upsellValidScenario = data.upsellValidScenario;
+
+        // 检查是否有mobile字段
+        if (data.mobile) {
+          form.mobile = data.mobile;
+          requireMobileVerification.value = true;
+        } else {
+          form.mobile = '';
+          requireMobileVerification.value = false;
+          // 如果不需要验证,则重置验证状态
+          needVerification.value = false;
+        }
       } else {
         ElMessage.error(res.data.msg);
       }
     });
   }
 
+  // 获取验证码
+  const getVerificationCode = () => {
+    if (!form.mobile) {
+      ElMessage.warning('请输入手机号');
+      return;
+    }
+
+    request
+      .post('/activity/upsell/manage/rule/getCode', {
+        mobile: form.mobile
+      })
+      .then((res) => {
+        if (res.data.code === 200) {
+          ElMessage.success('验证码已发送');
+          needVerification.value = true;
+          startCooldown();
+        } else {
+          ElMessage.error(res.data.msg);
+        }
+      });
+  };
+
+  // 开始倒计时
+  const startCooldown = () => {
+    cooldown.value = 60;
+    if (timer) clearInterval(timer);
+    timer = setInterval(() => {
+      if (cooldown.value > 0) {
+        cooldown.value--;
+      } else {
+        clearInterval(timer);
+        timer = null;
+      }
+    }, 1000);
+  };
+
   // 保存设置
   const onSubmit = () => {
+    // 验证表单
+    if (requireMobileVerification.value) {
+      if (!form.mobile) {
+        ElMessage.warning('请输入预留手机号');
+        return;
+      }
+
+      if (needVerification.value && !form.code) {
+        ElMessage.warning('请输入验证码');
+        return;
+      }
+    }
+
+    const requestData = {
+      upsellRate: form.upsellRate,
+      inviteExpireHour: form.inviteExpireHour,
+      upsellTimesPerIsbn: form.upsellTimesPerIsbn,
+      assistTimesEveryDay: form.assistTimesEveryDay,
+      maxPerIsbn: form.maxPerIsbn,
+      minPerIsbn: form.minPerIsbn,
+      mobile: form.mobile,
+      code: form.code,
+      upsellValidScenario: form.upsellValidScenario
+    };
+
+    // 只有在需要验证的情况下才添加mobile和code字段
+    if (requireMobileVerification.value) {
+      requestData.mobile = form.mobile;
+      requestData.code = form.code;
+    }
+
     request
-      .post('/marketing/ipMarkup/rules/update', {
-        markupRatio: form.markupRatio,
-        markupTimeLimit: form.markupTimeLimit,
-        markupTimesPerBook: form.markupTimesPerBook,
-        dailyAssistLimit: form.dailyAssistLimit,
-        reservedPhone: form.reservedPhone,
-        maxPriceMarkup: form.maxPriceMarkup,
-        minPriceMarkup: form.minPriceMarkup,
-        settlementScenarios: form.settlementScenarios
-      })
+      .post('/activity/upsell/manage/rule/update', requestData)
       .then((res) => {
         if (res.data.code === 200) {
           ElMessage.success('保存成功');
+          needVerification.value = false;
+          form.code = '';
         } else {
           ElMessage.error(res.data.msg);
         }
@@ -141,4 +227,12 @@
   onMounted(() => {
     getRules();
   });
+
+  // 组件销毁时清理定时器
+  onUnmounted(() => {
+    if (timer) {
+      clearInterval(timer);
+      timer = null;
+    }
+  });
 </script>