chengf
2026-02-07 e310dfdc93c20ac0c3b5fcd1a95de298cfce2ae9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
package org.jeecg.modules.demo.contract.controller;
 
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.SerializationUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.undertow.util.Headers;
import jakarta.servlet.http.HttpServletRequest;
import kong.unirest.Unirest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.demo.contract.entity.Contract;
import org.jeecg.modules.demo.contract.entity.ExcelDataDTO;
import org.jeecg.modules.demo.contract.entity.SemanticWord;
import org.jeecg.modules.demo.contract.service.IContractService;
import org.jeecg.modules.demo.contract.service.ISemanticWordService;
import org.jeecg.modules.demo.copywriting.controller.CopywritingAsyncService;
import org.jeecg.modules.demo.copywriting.entity.Copywriting;
import org.jeecg.modules.demo.copywriting.service.ICopywritingService;
import org.jeecg.modules.listener.ExcelDataListener;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.http.HttpResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
/**
 * 适配新Excel列的导入接口控制器
 */
@RestController
@RequestMapping("/api/excel")
@Slf4j
public class ExcelImportController {
 
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISemanticWordService semanticWordService;
    @Autowired
    private IContractService contractService;
    @Autowired
    public ICopywritingService copywritingService;
    /**
     * Excel文件导入接口(适配大类、品牌等五列)
     * @return 导入结果
     */
    @RequiresPermissions("contract:contract:importContract")
    @PostMapping("/importContract")
    public Result<String> importExcel(@RequestPart SemanticWord importParam, @RequestPart MultipartFile file, HttpServletRequest req) {
        // 1. 文件基础校验
        if (file.isEmpty()) {
            return Result.error("上传的文件不能为空");
        }
        String fileName = file.getOriginalFilename();
        if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
            return Result.error("仅支持上传Excel文件(.xlsx/.xls)");
        }
 
        // 2. 解析Excel文件
        ExcelDataListener listener = new ExcelDataListener();
        try {
            EasyExcel.read(file.getInputStream(), ExcelDataDTO.class, listener)
                    .sheet() // 读取第一个sheet(如需指定sheet,可传sheet名称/索引,如.sheet("数据sheet"))
                    .doRead();
 
            // 3. 获取解析后的数据,可执行业务逻辑
            List<ExcelDataDTO> dataList = listener.getDataList();
            dataList.remove(0);
            List<SemanticWord> semanticWords = new ArrayList<>();
            int i = 0;
            for (ExcelDataDTO data : dataList) {
                LambdaQueryWrapper<SemanticWord> sem = new LambdaQueryWrapper<>();
                sem.eq(SemanticWord::getContractId, importParam.getContractId());
                sem.eq(SemanticWord::getWord, data.getLeakWord());
                sem.eq(SemanticWord::getOutWord, data.getSemanticQuestion());
                long count = semanticWordService.count(sem);
                if (count > 0) {
                    i ++;
                } else {
                    SemanticWord copy = new  SemanticWord();
                    BeanUtils.copyProperties(copy, importParam);
                    copy.setContractId(importParam.getContractId());
                    copy.setBrand(data.getBrand());
                    copy.setCategoryOne(data.getCategory());
                    copy.setWord(data.getSemanticQuestion());
                    copy.setOutWord(data.getLeakWord());
                    QueryWrapper qw = new QueryWrapper<SysUser>();
                    qw.eq("realName", data.getCreator());
                    Page result = (Page) sysUserService.queryPageList(req, qw, 2, 1).getResult();
                    if (result.getTotal() != 1) {
                        return Result.error("未查询到用户:" + data.getCreator());
                    }
                    String userId = ((SysUser)(result).getRecords().get(0)).getId();
                    copy.setChanger(userId);
                    semanticWords.add(copy);
                }
            }
            semanticWordService.saveBatch(semanticWords);
            Contract contract = new Contract();
            contract.setId(importParam.getContractId());
            contract.setIsImportStatus("1");
            contractService.updateById(contract);
 
            // 示例:调用Service保存数据(替换为你的实际业务逻辑)
            // excelDataService.saveBatch(dataList);
 
            return Result.ok("Excel导入成功!共导入" + (dataList.size() - i) + "条数据,重复" + i + "条数据");
        } catch (IOException e) {
            log.error("文件读取失败", e);
            return Result.error("文件读取失败:" + e.getMessage());
        } catch (RuntimeException e) {
            log.error("数据解析失败", e);
            return Result.error("数据解析失败:" + e.getMessage());
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
 
 
    @Autowired
    private CopywritingAsyncService copywritingAsyncService;
 
    @RequiresPermissions("contract:contract:batchGenerateCopy")
    @RequestMapping(value = "/batchGenerateCopy", method = RequestMethod.POST)
    public Result<?> batchGenerateCopy(@RequestBody ContractParam cp) {
        if (cp.getContractId().isEmpty()) {
            return Result.error("文案编号不能为空");
        } else if (cp.getFileName().isEmpty()) {
            return Result.error("文件不能为空");
        } else if (cp.getYoushang().isEmpty()) {
            return Result.error("友商不能为空");
        } else if (cp.getAuditor().isEmpty() || cp.getAuditorName().isEmpty()) {
            return Result.error("用户不能为空");
        }
        QueryWrapper<SemanticWord> semanticWordQueryWrapper = new QueryWrapper<>();
        semanticWordQueryWrapper.eq("contract_id", cp.getContractId());
        List<SemanticWord> list = semanticWordService.list(semanticWordQueryWrapper);
        if (list.isEmpty()) {
            return Result.error("该合同不存在语义词");
        } else {
            // 调用异步方法执行实际生成逻辑
            copywritingAsyncService.asyncBatchGenerateCopy(
                    cp.getContractId(), list, cp.getFileName(), cp.getYoushang(),
                    cp.getBenchmarkUrl(),cp.getAuditor(), cp.getAuditorName()
            );
            // 立即返回响应,不等待生成完成
            return Result.OK("开始生成,任务已提交至后台处理");
        }
    }
 
    public static String getRandomElementFromArray(String[] strArray) {
        // 1. 校验数组合法性:空数组/Null直接返回null,避免异常
        if (strArray == null || strArray.length == 0) {
            return null;
        }
        // 2. 创建随机数生成器,生成0到数组长度-1的随机索引
        Random random = new Random();
        int randomIndex = random.nextInt(strArray.length);
        // 3. 根据随机索引返回对应元素
        return strArray[randomIndex];
    }
 
    private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 
    /**
     * 方法1:返回当前时间的完整格式化字符串(yyyy-MM-dd HH:mm:ss)
     * @return 格式化后的时间字符串,如:2026-02-06 20:15:30
     */
    public static String getCurrentTimeStr() {
        return LocalDateTime.now().format(DEFAULT_FORMATTER);
    }
 
    @RequiresPermissions("contract:contract:batchPublish")
    @PostMapping("/batchPublish")
    public Result<String> batchPublish(@RequestParam("contractId") String contractId) {
        if (contractId.isEmpty()) {
            return Result.error("合同编号不能为空!");
        }
        String[] arr = new String[]{"14457","28879","20838"};
        QueryWrapper<Copywriting> wrapper = new QueryWrapper<>();
// 手动拼接 LEFT JOIN 和筛选条件
        wrapper.select("copywriting.*")
                .inSql("word_id",  // 使用正确的关联字段 word_id
                        "SELECT id FROM semantic_word WHERE contract_id = '" + contractId + "'");
        wrapper.isNull("order_nid");
        wrapper.eq("status",3);
        List<Copywriting> copywritingList = copywritingService.list(wrapper);
        if (copywritingList.isEmpty()) {
            return Result.error("该合同不存在状态为审核可发稿的文案");
        }
        for (Copywriting copywriting : copywritingList) {
            kong.unirest.HttpResponse<String> response = Unirest.post("http://8.138.187.158:8082/api/media/send")
                    .field("api_key", "sk_4c8f6a970de896e232909e2959254441")
                    .field("resource_id", getRandomElementFromArray(arr))
                    .field("title", copywriting.getTitle())
                    .field("content", copywriting.getText())
                    .field("remark", getCurrentTimeStr())
                    .field("third_id", copywriting.getCreateBy())
                    .asString();
            // 1. 校验响应状态和响应体非空
            if (response != null && response.getStatus() == 200 && StringUtils.isNotBlank(response.getBody())) {
                // 2. 解析JSON响应体
                JSONObject responseJson = JSON.parseObject(response.getBody());
 
                // 3. 校验code是否为1(投稿成功),再提取order_nid
                if (responseJson.getInteger("code") == 1) {
                    JSONObject dataObj = responseJson.getJSONObject("data");
                    if (dataObj != null && dataObj.containsKey("order_nid")) {
                        // 获取order_nid(转为String,适配Copywriting的orderNid字段类型)
                        String orderNid = dataObj.get("order_nid").toString();
 
                        // 4. 赋值并更新数据库
                        copywriting.setOrderNid(orderNid);
                        copywriting.setStatus("4");
                        copywritingService.updateById(copywriting);
                    } else {
                        // 日志记录:响应体无data或order_nid字段
                        System.err.println("投稿成功但未获取到order_nid,响应体:" + response.getBody());
                    }
                } else {
                    // 日志记录:接口返回非成功状态
                    System.err.println("投稿失败,响应体:" + response.getBody());
                }
            }
        }
        return Result.ok("批量投稿成功!");
    }
}