Explorar el Código

Merge remote-tracking branch 'origin/master'

YPZ hace 3 semanas
padre
commit
2d3590067f

+ 2 - 3
java/storlead-knowledge/storlead-knowledge-biz/src/main/resources/mapper/AiMessageMapper.xml

@@ -23,9 +23,7 @@
     </resultMap>
     <select id="queryList" resultMap="AiMessageWithReviewMap">
         SELECT
-        m.id,
-        m.query,
-        m.answer,
+        m.*,
         IFNULL(sum(r.agree), 0) AS agree,
         IFNULL(sum(r.disagree), 0) AS disagree,
         MAX(CASE WHEN r.owner_by = 1 THEN r.agree    ELSE 0 END) AS my_agree,
@@ -45,6 +43,7 @@
         <if test="queryField != null and queryField != ''">
             HAVING ${queryField} > 0
         </if>
+        ORDER BY create_time desc
     </select>
 
     <select id="getTotal" resultType="java.lang.Integer">

+ 1 - 1
java/storlead-mail/storlead-mail-biz/src/main/java/com/storlead/mail/service/impl/MktMailStatusServiceImpl.java

@@ -29,7 +29,7 @@ public class MktMailStatusServiceImpl
         }
         LambdaQueryWrapper<MktMailStatusEntity> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(MktMailStatusEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
-                .apply("update_time > status_updated_at")
+                .apply("update_time > status_updated_at or status_updated_at is null ")
                 .gt(lastId != null, MktMailStatusEntity::getId, lastId)
                 .orderByAsc(MktMailStatusEntity::getId)
                 .last("limit " + limit);

+ 4 - 0
ui/smarttrade-platform/src/assets/styles/marketing.css

@@ -923,6 +923,10 @@
 
 .no-data{ min-height: 100px; display: flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: 14px; }
 :deep(.el-loading-mask){ background: transparent; }
+.btn:disabled{
+  opacity: 0.5;
+  cursor: not-allowed;
+}
 
 
 @media (max-width: 1400px) {

+ 10 - 4
ui/smarttrade-platform/src/components/addMarketing.vue

@@ -455,7 +455,7 @@
                                 "></div>
                             <div class="rule-content">
                                 <div class="rule-title">未打开邮件自动跟进</div>
-                                <div class="rule-desc">3天后发送提醒邮件,更换主题行</div>
+                                <div class="rule-desc">{{ newCampaign.rules.noOpenFollowupDays }}天后发送提醒邮件,更换主题行</div>
                             </div>
                             <div class="rule-config" v-if="newCampaign.rules.noOpenFollowup">
                                 <el-select style="width: 90px;" v-model="newCampaign.rules.noOpenFollowupDays" placeholder="请选择">
@@ -632,9 +632,9 @@
                 <button v-if="currentStep < 5" class="btn btn-primary" @click="currentStep++">
                     下一步 <i class="fas fa-arrow-right"></i>
                 </button>
-                <button v-else class="btn btn-primary" @click="createCampaign">
-                    <i class="fas fa-rocket"></i> {{ isEditMode ? "保存活动" : "创建活动" }}
-                </button>
+                <el-button :loading="loading" style="height: 41px;" v-else class="btn btn-primary" @click="createCampaign">
+                    <i class="fas fa-rocket" style="margin-right: 6px;"></i> {{ isEditMode ? "保存活动" : "创建活动" }}
+                </el-button>
             </div>
         </div>
     </div>
@@ -888,6 +888,7 @@
 
     const goToStep = (step) => { currentStep.value = step }
 
+    const loading = ref(false)
     const createCampaign = async () => {
         if (!newCampaign.value.name) {
             currentStep.value = 1
@@ -904,6 +905,7 @@
             return
         }
         try {
+            loading.value = true
             const typeMap = { prospect: 1, nurture: 2, reactivate: 3, promote: 4, seasonal: 5, exhibition: 6, other: 7 }
             const priorityMap = { urgent: 1, high: 2, medium: 3, low: 4 }
             const channelConfig = newCampaign.value.channels.reduce((acc, channel) => {
@@ -952,6 +954,8 @@
                     closeCreateModal()
                 }).catch(err => {
                     ElMessage.error(err?.message || '更新营销活动失败')
+                }).finally(() => {
+                    loading.value = false
                 })
             } else {
                 await addMarketing(payload).then(res => {
@@ -960,6 +964,8 @@
                     closeCreateModal()
                 }).catch(err => {
                     ElMessage.error(err?.message || '创建营销活动失败')
+                }).finally(() => {
+                    loading.value = false
                 })
             }
         } catch (error) {

+ 5 - 1
ui/smarttrade-platform/src/components/layout/TopBar.vue

@@ -567,7 +567,7 @@
     </transition>
   </header>
 
-  <AddMarketing ref="addMarketingRef" />
+  <AddMarketing ref="addMarketingRef" @refresh="handleMarketingRefresh" />
 
   <div v-if="showSettings" class="modal-overlay" @click.self="showSettings = false">
     <div class="modal create-modal" style="max-width: 800px;">
@@ -709,6 +709,10 @@ const pageTitle = computed(() => {
 })
 
 const addMarketingRef = ref()
+const handleMarketingRefresh = () => {
+  window.dispatchEvent(new CustomEvent('marketing:refresh'))
+}
+
 const openModal = (type) => {
   showQuickActions.value = false
   addMarketingRef.value.open()

+ 2 - 0
ui/smarttrade-platform/src/components/marketing/emailList.vue

@@ -75,6 +75,7 @@ const emailList = ref([])
 const open = (campaign) => {
   selectedCampaign.value = campaign || null
   emailList.value = []
+  activeFilter.value = 'pending'
   getStatusCounts()
   getList()
   showEmailListModal.value = true
@@ -141,6 +142,7 @@ const cancelSend = (item) => {
     cancelEmail({ id: item.id, status: (item.status == -1 ? -3 : -1) }).then(() => {
       ElMessage.success('操作成功')
       getList()
+      getStatusCounts()
     }).catch((err) => {
       ElMessage.error(err.message || '操作失败')
     })

+ 2 - 2
ui/smarttrade-platform/src/components/marketing/marketingDetail.vue

@@ -143,7 +143,7 @@
                   <div class="step-marker">{{ item.step }}</div>
                   <div class="step-content">
                     <div class="step-title">{{ item.name }}</div>
-                    <div class="step-meta">第{{ item.days }}天 · 邮件 · 待执行</div>
+                    <div class="step-meta">间隔{{ item.days }}天 · 邮件 · 待执行</div>
                   </div>
                 </div>
               </div>
@@ -208,7 +208,7 @@
             <i class="fas fa-download"></i> 导出报告
           </button> -->
           <button class="btn btn-secondary" @click="showCampaignDetailModal = false">关闭</button>
-          <button class="btn btn-primary" @click="editCampaign(selectedCampaign)">
+          <button class="btn btn-primary" :disabled="selectedCampaign.status != 0" @click="editCampaign(selectedCampaign)">
             <i class="fas fa-edit"></i> 编辑活动
           </button>
         </div>

+ 22 - 15
ui/smarttrade-platform/src/views/KnowledgeView.vue

@@ -450,7 +450,7 @@
         </div>
         <div class="modal-footer">
           <button class="btn btn-secondary" @click="showAddModal = false">取消</button>
-          <button class="btn btn-primary" @click="addKnowledge"><i class="fas fa-plus"></i> {{chunkType=='add'?'添加':'确认'}}</button>
+          <button class="btn btn-primary" @click="addKnowledge" v-loading='knowledgeModelLoading' element-loading-background="rgba(0, 0, 0, 0.8)"><i class="fas fa-plus"></i> {{chunkType=='add'?'添加':'确认'}}</button>
         </div>
       </div>
     </div>
@@ -699,6 +699,8 @@ const showToast = ref(false)
 const toastMessage = ref('')
 const toastType = ref('success')
 const chunkType = ref('add')
+const knowledgeModelLoading = ref(false)
+
 
 
 const syncStatus = {
@@ -1107,27 +1109,32 @@ const addKnowledgeDocument = ()=> {
   documentList.value = []
 }
 const addKnowledge = () => {
-   
+ 
   if(((chunkType.value=='add'||doc_form.value=='qa_model')&&!newKnowledge.value.answer)||!newKnowledge.value.content||!newKnowledge.value.dataset_id||!newKnowledge.value.document_id){
     ElMessage.error('请填入必填项')
     return false
   }
+  if (knowledgeModelLoading.value) return
+  knowledgeModelLoading.value= true
   if(chunkType.value =='add'){
-    createChunk(newKnowledge.value).then(res => {
-      if(res.success){
-        showToastMessage('知识添加成功,AI 已学习', 'success')
-        showAddModal.value = false
-      }
-    })
+      createChunk(newKnowledge.value).then(res => {
+        knowledgeModelLoading.value = false
+        if(res.success){
+          showToastMessage('知识添加成功,AI 已学习', 'success')
+          showAddModal.value = false
+        }
+      })
+    
   }else{
-    editChunk({segment:newKnowledge.value}).then(res => {
-      if(res.success){
-        showToastMessage('知识编辑成功,AI 已学习', 'success')
-        showAddModal.value = false
-      }
-    })
+      editChunk({segment:newKnowledge.value}).then(res => {
+        knowledgeModelLoading.value = false
+        if(res.success){
+          showToastMessage('知识编辑成功,AI 已学习', 'success')
+          showAddModal.value = false
+          getChunkDatasets()
+        }
+      })
   }
-  
 }
 
 const aiOptimize = (type) => {

+ 10 - 1
ui/smarttrade-platform/src/views/MarketingView.vue

@@ -731,7 +731,7 @@
 </template>
 
 <script setup>
-import { ref, computed, onMounted } from 'vue'
+import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
 import { ElMessageBox } from 'element-plus'
 import AddMarketing from '../components/addMarketing.vue'
 import { getMarketingList, setMarketingStatus, marketingAnalysis } from '../api/marketing'
@@ -773,9 +773,18 @@ const openCreateModal = () => {
 }
 
 const marketingList = ref([])
+const handleExternalMarketingRefresh = () => {
+  getData()
+}
+
 onMounted(() => {
   getData()
   getStatsData()
+  window.addEventListener('marketing:refresh', handleExternalMarketingRefresh)
+})
+
+onBeforeUnmount(() => {
+  window.removeEventListener('marketing:refresh', handleExternalMarketingRefresh)
 })
 
 const loading = ref(false)