Quellcode durchsuchen

Merge remote-tracking branch 'origin/master'

zhujing vor 1 Monat
Ursprung
Commit
3f7ea00c2f

+ 1 - 0
java/storlead-mail/storlead-mail-biz/src/main/resources/mapper/MktMailMessageMapper.xml

@@ -38,4 +38,5 @@
         <result column="delay_send_time" property="delaySendTime"/>
     </resultMap>
 
+
 </mapper>

+ 5 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/MarketingCampaignDTO.java

@@ -12,6 +12,7 @@ import org.springframework.format.annotation.DateTimeFormat;
 import com.storlead.framework.mybatis.page.Page;
 
 import java.time.LocalDate;
+import java.util.Date;
 import java.util.List;
 
 @Data
@@ -88,8 +89,11 @@ public class MarketingCampaignDTO extends Page {
     private String emailAddress;
 
     @ApiModelProperty(value = "发送时间")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
     @TableField("email_sent_time")
-    private String emailSentTime;
+    private Date emailSentTime;
 
     @ApiModelProperty(value = "邮件模板")
     @TableField("email_template")

+ 5 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/entity/MarketingCampaignEntity.java

@@ -12,6 +12,7 @@ import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDate;
+import java.util.Date;
 
 @Data
 @TableName("marketing_campaign")
@@ -83,8 +84,11 @@ public class MarketingCampaignEntity extends SysBaseField {
     private String emailAddress;
 
     @ApiModelProperty(value = "发送时间")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
     @TableField("email_sent_time")
-    private String emailSentTime;
+    private Date emailSentTime;
 
     @ApiModelProperty(value = "邮件模板")
     @TableField("email_template")

+ 9 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/MarketEmailsService.java

@@ -65,6 +65,15 @@ public interface MarketEmailsService extends MyBaseService<MarketEmailsEntity> {
      */
     Result<Object> getManagementDetail(Long marketingCampaignId);
 
+    /***
+      * @Description: 通过id/marketingCampaignId/客户id关联的邮件状态
+      * @Param:
+      * @return:
+      * @Author: YPZ
+      * @Date: 2026/9/9 15:39
+      */
+    void updateCustomerEmailStatus(MarketEmailsCustomerVO marketEmailsCustomerVO);
+
     @Async
     void addSendTime(MarketingCampaignEntity marketingCampaignEntity);
 

+ 6 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/MarketingCampaignService.java

@@ -24,4 +24,10 @@ public interface MarketingCampaignService extends MyBaseService<MarketingCampaig
 
     Result<Object> getDashboardStats();
 
+    /**
+     * 按开始/结束日期同步营销活动的生命周期状态(每天定时任务调用)。
+     * 方法内部会打印本次被变更的活动:哪些改为开始(运行中)、哪些改为结束(完成)。
+     */
+    void syncStartEndStatus();
+
 }

+ 45 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketEmailsServiceImpl.java

@@ -16,6 +16,8 @@ import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import com.storlead.knowledge.pojo.dto.ChatDTO;
 import com.storlead.knowledge.service.ChatService;
 import com.storlead.knowledge.service.WorkflowsService;
+import com.storlead.mail.pojo.entity.MktMailStatusEntity;
+import com.storlead.mail.service.MktMailStatusService;
 import com.storlead.trade.dto.MarketEmailsDTO;
 import com.storlead.trade.entity.*;
 import com.storlead.trade.mapper.MarketEmailsMapper;
@@ -23,6 +25,7 @@ import com.storlead.trade.service.*;
 import com.storlead.trade.vo.*;
 import org.slf4j.Logger;
 import org.springframework.beans.BeanUtils;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
@@ -55,7 +58,7 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
     @Resource
     private CustomerTradeService customerTradeService;
     @Resource
-    @org.springframework.context.annotation.Lazy
+    @Lazy
     private MarketingCampaignSopDetailService marketingCampaignSopDetailEntityService;
     @Resource
     private SopDetailService sopDetailService;
@@ -63,9 +66,12 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
     private WorkflowsService workflowsService;
 
     @Resource
-    @org.springframework.context.annotation.Lazy
+    @Lazy
     private MarketingCampaignService marketingCampaignService;
 
+    @Resource
+    private MktMailStatusService mktMailStatusService;
+
 
     @Override
     public Result<Object> getList(MarketEmailsDTO dto) {
@@ -687,6 +693,43 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
         return Result.ok(voList);
     }
 
+    @Override
+    public void updateCustomerEmailStatus(MarketEmailsCustomerVO marketEmailsCustomerVO) {
+        LambdaQueryWrapper<MarketEmailsEntity> queryWrapper = new LambdaQueryWrapper<>();
+        if (!ObjectUtils.isEmpty(marketEmailsCustomerVO.getCustomerId())){
+            queryWrapper.eq(MarketEmailsEntity::getCustomerId, marketEmailsCustomerVO.getCustomerId());
+        }
+        if (!ObjectUtils.isEmpty(marketEmailsCustomerVO.getMarketingCampaignId())){
+            queryWrapper.eq(MarketEmailsEntity::getMarketingCampaignId, marketEmailsCustomerVO.getMarketingCampaignId());
+        }
+        if (!ObjectUtils.isEmpty(marketEmailsCustomerVO.getId())){
+            queryWrapper.eq(MarketEmailsEntity::getId, marketEmailsCustomerVO.getId());
+        }
+        if (!CollectionUtils.isEmpty(marketEmailsCustomerVO.getMarketingCampaignIdList())){
+            queryWrapper.in(MarketEmailsEntity::getMarketingCampaignId, marketEmailsCustomerVO.getMarketingCampaignIdList());
+        }
+        if (!CollectionUtils.isEmpty(marketEmailsCustomerVO.getCustomerIdList())){
+            queryWrapper.in(MarketEmailsEntity::getCustomerId, marketEmailsCustomerVO.getCustomerIdList());
+        }
+        queryWrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+        List<MarketEmailsEntity> entityList = this.list(queryWrapper);
+        List<Long> idList = entityList.stream().map(MarketEmailsEntity::getId).collect(Collectors.toList());
+        List<Long> emailIdList = entityList.stream().map(MarketEmailsEntity::getEmailId).collect(Collectors.toList());
+        LambdaUpdateWrapper<MarketEmailsEntity> markerEmailUpdateWrapper = new LambdaUpdateWrapper<>();
+        markerEmailUpdateWrapper.in(MarketEmailsEntity::getId, idList);
+        markerEmailUpdateWrapper.set(MarketEmailsEntity::getStatus, marketEmailsCustomerVO.getStatus());
+        this.update(null, markerEmailUpdateWrapper);
+
+        if (!CollectionUtils.isEmpty(emailIdList) && !ObjectUtils.isEmpty(marketEmailsCustomerVO.getStatus())){
+            LambdaUpdateWrapper<MktMailStatusEntity> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.in(MktMailStatusEntity::getId, emailIdList);
+            updateWrapper.set(MktMailStatusEntity::getSendStatus, marketEmailsCustomerVO.getStatus());
+            mktMailStatusService.update(null, updateWrapper);
+        }
+
+
+    }
+
 
     @Override
     public void addSendTime(MarketingCampaignEntity marketingCampaignEntity) {

+ 110 - 8
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketingCampaignServiceImpl.java

@@ -13,12 +13,14 @@ import com.storlead.trade.entity.*;
 import com.storlead.trade.mapper.MarketingCampaignEntityMapper;
 import com.storlead.trade.service.*;
 import com.storlead.trade.vo.CampaignStatsVO;
+import com.storlead.trade.vo.MarketEmailsCustomerVO;
 import com.storlead.trade.vo.MarketingCampaignDetailVO;
 import com.storlead.user.service.IUserService;
 import com.storlead.trade.vo.MarketingCampaignVO;
 import com.storlead.framework.common.constant.CommonConstant;
 import com.storlead.framework.common.result.Result;
 import com.storlead.trade.service.impl.support.TradeDataSourceServiceImpl;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -34,7 +36,10 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import java.time.LocalDate;
+import java.time.ZoneId;
 
+@Slf4j
 @Service
 @DS(DSConstants.DATASOURCE_TRADE)
 public class MarketingCampaignServiceImpl
@@ -230,10 +235,6 @@ public class MarketingCampaignServiceImpl
         BeanUtils.copyProperties(marketingCampaignDTO, marketingCampaignEntity);
         // supervisorList 转为逗号分隔字符串
         marketingCampaignEntity.setSupervisor(joinSupervisorList(marketingCampaignDTO));
-        // 过滤 AI 最优时间占位值,避免写入 DATETIME 列报错
-        if ("optimal".equalsIgnoreCase(marketingCampaignEntity.getEmailSentTime())) {
-            marketingCampaignEntity.setEmailSentTime(null);
-        }
         boolean isOk = this.save(marketingCampaignEntity);
         if (!isOk) {
 
@@ -296,10 +297,6 @@ public class MarketingCampaignServiceImpl
         BeanUtils.copyProperties(marketingCampaignDTO, marketingCampaignEntity);
         // supervisorList 转为逗号分隔字符串
         marketingCampaignEntity.setSupervisor(joinSupervisorList(marketingCampaignDTO));
-        // 过滤 AI 最优时间占位值,避免写入 DATETIME 列报错
-        if ("optimal".equalsIgnoreCase(marketingCampaignEntity.getEmailSentTime())) {
-            marketingCampaignEntity.setEmailSentTime(null);
-        }
         boolean isOk = this.updateById(marketingCampaignEntity);
         if (!isOk) {
             return Result.error("修改失败");
@@ -376,6 +373,111 @@ public class MarketingCampaignServiceImpl
         return Result.ok();
     }
 
+    /**
+     * 生命周期状态常量(对应 marketing_campaign.status 注释:0未开始 1运行中 2暂停 3完成)
+     */
+    private static final int STATUS_NOT_STARTED = 0;
+    private static final int STATUS_RUNNING = 1;
+    private static final int STATUS_PAUSED = 2;
+    private static final int STATUS_COMPLETED = 3;
+
+    /**
+     * 按开始/结束日期同步所有营销活动的生命周期状态。
+     * <p>每天 8 点由 {@code MarketStartOrEndTask} 调度调用。</p>
+     * 规则:
+     * <ul>
+     *     <li>今天 &lt; 开始日期 → 未开始(0)</li>
+     *     <li>开始日期 ≤ 今天 ≤ 结束日期 → 运行中(1)</li>
+     *     <li>今天 &gt; 结束日期 → 完成(3)</li>
+     * </ul>
+     * 手动暂停(2)的活动不自动覆盖,尊重人工操作;开始/结束日期任一缺失则跳过。
+     *
+     * @return 被更新的活动数量
+     */
+    @Override
+    public void syncStartEndStatus() {
+        LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
+        List<MarketingCampaignEntity> all = this.lambdaQuery()
+                .eq(MarketingCampaignEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
+                .list();
+        if (CollectionUtils.isEmpty(all)) {
+            log.info("营销活动开始/结束状态同步:无未删除活动,跳过");
+            return;
+        }
+        // 按目标状态分组,只收集需要变更的 id(跳过暂停 / 日期缺失 / 状态已一致)
+        // 后续每种状态仅执行一次批量 UPDATE,而非逐条 UPDATE
+        Map<Integer, List<Long>> idsByStatus = new HashMap<>(4);
+        // 变更的实体列表(status 已回填为目标状态,用于区分改为开始/结束)
+        List<MarketingCampaignEntity> changed = new ArrayList<>();
+        for (MarketingCampaignEntity c : all) {
+            Integer expected = computeStartEndStatus(c, today);
+            if (expected == null) {
+                continue;
+            }
+            Integer current = c.getStatus();
+            // 尊重手动暂停,不自动覆盖
+            if (current != null && current == STATUS_PAUSED) {
+                continue;
+            }
+            if (expected.equals(current)) {
+                continue;
+            }
+            idsByStatus.computeIfAbsent(expected, k -> new ArrayList<>()).add(c.getId());
+            c.setStatus(expected);
+            changed.add(c);
+        }
+        // 每种目标状态执行一次批量 UPDATE
+        for (Map.Entry<Integer, List<Long>> entry : idsByStatus.entrySet()) {
+            List<Long> ids = entry.getValue();
+            if (CollectionUtils.isEmpty(ids)) {
+                continue;
+            }
+            this.lambdaUpdate()
+                    .in(MarketingCampaignEntity::getId, ids)
+                    .set(MarketingCampaignEntity::getStatus, entry.getKey())
+                    .update();
+        }
+        // 按目标状态拆分列表并打印:哪些改为开始、哪些改为结束
+        List<Long> started = changed.stream()
+                .filter(e -> STATUS_RUNNING == e.getStatus())
+                .map(MarketingCampaignEntity::getId)
+                .collect(Collectors.toList());
+        List<Long> ended = changed.stream()
+                .filter(e -> STATUS_COMPLETED == e.getStatus())
+                .map(MarketingCampaignEntity::getId)
+                .collect(Collectors.toList());
+        log.info("营销活动开始/结束状态同步完成:改为开始(运行中)={}, 改为结束(完成)={}", started, ended);
+        MarketEmailsCustomerVO startVO = new MarketEmailsCustomerVO();
+        startVO.setMarketingCampaignIdList(started);
+        //修改状态为待发送
+        startVO.setStatus(-1);
+        marketEmailsService.updateCustomerEmailStatus(startVO);
+
+        MarketEmailsCustomerVO endVO = new MarketEmailsCustomerVO();
+        endVO.setMarketingCampaignIdList(ended);
+        //修改状态为待发送
+        endVO.setStatus(-3);
+        marketEmailsService.updateCustomerEmailStatus(endVO);
+    }
+
+    /**
+     * 根据开始/结束日期与今天计算期望的状态值;开始/结束日期任一缺失返回 null。
+     */
+    private Integer computeStartEndStatus(MarketingCampaignEntity c, LocalDate today) {
+        LocalDate begin = c.getBeginData();
+        LocalDate end = c.getEndDate();
+        if (begin == null || end == null) {
+            return null;
+        }
+        if (today.isBefore(begin)) {
+            return STATUS_NOT_STARTED;
+        }
+        if (!today.isAfter(end)) {
+            return STATUS_RUNNING;
+        }
+        return STATUS_COMPLETED;
+    }
+
     @Override
     public Result<Object> getDashboardStats() {
         // 计算本月起止时间

+ 32 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/task/MarketStartOrEndTask.java

@@ -0,0 +1,32 @@
+package com.storlead.trade.task;
+
+import com.storlead.trade.service.CustomerAnalysisDispatchService;
+import com.storlead.trade.service.MarketingCampaignService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 每天 8 点:修改营销活动的开始/结束状态
+ */
+@Slf4j
+@Component
+public class MarketStartOrEndTask {
+
+    @Resource
+    private MarketingCampaignService marketingCampaignService;
+
+    @Scheduled(cron = "0 0 8 * * ?")
+    public void dispatch() {
+        long start = System.currentTimeMillis();
+        log.info("营销活动开始/结束状态同步任务开始");
+        try {
+            marketingCampaignService.syncStartEndStatus();
+            log.info("营销活动开始/结束状态同步任务结束, cost={}ms", System.currentTimeMillis() - start);
+        } catch (Exception e) {
+            log.error("营销活动开始/结束状态同步任务失败", e);
+        }
+    }
+}

+ 18 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/MarketEmailsCustomerVO.java

@@ -1,19 +1,34 @@
 package com.storlead.trade.vo;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.util.List;
+
 @Data
 @ApiModel(value = "MarketEmailsCustomerVO", description = "营销邮件客户信息VO")
 public class MarketEmailsCustomerVO {
 
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "营销活动Id")
+    private Long marketingCampaignId;
+
+    @ApiModelProperty(value = "营销活动IdList")
+    private List<Long> marketingCampaignIdList;
+
     @ApiModelProperty(value = "客户分析结果id")
     private Long analysisResultId;
 
     @ApiModelProperty(value = "客户id")
     private Long customerId;
 
+    @ApiModelProperty(value = "客户idList")
+    private List<Long> customerIdList;
+
     @ApiModelProperty(value = "客户名称")
     private String customerName;
 
@@ -34,4 +49,7 @@ public class MarketEmailsCustomerVO {
 
     @ApiModelProperty(value = "置信度")
     private Double confidence;
+
+    @ApiModelProperty(value = "发送状态:-3取消 -2草稿 -1定时 0发送中 1成功 2失败;收信记录一般为1")
+    private Integer status;
 }

+ 5 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/MarketingCampaignVO.java

@@ -13,6 +13,7 @@ import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDate;
+import java.util.Date;
 import java.util.List;
 
 @Data
@@ -71,7 +72,10 @@ public class MarketingCampaignVO extends SysBaseField {
     private String emailAddress;
 
     @ApiModelProperty(value = "发送时间")
-    private String emailSentTime;
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
+    private Date emailSentTime;
 
     @ApiModelProperty(value = "邮件模板")
     private String emailTemplate;

+ 18 - 20
ui/smarttrade-platform/src/components/addMarketing.vue

@@ -341,9 +341,9 @@
                                 <label class="form-label">发送时间</label>
                                 <el-select v-model="newCampaign.emailSendTime" placeholder="请选择发送时间">
                                     <el-option label="AI推荐最优时间" value="optimal" />
-                                    <el-option label="上午 9:00-11:00" value="morning" />
+                                    <!-- <el-option label="上午 9:00-11:00" value="morning" />
                                     <el-option label="下午 14:00-16:00" value="afternoon" />
-                                    <el-option label="晚上 19:00-21:00" value="evening" />
+                                    <el-option label="晚上 19:00-21:00" value="evening" /> -->
                                 </el-select>
                             </div>
                         </div>
@@ -883,7 +883,7 @@
     }
     const getChannelIconById = (id) => ({ email: 'fas fa-envelope', whatsapp: 'fab fa-whatsapp', linkedin: 'fab fa-linkedin', wechat: 'fab fa-weixin' }[id] || 'fas fa-comment')
     const hasWarnings = computed(() => customerList.value.length > 500 || newCampaign.value.channels.length === 0)
-    const confirmChecks = ref({ content: false, schedule: false, compliance: false, unsubscribe: true })
+    const confirmChecks = ref({ content: true, schedule: true, compliance: true, unsubscribe: true })
     const canCreate = computed(() => confirmChecks.value.content && confirmChecks.value.schedule && confirmChecks.value.compliance)
 
     const goToStep = (step) => { currentStep.value = step }
@@ -923,7 +923,7 @@
                 opportunityCount: Number(newCampaign.value.goals.opportunities) || null,
                 channelConfiguration: channelConfig,
                 emailAddress: newCampaign.value.emailSender,
-                emailSentTime: newCampaign.value.emailSendTime,
+                emailSentTime: newCampaign.value.emailSendTime == 'optimal' ? '' : newCampaign.value.emailSendTime,
                 trackConfigOpen: newCampaign.value.trackOpen ? 1 : 0,
                 trackConfigClick: newCampaign.value.trackClick ? 1 : 0,
                 trackConfigReply: newCampaign.value.trackReply ? 1 : 0,
@@ -1061,13 +1061,11 @@
             return
         }
         editSop(customSopData.value.id, customSopData.value).then(res => {
-            if(res.code === 200) {
-                ElMessage.success('保存成功')
-                getSop()
-                showCustomSopModal.value = false
-            } else {
-                ElMessage.error(res.message || '保存失败')
-            }
+            ElMessage.success('保存成功')
+            getSop()
+            showCustomSopModal.value = false
+        }).catch(err => {
+            ElMessage.error(err?.message || '保存失败')
         })
     }
 
@@ -1090,13 +1088,11 @@
             details: datas
         }
         addSop(params).then(res => {
-            if(res.code === 200) {
-                ElMessage.success('已保存新SOP序列')
-                getSop()
-                showCustomSopModal.value = false
-            } else {
-                ElMessage.error(res.message || '保存失败')
-            }
+            ElMessage.success('已保存新SOP序列')
+            getSop()
+            showCustomSopModal.value = false
+        }).catch(err => {
+            ElMessage.error(err?.message || '保存新SOP序列失败')
         })
     }
 
@@ -1158,9 +1154,11 @@
     }
 
     const addCustomer = (data) => {
+        if(customerList.value.find(item => item.id === data.id)) {
+            ElMessage.warning('客户已存在')
+            return
+        }
         customerList.value.push(data)
-        //去重
-        customerList.value = [...new Set(customerList.value)]
         ElMessage.success('添加成功')
     }
 

+ 28 - 13
ui/smarttrade-platform/src/components/marketing/customerDetail.vue

@@ -69,12 +69,14 @@
                                     <div class="customer-meta">
                                         <div class="customer-name-row">
                                             <div class="customer-name">{{ customer.customerName }}</div>
-                                            <span class="customer-badge">{{ customer.tag || '潜客' }}</span>
+                                            <span class="customer-badge" v-if="customer.customerStatusDictValue">{{ getStatusLabel(customer.customerStatusDictValue) }}</span>
+                                        </div>
+                                        <div class="customer-subtitle" v-if="customer.liaison">
+                                            <span><i class="fas fa-user" style="margin-right: 6px"></i> {{ customer.liaison.name }}{{ customer.liaison.departmentPosition ? ' · ' + customer.liaison.departmentPosition : '' }}</span>
                                         </div>
-                                        <div class="customer-subtitle">{{ customer.role || '采购总监' }} · {{ customer.company }}</div>
                                         <div class="customer-info-row">
                                             <span><i class="fas fa-map-marker-alt"></i> {{ customer.continent }} - {{ customer.country }}</span>
-                                            <span><i class="fas fa-dollar-sign"></i> {{ customer.annualPurchase }}</span>
+                                            <span v-if="customer.customerCompany && customer.customerCompany.industry">{{ customer.customerCompany.industry }}</span>
                                         </div>
                                     </div>
                                 </div>
@@ -83,9 +85,9 @@
                                         <div class="customer-score">{{ customer.score }}</div>
                                         <div class="customer-score-label">意向分</div>
                                     </div>
-                                    <div class="right-btn">
-                                        <el-icon v-if="modalType == 'add'" @click="addCustomer(customer)"><Plus /></el-icon>
-                                        <el-icon v-else @click="deleteCustomer(customer)"><Delete /></el-icon>
+                                    <div class="right-btn" @click="handleBtn(customer)">
+                                        <el-icon v-if="modalType == 'add'"><Plus /></el-icon>
+                                        <el-icon v-else><Delete /></el-icon>
                                     </div>
                                 </div>
                             </div>
@@ -118,6 +120,7 @@
     const showCustomerPreview = ref(false)
     const modalType = ref('')
     const allData = ref([])
+    const filterData = ref()
     const open = (type, data) => {
         customers.value = []
         total.value = 0
@@ -134,6 +137,7 @@
             liaisonName: ''
         }
         if(type == 'detail'){
+            filterData.value = data
             allData.value = data
             customers.value = data.slice(0, 10)
             total.value = data.length
@@ -156,6 +160,8 @@
         customerParams.value.country = value ? value[1] : ''
     }
 
+    const getStatusLabel = (type) => ({ 1: '暂无需求', 2: '潜在客户', 3: '意向客户', 4: '忠诚客户', 11: '了解产品', 22: '正在跟进', 33: '寄样试用', 44: '意向购买', 55: '准备付款', 66: '暂时搁置' }[type] || type)
+
     const customers = ref([])
     const total = ref(0)
     const getCustomerData = () => {
@@ -169,7 +175,7 @@
         if(modalType.value == 'add'){
             getCustomerData()
         }else{
-            customers.value = allData.value.slice((page - 1) * customerParams.value.pageSize, page * customerParams.value.pageSize)
+            customers.value = filterData.value.slice((page - 1) * customerParams.value.pageSize, page * customerParams.value.pageSize)
         }
     }
 
@@ -178,8 +184,8 @@
             customerParams.value.pageIndex = 1
             getCustomerData()
         }else{
-            const filterData = allData.value.filter(item => {
-                const blurryMatch = customerParams.value.blurry ? (item.customerName.includes(customerParams.value.blurry) || item.company.includes(customerParams.value.blurry) || item.email.includes(customerParams.value.blurry)) : true
+            filterData.value = allData.value.filter(item => {
+                const blurryMatch = customerParams.value.blurry ? (item.customerName.includes(customerParams.value.blurry)) : true
                 const liaisonMatch = customerParams.value.liaisonName ? (item.liaisonName && item.liaisonName.includes(customerParams.value.liaisonName)) : true
                 const statusMatch = customerParams.value.customerStatusDictValue ? (item.customerStatusDictValue == customerParams.value.customerStatusDictValue) : true
                 const typeMatch = customerParams.value.customerTypeDictValue ? (item.customerTypeDictValue == customerParams.value.customerTypeDictValue) : true
@@ -187,8 +193,8 @@
                 const countryMatch = customerParams.value.country ? (item.country == customerParams.value.country) : true
                 return blurryMatch && liaisonMatch && statusMatch && typeMatch && levelMatch && countryMatch
             })
-            customers.value = filterData.slice(0, 10)
-            total.value = filterData.length
+            customers.value = filterData.value.slice(0, 10)
+            total.value = filterData.value.length
         }
     }
 
@@ -204,10 +210,19 @@
         }
     }
 
+    const handleBtn = (customer) => {
+        if(modalType.value == 'add'){
+            addCustomer(customer)
+        }else{
+            deleteCustomer(customer)
+        }
+    }
+
     const deleteCustomer = (data) => {
-        customers.value = customers.value.filter(item => item.id != data.id)
+        filterData.value = filterData.value.filter(item => item.id != data.id)
+        customers.value = filterData.value.slice((customerParams.value.pageIndex - 1) * customerParams.value.pageSize, customerParams.value.pageIndex * customerParams.value.pageSize)
         allData.value = allData.value.filter(item => item.id != data.id)
-        total.value = allData.value.length
+        total.value = filterData.value.length
         emits('delete', data)
     }
 

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

@@ -254,6 +254,7 @@
     const addMarketingRef = ref()
     const editCampaign = (campaign) => {
         addMarketingRef.value.open(campaign)
+        showCampaignDetailModal.value = false
     }
 
     const refresh = () => {