Przeglądaj źródła

投诉功能开发

xucaiqin 1 tydzień temu
rodzic
commit
16a531378e

+ 178 - 1
sckw-modules/sckw-system/src/main/java/com/sckw/system/controller/KwsComplaintController.java

@@ -4,6 +4,7 @@ import com.sckw.core.web.response.BaseResult;
 import com.sckw.core.web.response.result.PageDataResult;
 import com.sckw.system.model.vo.req.ComplaintManagePageReqVo;
 import com.sckw.system.model.vo.req.ComplaintProcessReqVo;
+import com.sckw.system.model.vo.req.ComplaintAppSubmitReqVo;
 import com.sckw.system.model.vo.res.ComplaintDetailResVo;
 import com.sckw.system.model.vo.res.ComplaintManageItemResVo;
 import com.sckw.system.service.KwsComplaintService;
@@ -39,6 +40,182 @@ public class KwsComplaintController {
         return BaseResult.success(kwsComplaintService.processComplaint(reqVo));
     }
 
+    @GetMapping(value = "/scan", produces = "text/html;charset=UTF-8")
+    public String scanPage() {
+        return """
+                <!doctype html>
+                <html lang="zh-CN">
+                <head>
+                  <meta charset="utf-8" />
+                  <meta name="viewport" content="width=device-width, initial-scale=1" />
+                  <title>提交投诉</title>
+                  <style>
+                    :root { --primary:#1677ff; --bg:#f5f7fb; --card:#fff; --text:#1f2329; --muted:#646a73; --border:#e5e6eb; }
+                    *{ box-sizing:border-box; }
+                    body{ margin:0; font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue","PingFang SC","Microsoft YaHei",Arial; background:var(--bg); color:var(--text); }
+                    .wrap{ max-width:560px; margin:0 auto; padding:18px 14px 28px; }
+                    .card{ background:var(--card); border:1px solid var(--border); border-radius:12px; padding:16px; }
+                    h1{ font-size:18px; margin:0 0 14px; }
+                    .field{ margin:12px 0; }
+                    .label{ font-size:13px; color:var(--muted); margin:0 0 6px; }
+                    .req{ color:#f53f3f; margin-left:4px; }
+                    select,input,textarea{ width:100%; border:1px solid var(--border); border-radius:10px; padding:12px; font-size:14px; outline:none; background:#fff; }
+                    textarea{ min-height:110px; resize:vertical; }
+                    .upload{ border:1px dashed var(--border); border-radius:10px; padding:14px; text-align:center; color:var(--muted); }
+                    .upload input{ padding:10px; }
+                    .row{ display:flex; gap:12px; }
+                    .row .btn{ flex:1; }
+                    .btn{ border-radius:10px; padding:12px; font-size:14px; border:1px solid var(--border); background:#fff; cursor:pointer; }
+                    .btn.primary{ background:var(--primary); color:#fff; border-color:var(--primary); }
+                    .hint{ font-size:12px; color:var(--muted); margin-top:8px; }
+                    .status{ font-size:12px; color:var(--muted); margin-top:8px; min-height:16px; }
+                    .preview{ margin-top:10px; display:none; }
+                    .preview img{ width:100%; border-radius:10px; border:1px solid var(--border); }
+                  </style>
+                </head>
+                <body>
+                <div class="wrap">
+                  <div class="card">
+                    <h1>提交投诉</h1>
+                    <div class="field">
+                      <div class="label">投诉类型<span class="req">*</span></div>
+                      <select id="typeCode">
+                        <option value="1">违规</option>
+                        <option value="2" selected>服务态度</option>
+                        <option value="3">其他</option>
+                      </select>
+                    </div>
+                    <div class="field">
+                      <div class="label">投诉对象<span class="req">*</span></div>
+                      <input id="targetName" placeholder="请输入投诉对象姓名" />
+                    </div>
+                    <div class="field">
+                      <div class="label">投诉内容<span class="req">*</span></div>
+                      <textarea id="content" placeholder="请详细描述投诉内容"></textarea>
+                    </div>
+                    <div class="field">
+                      <div class="label">发生时间<span class="req">*</span></div>
+                      <input id="occurTime" type="datetime-local" />
+                    </div>
+                    <div class="field">
+                      <div class="label">上传图片</div>
+                      <div class="upload">
+                        <input id="file" type="file" accept="image/*" />
+                        <div class="hint">支持上传1张图片</div>
+                        <div class="status" id="uploadStatus"></div>
+                        <div class="preview" id="preview"><img id="previewImg" alt="预览" /></div>
+                      </div>
+                    </div>
+                    <div class="row">
+                      <button class="btn" id="resetBtn" type="button">取消</button>
+                      <button class="btn primary" id="submitBtn" type="button">提交投诉</button>
+                    </div>
+                  </div>
+                </div>
+                <script>
+                  const state = { fileUrl: "", fileName: "", fileType: "", fileSize: 0 };
+                  function pad(n){ return n<10 ? "0"+n : ""+n; }
+                  function initDate(){
+                    const d = new Date();
+                    const v = d.getFullYear()+"-"+pad(d.getMonth()+1)+"-"+pad(d.getDate())+" "+pad(d.getHours())+":"+pad(d.getMinutes());
+                    document.getElementById("occurTime").value = v;
+                  }
+                  initDate();
+                
+                  async function uploadFile(file){
+                    const statusEl = document.getElementById("uploadStatus");
+                    statusEl.textContent = "上传中...";
+                    const fd = new FormData();
+                    fd.append("file", file);
+                    const resp = await fetch("/sckw-ng-file/file/appUploadFileInfo", { method:"POST", body: fd });
+                    const json = await resp.json();
+                    if (!(json && (json.code === 200 || json.code === 60200))) {
+                      throw new Error((json && json.msg) ? json.msg : "上传失败");
+                    }
+                    const data = json.data || {};
+                    const filePath = data.fileAbsolutePath || "";
+                    if (!filePath) {
+                      throw new Error("上传成功但未返回文件路径");
+                    }
+                    state.fileUrl = filePath;
+                    state.fileName = file.name || (data.fileOriginalName || "");
+                    state.fileType = file.type || "";
+                    state.fileSize = file.size || 0;
+                    statusEl.textContent = "上传成功";
+                    const preview = document.getElementById("preview");
+                    const img = document.getElementById("previewImg");
+                    img.src = filePath.startsWith("http") ? filePath : (location.origin + "/" + filePath.replace(/^\\/+/, ""));
+                    preview.style.display = "block";
+                  }
+                
+                  document.getElementById("file").addEventListener("change", async (e) => {
+                    const file = e.target.files && e.target.files[0];
+                    if (!file) return;
+                    try {
+                      await uploadFile(file);
+                    } catch (err) {
+                      state.fileUrl = "";
+                      document.getElementById("uploadStatus").textContent = err && err.message ? err.message : "上传失败";
+                      document.getElementById("preview").style.display = "none";
+                    }
+                  });
+                
+                  document.getElementById("resetBtn").addEventListener("click", () => {
+                    document.getElementById("typeCode").value = "2";
+                    document.getElementById("targetName").value = "";
+                    document.getElementById("content").value = "";
+                    initDate();
+                    document.getElementById("file").value = "";
+                    document.getElementById("uploadStatus").textContent = "";
+                    document.getElementById("preview").style.display = "none";
+                    state.fileUrl = ""; state.fileName=""; state.fileType=""; state.fileSize=0;
+                  });
+                
+                  document.getElementById("submitBtn").addEventListener("click", async () => {
+                    const typeCode = parseInt(document.getElementById("typeCode").value, 10);
+                    const targetName = (document.getElementById("targetName").value || "").trim();
+                    const content = (document.getElementById("content").value || "").trim();
+                    const occurTime = document.getElementById("occurTime").value;
+                    if (!typeCode) { alert("请选择投诉类型"); return; }
+                    if (!targetName) { alert("请输入投诉对象"); return; }
+                    if (!content) { alert("请输入投诉内容"); return; }
+                    if (!occurTime) { alert("请选择发生时间"); return; }
+                
+                    const body = {
+                      typeCode,
+                      targetName,
+                      content,
+                      occurTime: occurTime.length === 16 ? (occurTime + ":00") : occurTime,
+                      isAnonymous: true,
+                      fileUrl: state.fileUrl || "",
+                      fileName: state.fileName || "",
+                      fileType: state.fileType || "",
+                      fileSize: state.fileSize || 0
+                    };
+                
+                    const resp = await fetch("/sckw-ng-system/kwsComplaint/scan/submit", {
+                      method:"POST",
+                      headers: { "Content-Type":"application/json" },
+                      body: JSON.stringify(body)
+                    });
+                    const json = await resp.json();
+                    if (json && json.code === 60200) {
+                      alert("提交成功");
+                      document.getElementById("resetBtn").click();
+                      return;
+                    }
+                    alert((json && (json.message || json.msg)) ? (json.message || json.msg) : "提交失败");
+                  });
+                </script>
+                </body>
+                </html>
+                """;
+    }
 
-}
+    @PostMapping("/scan/submit")
+    public BaseResult<ComplaintDetailResVo> scanSubmit(@RequestBody @Valid ComplaintAppSubmitReqVo reqVo) {
+        return BaseResult.success(kwsComplaintService.submitScanComplaint(reqVo));
+    }
 
+
+}

+ 45 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/service/KwsComplaintService.java

@@ -90,6 +90,51 @@ public class KwsComplaintService {
         return buildComplaintDetail(complaint, true);
     }
 
+    @Transactional(rollbackFor = Exception.class)
+    public ComplaintDetailResVo submitScanComplaint(ComplaintAppSubmitReqVo reqVo) {
+        LocalDateTime now = LocalDateTime.now();
+
+        TComplaint complaint = new TComplaint();
+        complaint.setComplaintNo(buildComplaintNo(now));
+        complaint.setChannel(2);
+        complaint.setTypeCode(reqVo.getTypeCode());
+        complaint.setTargetName(reqVo.getTargetName());
+        complaint.setSubmitterId(null);
+        complaint.setSubmitterName(null);
+        complaint.setIsAnonymous(true);
+        complaint.setContent(reqVo.getContent());
+        complaint.setStatus(0);
+        complaint.setOccurTime(reqVo.getOccurTime());
+
+        complaint.setCreateBy(0L);
+        complaint.setCreateTime(now);
+        complaint.setDelFlag(Global.UN_DELETED);
+
+        if (!tComplaintService.save(complaint)) {
+            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, "提交投诉失败");
+        }
+
+        if (StrUtil.isNotBlank(reqVo.getFileUrl())) {
+            TComplaintAttachment attachment = new TComplaintAttachment();
+            attachment.setComplaintId(complaint.getId());
+            attachment.setFileUrl(reqVo.getFileUrl());
+            attachment.setFileName(reqVo.getFileName());
+            attachment.setFileType(reqVo.getFileType());
+            attachment.setFileSize(reqVo.getFileSize());
+            attachment.setSortNo(1);
+            attachment.setCreateBy(0L);
+            attachment.setCreateTime(now);
+            attachment.setUpdateBy(0L);
+            attachment.setUpdateTime(now);
+            attachment.setDelFlag(Global.UN_DELETED);
+            if (!tComplaintAttachmentService.save(attachment)) {
+                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, "保存投诉附件失败");
+            }
+        }
+
+        return buildComplaintDetail(complaint, true);
+    }
+
     public PageDataResult<ComplaintAppItemResVo> appComplaintPage(ComplaintAppListReqVo reqVo) {
         Page<TComplaint> page = new Page<>(reqVo.getPageNum(), reqVo.getPageSize());
         LambdaQueryWrapper<TComplaint> wrapper = new LambdaQueryWrapper<>();