3 Commits d2226d860d ... 6f4baa2773

Tác giả SHA1 Thông báo Ngày
  pansl 6f4baa2773 Merge branch 'pansl' into test 1 năm trước cách đây
  pansl b29c7fbc56 Merge branch 'pansl' into test 1 năm trước cách đây
  pansl ff2f738ff8 Merge branch 'pansl' into test 1 năm trước cách đây

+ 2 - 2
src/router/modules/charge.ts

@@ -10,8 +10,8 @@
 //       {
 //         path: 'index',
 //         name: 'user-account11',
-//         meta: { title: '巨量2.0事件-微信小程序', icon: 'home' },
-//         component: () => import('@/views/payBack/juliangPlus/index.vue')
+//         meta: { title: '引流管理', icon: 'home' },
+//         component: () => import('@/views/drainageManage/drainageList/index.vue')
 //       },
 //       {
 //         path: 'index1',

+ 188 - 0
src/views/drainageManage/drainageList/form/create.vue

@@ -0,0 +1,188 @@
+<template>
+  <el-form :model="formData" label-width="130px" ref="ruleForm" :rules="rules" v-loading="loading" class="pr-4">
+    <div class="flex flex-row justify-between">
+      <div class="w-full">
+        <el-form-item label="关注类型" prop="focus_type">
+          <el-radio-group v-model="formData.focus_type">
+            <el-radio :label="1">公众号引流</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="公众号" prop="gzh_id">
+          <el-select v-model="formData.gzh_id" filterable remote clearable
+            :remote-method="(query) => { remoteMethod(query, 'wechatPlatformOfficialAccountList') }">
+            <el-option v-for="item in officialAccountsList" :key="item.id" :label="item.nick_name" :value="item.id" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="播放页弹窗设置" prop="pop_type">
+          <el-radio-group v-model="formData.pop_type">
+            <el-radio :label="1">强制关注</el-radio>
+            <el-radio :label="2">引导关注</el-radio>
+            <el-radio :label="3">不关注</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item v-if="formData.pop_type == 2" label="弹窗设置" prop="pop_type_sub">
+          <el-radio-group v-model="formData.pop_type_sub">
+            <el-radio :label="1">仅设置剧集弹窗</el-radio>
+            <el-radio :label="2">设置剧集及以后每集都弹</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="弹窗类型" prop="link_type">
+          <el-radio-group v-model="formData.link_type">
+            <el-radio :label="1">关注链接</el-radio>
+            <el-radio :label="2">关注二维码</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item v-if="formData.link_type == 1" label="关注链接" prop="_link_url"
+          :rules="[{ required: true, message: '关注链接必须填写' }]" label-width="120px">
+          <el-input style="width:300px;" autosize v-model="formData._link_url" auto-complete="off"
+            placeholder="关注链接地址要与配置的公众号保存一致"></el-input>
+        </el-form-item>
+        <el-form-item v-if="formData.link_type == 2" label="关注二维码" prop="cover_image">
+          <my-upload acceptType=".png,.jpg,.jpeg" :isMultiple="false" @fileRemove="fileRemove" @fileSuccess="fileSuccess"
+            :fileList="formData.fileList" action="/qiniu/upload/image"></my-upload>
+        </el-form-item>
+      </div>
+    </div>
+    <div class="flex justify-end">
+      <el-button type="primary" @click="submitForm(ruleForm)">{{ $t('system.confirm') }}</el-button>
+    </div>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+import { InfoFilled } from '@element-plus/icons-vue';
+import { wechatPlatformOfficialAccountList } from '@/api/officialAccount/officialList/index'
+import { videoStockVideoUpdate, videoStockVideoAdd, videoStockVideoCategoryList } from '@/api/video/index'
+import type { FormInstance, FormRules } from 'element-plus'
+const ruleForm = ref<FormInstance>()
+import { onMounted, ref } from 'vue';
+const props = defineProps({
+  primary: String | Number | Object,
+});
+const officialAccountsList = ref([])
+const emit = defineEmits(['close']);
+const formData = ref({ focus_type: 1, pop_type: 1, pop_type_sub: 1, link_type: 1 })
+const rules = reactive({
+  focus_type: [
+    {
+      required: true,
+      message: '请选择关注类型',
+      trigger: 'change'
+    }
+  ],
+  gzh_id: [
+    {
+      required: true,
+      message: '请选择公众号',
+      trigger: 'change'
+    }
+  ],
+  pop_type: [
+    {
+      required: true,
+      message: '请选择播放页弹窗设置',
+      trigger: 'change'
+    }
+  ],
+  pop_type_sub: [
+    {
+      required: true,
+      message: '请选择弹窗类型',
+      trigger: 'change'
+    }
+  ],
+  link_type: [
+    {
+      required: true,
+      message: '请选择弹窗设置',
+      trigger: 'change'
+    }
+  ],
+  link_url: [
+    {
+      required: true,
+      message: '请上传关注二维码',
+    }
+  ],
+  _link_url: [
+    {
+      required: true,
+      message: '请输入关注链接',
+    },
+    { pattern: /^(http|https):\/\/[^ "]+$/, message: '关注链接格式不正确', trigger: 'blur' }
+  ],
+});
+const loading = ref(false)
+
+
+const remoteMethod = (query: string, type: string,) => {
+  console.log(query, 'queryquery', type);
+  switch (type) {
+    case 'wechatPlatformOfficialAccountList':
+      initRemoteOption('wechatPlatformOfficialAccountList', { nick_name: query })
+      break;
+  }
+}
+
+const initRemoteOption = (type: string, params?: object) => {
+  switch (type) {
+    case 'wechatPlatformOfficialAccountList':
+      wechatPlatformOfficialAccountList({ limit: 99, ...params }).then(res => {
+        officialAccountsList.value = res.data
+      })
+      break;
+  }
+}
+const fileSuccess = (e) => {
+  console.log(e);
+  formData.value.link_url = e;
+}
+const fileRemove = (e) => {
+  console.log(e);
+  formData.value.link_url = '';
+}
+const submitForm = (formEl: FormInstance | undefined) => {
+  console.log(formData.value, 'formData.valueformData.value');
+  if (!formEl) return;
+  formEl
+    .validate(valid => {
+      if (valid) {
+        let api;
+        let params = {
+          focus_type: formData.value.focus_type,
+          gzh_id: formData.value.gzh_id,
+          pop_type: formData.value.pop_type,
+          pop_type_sub: formData.value.pop_type_sub,
+          link_type: formData.value.link_type,
+          link_url: formData.value.link_url || formData.value._link_url,
+        };
+        console.log(params, 'submitFormsubmitForm');
+        return
+        if (props.primary) {
+          api = videoStockVideoUpdate
+          params.id = formData.value.id
+        } else {
+          api = videoStockVideoAdd
+        }
+        api(params).then(res => {
+          console.log(res);
+          ElMessage.success(res.message)
+          emit('close')
+        })
+      } else {
+        loading.value = false;
+      }
+    })
+    .then(() => { });
+}
+
+if (props.primary) {
+  formData.value = JSON.parse(JSON.stringify(props.primary))
+  formData.value.fileList = [{ uid: props.primary.id, url: props.primary.link_url }]
+} else {
+  formData.value.fileList = []
+}
+onMounted(() => {
+  initRemoteOption('wechatPlatformOfficialAccountList')
+});
+</script>

+ 177 - 0
src/views/drainageManage/drainageList/index.vue

@@ -0,0 +1,177 @@
+<template>
+  <div class="flex flex-col justify-between w-full sm:flex-row">
+    <div class="w-full">
+      <Search :search="search" :reset="reset">
+        <template v-slot:body>
+          <el-form-item label="公众号">
+            <el-select v-model="query.gzh_id" filterable remote clearable
+              :remote-method="(query) => { remoteMethod(query, 'wechatPlatformOfficialAccountList') }">
+              <el-option v-for="item in officialAccountsList" :key="item.id" :label="item.nick_name" :value="item.id" />
+            </el-select>
+          </el-form-item>
+        </template>
+        <template v-slot:content>
+          <div class="table-default">
+            <div class="pt-5 pl-2">
+              <el-button type="primary" v-action="'wechatPlatform.KFMessage.add'" size="default"
+                @click="openType('createVisible', null)">新增</el-button>
+            </div>
+            <el-table :data="tableData" class="mt-3" v-loading="loading">
+              <el-table-column prop="name" label="配置公众号" min-width="200">
+                <template #default="scope">
+                  <div class="flex flex-col">
+                    <div>
+                      {{ scope.row.gzh_names }}
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="send_at" label="关注类型" min-width="200">
+                <template #default="scope">
+                  <span>{{ scope.row.send_at }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column prop="send_at" label="弹窗类型" min-width="200">
+                <template #default="scope">
+                  <span>{{ scope.row.send_at }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column prop="send_at" label="创建时间" min-width="200">
+                <template #default="scope">
+                  <span>{{ scope.row.send_at }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" width="200" fixed="right">
+                <template #default="scope">
+                  <div v-if="![4, 2].includes(scope.row.status)" v-action="'wechatPlatform.KFMessage.updateContent'">
+                    <el-button link type="primary" size="small"
+                      @click="openType('createVisible', scope.row)">编辑</el-button>
+                  </div>
+                  <div>
+                    <el-button link type="primary" size="small" v-action="'wechatPlatform.KFMessage.detail'"
+                      @click="openType('createVisible', { look: true, ...scope.row })">查看</el-button>
+                  </div>
+                  <div v-if="scope.row.status != 2" v-action="'wechatPlatform.KFMessage.delete'">
+                    <el-button link type="primary" size="small" @click="deleteChange(scope.row)">删除</el-button>
+                  </div>
+                </template>
+              </el-table-column>
+            </el-table>
+            <Paginate />
+          </div>
+        </template>
+      </Search>
+      <Dialog v-model="createVisible" :title="createTitle" destroy-on-close>
+        <Create @close="closeType('createVisible')" :primary="current" />
+      </Dialog>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { InfoFilled } from '@element-plus/icons-vue';
+import { shortcuts } from '@/utils/shortcuts'
+import { optionsCommonParams } from '@/api/common/index'
+import Create from './form/create.vue';
+import { useGetList } from '@/hook/curd/useGetList';
+import { wechatPlatformOfficialAccountList } from '@/api/officialAccount/officialList/index'
+import { wechatPlatformKfMessageStop, wechatPlatformKfMessageDelete, wechatPlatformKfMessageUpdateGZH } from '@/api/officialAccount/newsService/index'
+const api = 'wechatPlatform/kfMessage/list';
+const createVisible = ref(false)
+const current = ref<object | null>({})
+const messageTypeList = ref([])
+const sendStateList = ref([])
+const officialAccountsList = ref([])
+const createTitle = ref('新增')
+const { data, query, search, reset, loading } = useGetList(api);
+const rolesIdentify = inject('rolesIdentify')
+const tableData = computed(() => data.value?.data);
+
+const openType = (type: string, data: object | null) => {
+  current.value = data;
+  switch (type) {
+    case 'createVisible':
+      createVisible.value = true
+      if (current.value?.id) {
+        createTitle.value = '编辑'
+        if (current.value.look) {
+          createTitle.value = "查看"
+        }
+      } else {
+        createTitle.value = '新增'
+      }
+      break;
+  }
+}
+
+const initCommonParams = () => {
+  optionsCommonParams().then(res => {
+    console.log(res, 'optionsCommonParams');
+    messageTypeList.value = res?.data?.wechatPlatform?.kfMessageType
+    sendStateList.value = res?.data?.wechatPlatform?.kfMessageStatus
+  })
+}
+
+const closeType = (type: string) => {
+  switch (type) {
+    case 'createVisible':
+      createVisible.value = false
+      break;
+  }
+  search()
+}
+
+const deleteChange = (row: object) => {
+  ElMessageBox.confirm(
+    `确定要删除活动:${row.name} 吗?`,
+    '提示',
+    {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }
+  )
+    .then(() => {
+      wechatPlatformKfMessageDelete({ ids: [row.id] }).then(res => {
+        console.log(res);
+        ElMessage.success(res.message)
+        search()
+      })
+    })
+    .catch(() => {
+
+    })
+}
+const remoteMethod = (query: string, type: string,) => {
+  console.log(query, 'queryquery', type);
+  switch (type) {
+    case 'wechatPlatformOfficialAccountList':
+      initRemoteOption('wechatPlatformOfficialAccountList', { nick_name: query })
+      break;
+  }
+}
+
+const initRemoteOption = (type: string, params?: object) => {
+  switch (type) {
+    case 'wechatPlatformOfficialAccountList':
+      wechatPlatformOfficialAccountList({ limit: 99, ...params }).then(res => {
+        officialAccountsList.value = res.data
+      })
+      break;
+  }
+}
+
+onMounted(() => {
+  initCommonParams()
+  initRemoteOption('wechatPlatformOfficialAccountList')
+  search();
+});
+</script>
+
+<style lang="scss" scoped>
+.withdraw-popup-warn {
+  font-size: 14px;
+  font-weight: 600;
+  color: #666;
+}
+</style>

+ 3 - 3
src/views/officialAccount/newsService/index.vue

@@ -6,11 +6,11 @@
           <el-form-item label="活动名称">
             <el-input placeholder="请输入活动名称" v-model="query.name" clearable></el-input>
           </el-form-item>
-          <el-form-item label="消息类型">
+          <!-- <el-form-item label="消息类型">
             <el-select v-model="query.message_type" clearable filterable placeholder="请选择消息类型">
               <el-option v-for="(item, index) in messageTypeList" :key="index" :label="item.label" :value="item.value" />
             </el-select>
-          </el-form-item>
+          </el-form-item> -->
           <el-form-item label="发送状态">
             <el-select v-model="query.status" clearable filterable placeholder="请选择发送状态">
               <el-option v-for="(item, index) in sendStateList" :key="index" :label="item.label" :value="item.value" />
@@ -47,7 +47,7 @@
                   <span>{{ scope.row.send_at }}</span>
                 </template>
               </el-table-column>
-              <el-table-column prop="message_type_str" label="消息类型" min-width="150"></el-table-column>
+              <!-- <el-table-column prop="message_type_str" label="消息类型" min-width="150"></el-table-column> -->
               <el-table-column prop="status_str" label="发送状态" min-width="150">
                 <template #default="scope">
                   <el-text class="mx-1" :type="colorType(scope.row)">{{ scope.row.status_str }}</el-text>

+ 5 - 6
src/views/officialAccount/publicCustomMenu/form/customMenu.vue

@@ -116,7 +116,7 @@
                     <div
                       v-if="menus?.buttons[menus?.curActiveIndex]?.sub_button[menus?.curSubActiveIndex]?.type == 'view'">
                       <el-form-item label="网页链接">
-                        <el-input style="width:300px;"
+                        <el-input style="width:300px;" type="url"
                           v-model="menus.buttons[menus.curActiveIndex].sub_button[menus.curSubActiveIndex].url"
                           auto-complete="off" placeholder="请输入网页链接"></el-input>
                       </el-form-item>
@@ -137,7 +137,6 @@
                     <el-form-item label="菜单名称" prop="title">
                       <el-input v-model="menus.buttons[menus.curActiveIndex].name" @change="nameChange"
                         style="width: 260px" :maxlength="10" placeholder="请输入菜单名称(最多10个字符)"></el-input>
-                      <span style="color:#fd555d;padding-left:10px">受微信限制,如您发现微信显示有问题,请减少内容</span>
                     </el-form-item>
                     <div v-if="!menus.buttons[menus.curActiveIndex].sub_button.length">
                       <el-form-item label="菜单内容">
@@ -163,7 +162,7 @@
                       </div>
                       <div v-if="menus?.buttons[menus?.curActiveIndex]?.type == 'view'">
                         <el-form-item label="网页链接">
-                          <el-input style="width:300px;" v-model="menus.buttons[menus.curActiveIndex].url"
+                          <el-input style="width:300px;" type="url" v-model="menus.buttons[menus.curActiveIndex].url"
                             auto-complete="off" placeholder="请输入网页链接"></el-input>
                         </el-form-item>
                       </div>
@@ -421,15 +420,15 @@ onMounted(() => {
     init: true,
     buttons:
       [
-        { name: "首页", hasChild: false, showChildMenu: true, content: '', type: "miniprogram", url: "", key: "首页", sub_button: [], },
+        { name: "首页", hasChild: false, showChildMenu: true, content: '', type: "miniprogram", url: "/pages/index/index", key: "首页", sub_button: [], },
         {
-          name: "我的", hasChild: false, showChildMenu: false, content: '', type: "miniprogram", url: "", key: "我的", sub_button: [],
+          name: "我的", hasChild: false, showChildMenu: false, content: '', type: "miniprogram", url: "/pages/member/index", key: "我的", sub_button: [],
         },
         {
           name: "菜单名称3", hasChild: true, showChildMenu: false, content: '', type: "miniprogram", url: "", key: "菜单名称3",
           sub_button:
             [
-              { key: "子菜单名称", type: "miniprogram", name: "子菜单名称", content: '', url: "" }
+              { key: "子菜单名称", type: "view", name: "子菜单名称", content: '', url: "" }
             ]
         }
       ]

+ 21 - 0
src/views/officialAccount/publicCustomMenu/form/validation.ts

@@ -11,6 +11,15 @@ export const validation = (buttons: Array<object>) => {
       ) {
         throw new Error(`(${button.name}) 链接不能为空`);
       }
+
+      if (
+        ['view'].includes(button.type) &&
+        button.sub_button.length <= 0 &&
+        !isValidUrl(button.url)
+      ) {
+        throw new Error(`(${button.name}) 链接不合法`);
+      }
+
       if (
         button.sub_button.length <= 0 &&
         button.type == 'click' &&
@@ -29,6 +38,10 @@ export const validation = (buttons: Array<object>) => {
           ) {
             throw new Error(`子菜单 (${subButton.name}) 链接不能为空`);
           }
+
+          if (['view'].includes(subButton.type) && !isValidUrl(subButton.url)) {
+            throw new Error(`(${subButton.name}) 链接不合法`);
+          }
           if (subButton.type == 'click' && !subButton.content) {
             throw new Error(`子菜单 (${subButton.name}) 文本内容不能为空`);
           }
@@ -42,3 +55,11 @@ export const validation = (buttons: Array<object>) => {
     return false;
   }
 };
+
+function isValidUrl(url: string) {
+  // 此处可以编写URL合法性检查的逻辑
+  // 返回 true 或 false 表示 URL 是否合法
+  // 例如,可以使用正则表达式进行检查
+  const urlRegex = /^(http|https):\/\/[^ "]+$/;
+  return urlRegex.test(url);
+}

+ 15 - 14
src/views/officialAccount/publicCustomMenu/index.vue

@@ -4,7 +4,12 @@
       <Search :search="search" :reset="resetQuery">
         <template v-slot:body>
           <el-form-item label="模板名称">
-            <el-input placeholder="请输入模板名称" v-model="query.keyword" clearable></el-input>
+            <el-input placeholder="请输入模板名称" v-model="query.title" clearable></el-input>
+          </el-form-item>
+          <el-form-item label="系统类型">
+            <el-select v-model="query.type" clearable placeholder="请选择系统类型">
+              <el-option v-for="item in systemType" :key="item.id" :label="item.label" :value="item.value" />
+            </el-select>
           </el-form-item>
           <el-form-item label="公众号">
             <el-select v-model="query.wechat_authorization_info_id" filterable remote clearable
@@ -20,7 +25,7 @@
               <el-alert title="注:一个公众号对应一套菜单配置,如果重复配置,原内容将被覆盖,以最新配置为准" type="warning" show-icon :closable="false" />
             </div>
             <div class="pt-5 pl-2">
-              <el-button type="primary" v-action="'wechatPlatform.WechatKeywords.add'" size="default"
+              <el-button type="primary" v-action="'wechatPlatform.WechatMenu.add'" size="default"
                 @click="openType('createVisible', null)">新增</el-button>
             </div>
             <el-table :data="tableData" class="mt-3" v-loading="loading">
@@ -43,16 +48,16 @@
 
               <el-table-column label="操作" width="200" fixed="right">
                 <template #default="scope">
-                  <el-button link type="primary" v-action="'wechatPlatform.WechatKeywords.edit'" size="small"
+                  <el-button link type="primary" v-action="'wechatPlatform.WechatMenu.edit'" size="small"
                     @click="openType('createVisible', scope.row)">编辑</el-button>
                   <br />
-                  <el-button link type="primary" v-action="'wechatPlatform.WechatKeywords.detail'" size="small"
+                  <el-button link type="primary" v-action="'wechatPlatform.WechatMenu.detail'" size="small"
                     @click="openType('createVisible', { look: true, ...scope.row })">查看</el-button>
                   <br />
-                  <el-button link type="primary" size="small" v-action="'wechatPlatform.WechatKeywords.del'"
+                  <el-button link type="primary" size="small" v-action="'wechatPlatform.WechatMenu.del'"
                     @click="deleteChange(scope.row)">删除</el-button>
                   <br />
-                  <el-button link type="primary" size="small" v-action="'wechatPlatform.WechatKeywords.allocation'"
+                  <el-button link type="primary" size="small" v-action="'wechatPlatform.WechatMenu.allocation'"
                     @click="openType('configPublicVisible', scope.row)">配置公众号</el-button>
                   <br />
                 </template>
@@ -76,11 +81,7 @@ import { checkPermission } from '@/directives/permission';
 import Create from './form/create.vue';
 import configPublic from '@/views/officialAccount/components/configPublic.vue'
 import { useGetList } from '@/hook/curd/useGetList';
-import {
-  wechatPlatformKeywordGetConfig,
-  wechatPlatformKeywordSetConfig,
-  wechatPlatformKeywordDel
-} from '@/api/officialAccount/keywordReply/index'
+import { wechatPlatformMenuDel } from '@/api/officialAccount/publicCustomMenu/index'
 import { wechatPlatformOfficialAccountList } from '@/api/officialAccount/officialList/index'
 const api = 'wechatPlatform/menu/list';
 import Cache from '@/support/cache';
@@ -92,7 +93,7 @@ const createTitle = ref('新增')
 const { data, query, search, reset, loading } = useGetList(api);
 const rolesIdentify = inject('rolesIdentify')
 const tableData = computed(() => data.value?.data);
-
+const systemType = ref([{ id: 1, label: 'android', value: 'android' }, { id: 2, label: 'ios', value: 'ios' }])
 
 const openType = (type: string, data: object | null) => {
   current.value = data;
@@ -135,7 +136,7 @@ const closeType = (type: string) => {
 
 const deleteChange = (row: object) => {
   ElMessageBox.confirm(
-    '确定要删除吗?',
+    '一旦删除此模板,其对应的公众号菜单会一并清空,确定要删除此菜单模板吗?',
     '提示',
     {
       confirmButtonText: '确定',
@@ -144,7 +145,7 @@ const deleteChange = (row: object) => {
     }
   )
     .then(() => {
-      wechatPlatformKeywordDel({ ids: row.id }).then(res => {
+      wechatPlatformMenuDel({ ids: row.id }).then(res => {
         console.log(res);
         ElMessage.success(res.message)
         search()