lsw преди 1 година
родител
ревизия
bfd20f5992

+ 1 - 2
admin-ui/src/components/FileUpload/index.vue

@@ -15,7 +15,7 @@
       ref="fileUpload"
     >
       <!-- 上传按钮 -->
-      <el-button size="mini" type="primary">选取文件</el-button>
+      <el-button icon="el-icon-upload" type="primary">选取文件</el-button>
       <!-- 上传提示 -->
       <div class="el-upload__tip" slot="tip" v-if="showTip">
         请上传
@@ -24,7 +24,6 @@
         的文件
       </div>
     </el-upload>
-
     <!-- 文件列表 -->
     <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
       <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">

+ 30 - 46
admin-ui/src/views/work/contract/edit.vue

@@ -1,38 +1,19 @@
 <template>
   <div class="cmain">
-      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
-        <el-form-item label="合同名称" prop="name">
-          <el-input v-model="form.name" placeholder="请输入合同名称" clearable/>
-        </el-form-item>
-        <el-form-item label="合同路径" prop="url">
-          <el-input v-model="form.url" placeholder="请输入合同路径" clearable/>
-        </el-form-item>
-        <el-form-item label="状态" prop="state">
-          <el-input v-model="form.state" placeholder="请输入状态" clearable/>
-        </el-form-item>
-        <el-form-item label="创建者" prop="createBy">
-          <el-input v-model="form.createBy" placeholder="请输入创建者" clearable/>
-        </el-form-item>
-        <el-form-item label="创建时间" prop="createTime">
-          <el-date-picker clearable
-            v-model="form.createTime"
-            type="date"
-            value-format="yyyy-MM-dd"
-            placeholder="请选择创建时间">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="更新者" prop="updateBy">
-          <el-input v-model="form.updateBy" placeholder="请输入更新者" clearable/>
-        </el-form-item>
-        <el-form-item label="更新时间" prop="updateTime">
-          <el-date-picker clearable
-            v-model="form.updateTime"
-            type="date"
-            value-format="yyyy-MM-dd"
-            placeholder="请选择更新时间">
-          </el-date-picker>
-        </el-form-item>
-      </el-form>
+    <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+      <el-form-item label="合同名称" prop="name">
+        <el-input v-model="form.name" placeholder="请输入合同名称" clearable />
+      </el-form-item>
+      <el-form-item label="合同状态" prop="state">
+        <el-select v-model="form.state" placeholder="请选择">
+          <el-option label="启用" :value="0"></el-option>
+          <el-option label="关闭" :value="1"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="上传合同">
+        <file-upload v-model="form.url" :accept="'.doc, .docx, .pdf'" :fileSize="20" :limit="1" />
+      </el-form-item>
+    </el-form>
     <div class="mfooter">
       <el-button type="primary" @click="submitForm">确 定</el-button>
       <el-button @click="$layer.close(layerid)">取 消</el-button>
@@ -44,8 +25,11 @@
 export default {
   data() {
     return {
-      form: {},
+      form: { state: 0 },
       rules: {
+        name: [{ required: true, message: '不能为空', trigger: 'blur' }],
+        state: [{ required: true, message: '不能为空', trigger: 'blur' }],
+        url: [{ required: true, message: '不能为空', trigger: 'blur' }]
       }
     };
   },
@@ -62,27 +46,27 @@ export default {
   },
   mounted() {
     if (this.param.id) {
-      this.ajax({ url: '/work/contract/detail/' + this.param.id }).then(response => {
+      this.ajax({ url: '/work/contract/detail/' + this.param.id }).then((response) => {
         this.form = response.data;
       });
     }
   },
   methods: {
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs['form'].validate((valid) => {
         if (valid) {
           if (this.form.id) {
-              this.ajax({method: 'post',url: '/work/contract/edit', data: this.form }).then(response => {
-                  this.$modal.msgSuccess("修改成功");
-                  this.$layer.close(this.layerid);
-                  this.$parent.getList();
-              });
+            this.ajax({ method: 'post', url: '/work/contract/edit', data: this.form }).then((response) => {
+              this.$modal.msgSuccess('修改成功');
+              this.$layer.close(this.layerid);
+              this.$parent.getList();
+            });
           } else {
-              this.ajax({method: 'post',url: '/work/contract/add', data: this.form }).then(response => {
-                  this.$modal.msgSuccess("新增成功");
-                  this.$layer.close(this.layerid);
-                  this.$parent.getList();
-               });
+            this.ajax({ method: 'post', url: '/work/contract/add', data: this.form }).then((response) => {
+              this.$modal.msgSuccess('新增成功');
+              this.$layer.close(this.layerid);
+              this.$parent.getList();
+            });
           }
         }
       });

+ 36 - 39
admin-ui/src/views/work/contract/index.vue

@@ -2,13 +2,7 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent v-show="showSearch">
       <el-form-item label="合同名称" prop="name">
-        <el-input v-model="queryParams.name" placeholder="请输入合同名称"  @keyup.enter.native="handleQuery" clearable class="inp"/>
-      </el-form-item>
-      <el-form-item label="合同路径" prop="url">
-        <el-input v-model="queryParams.url" placeholder="请输入合同路径"  @keyup.enter.native="handleQuery" clearable class="inp"/>
-      </el-form-item>
-      <el-form-item label="状态" prop="state">
-        <el-input v-model="queryParams.state" placeholder="请输入状态"  @keyup.enter.native="handleQuery" clearable class="inp"/>
+        <el-input v-model="queryParams.name" placeholder="请输入合同名称" @keyup.enter.native="handleQuery" clearable />
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
@@ -16,40 +10,43 @@
       </el-form-item>
     </el-form>
     <el-row :gutter="10" class="mb8">
-        <el-button type="primary" icon="el-icon-plus" :disabled="ids.length > 0" @click="op('add')" v-hasPermi="['work:contract:add']">新增</el-button>
-        <el-button type="success" icon="el-icon-edit" :disabled="ids.length != 1" @click="op('edit',ids)" v-hasPermi="['work:contract:edit']">修改</el-button>
-        <el-button type="danger" icon="el-icon-delete" :disabled="ids.length == 0" @click="del" v-hasPermi="['work:contract:remove']">删除{{ids.length>0?'('+ids.length+')':''}}</el-button>
-        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <el-button type="primary" icon="el-icon-plus" :disabled="ids.length > 0" @click="op('add')" v-hasPermi="['work:contract:add']">新增</el-button>
+      <el-button type="success" icon="el-icon-edit" :disabled="ids.length != 1" @click="op('edit', ids)" v-hasPermi="['work:contract:edit']">修改</el-button>
+      <el-button type="danger" icon="el-icon-delete" :disabled="ids.length == 0" @click="del" v-hasPermi="['work:contract:remove']">删除{{ ids.length > 0 ? '(' + ids.length + ')' : '' }}</el-button>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-
     <el-table :data="response.rows" border @selection-change="selects" height="calc(100vh - 270px)">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="id" align="center" prop="id" />
-      <el-table-column label="合同名称" align="center" prop="name" />
-      <el-table-column label="合同路径" align="center" prop="url" />
-      <el-table-column label="状态" align="center" prop="state" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="合同名称" align="left" prop="name" />
+      <el-table-column label="合同状态" align="center" prop="state" width="130">
         <template slot-scope="scope">
-          <el-button size="mini" type="text" icon="el-icon-edit" @click="op('edit',scope.row)" v-hasPermi="['work:contract:edit']">修改</el-button>
+          <el-tag type="success" v-if="scope.row.state == 0">启用</el-tag>
+          <el-tag type="danger" v-if="scope.row.state == 1">停用</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="200" />
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="op('edit', scope.row)" v-hasPermi="['work:contract:edit']">修改</el-button>
           <el-button size="mini" type="text" icon="el-icon-delete" @click="del(scope.row)" v-hasPermi="['work:contract:remove']">删除</el-button>
         </template>
       </el-table-column>
       <template slot="empty">
-          <el-empty></el-empty>
+        <el-empty></el-empty>
       </template>
     </el-table>
-    <pagination v-if="response.total>0" :total="response.total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
+    <pagination v-if="response.total > 0" :total="response.total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
   </div>
 </template>
 
 <script>
-import edit from './edit'
+import edit from './edit';
 export default {
-  name: "Contract",
+  name: 'Contract',
   data() {
     return {
       ids: [],
-      showSearch:true,
+      showSearch: true,
       response: {},
       queryParams: {
         pageNum: 1,
@@ -67,8 +64,8 @@ export default {
   },
   methods: {
     getList() {
-      this.ajax({ url: '/work/contract/list', data: this.queryParams }).then(response => {
-            this.response = response;
+      this.ajax({ url: '/work/contract/list', data: this.queryParams }).then((response) => {
+        this.response = response;
       });
     },
     handleQuery() {
@@ -76,28 +73,28 @@ export default {
       this.getList();
     },
     resetQuery() {
-      this.resetForm("queryForm");
+      this.resetForm('queryForm');
       this.handleQuery();
     },
     selects(rows) {
-      this.ids = rows.map(item => item.id)
+      this.ids = rows.map((item) => item.id);
     },
     op(tag, row) {
-          if (tag == 'add') {
-            this.iframe({ obj: edit, param: {}, title:'新增',width: '45%', height: '55%'});
-          }
-          if (tag == 'edit') {
-              const id = row.id || this.ids[0];
-              this.iframe({ obj: edit, param: {id: id}, title:'编辑',width: '50%', height: '50%'});
-          }
+      if (tag == 'add') {
+        this.iframe({ obj: edit, param: {}, title: '新增合同', width: '35%', height: '40%' });
+      }
+      if (tag == 'edit') {
+        const id = row.id || this.ids[0];
+        this.iframe({ obj: edit, param: { id: id }, title: '编辑合同', width: '35%', height: '40%' });
+      }
     },
     del(row) {
-        this.$confirm('是否确认删除选中数据?', '警告', { type: 'warning' }).then(() => {
-        this.get({ url: '/work/contract/remove/' + (row.id || this.ids) }).then(response => {
-                this.$modal.msgSuccess('删除成功');
-                this.getList();
-            });
+      this.$confirm('是否确认删除选中数据?', '警告', { type: 'warning' }).then(() => {
+        this.get({ url: '/work/contract/remove/' + (row.id || this.ids) }).then((response) => {
+          this.$modal.msgSuccess('删除成功');
+          this.getList();
         });
+      });
     }
   }
 };

+ 14 - 0
app/components/card/card.vue

@@ -23,6 +23,9 @@ export default {
 		value: {
 			type: String
 		},
+		side: {
+			type: String
+		},
 		read: {
 			type: Boolean,
 			default: false
@@ -62,6 +65,7 @@ export default {
 								if (data.code == 200) {
 									this.fileName = data.fileName;
 									this.$emit('input', data.fileName);
+									this.ocr({ imageUrl: 'http://123.60.57.26/api/profile/upload/2024/04/22/1713726675590.jpg', side: this.side });
 								} else {
 									uni.showModal({ content: data.msg, showCancel: false });
 								}
@@ -76,6 +80,16 @@ export default {
 				}
 			});
 		},
+		ocr(item) {
+			this.http.request({
+				url: '/app/common/ocr',
+				data: item,
+				method: 'POST',
+				success: (res) => {
+					this.$emit('success', { side: this.side, data: res.data.data });
+				}
+			});
+		},
 		// 预览图片
 		preview(item) {
 			uni.previewImage({

+ 34 - 11
app/pages/authentication/index.vue

@@ -9,7 +9,18 @@
 			<text>为保障资金安全,用户需进行实名认证,请务必认真填写</text>
 		</view>
 		<view class="main">
-			<view class="form">
+			<view v-if="step === 1">
+				<u-divider text="本人二代身份证"></u-divider>
+				<view class="r">
+					<view class="r50">
+						<card v-model="item.p1" text="点击拍摄/上传人像面" icon="&#xe690;" :read="item.isAuthentication === 1" side="face" @success="success"></card>
+					</view>
+					<view class="r50">
+						<card v-model="item.p2" text="点击拍摄/上传国徽面" icon="&#xe61f;" :read="item.isAuthentication === 1" side="back"></card>
+					</view>
+				</view>
+			</view>
+			<view class="form" v-else>
 				<view class="form_group">
 					<view class="lable re">姓名</view>
 					<input type="text" placeholder="请输入姓名" v-model="item.name" :disabled="item.isAuthentication === 1" />
@@ -19,16 +30,8 @@
 					<input type="text" placeholder="请输入姓名" v-model="item.idCard" :disabled="item.isAuthentication === 1" />
 				</view>
 			</view>
-			<u-divider text="本人二代身份证"></u-divider>
-			<view class="r">
-				<view class="r50">
-					<card v-model="item.p1" text="点击拍摄/上传人像面" icon="&#xe690;" :read="item.isAuthentication === 1"></card>
-				</view>
-				<view class="r50">
-					<card v-model="item.p2" text="点击拍摄/上传国徽面" icon="&#xe61f;" :read="item.isAuthentication === 1"></card>
-				</view>
-			</view>
-			<button class="btn" @click="save()" v-if="item.isAuthentication != 1">确定</button>
+			<button class="btn" @click="next()" v-if="step === 1">下一步</button>
+			<button class="btn" @click="save()" v-if="step === 2 && item.isAuthentication != 1">确定</button>
 		</view>
 	</view>
 </template>
@@ -37,6 +40,7 @@
 export default {
 	data() {
 		return {
+			step: 1,
 			item: {}
 		};
 	},
@@ -53,6 +57,25 @@ export default {
 				}
 			});
 		},
+		success(res) {
+			if (res.side == 'face') {
+				this.item.name = res.data.name;
+				this.item.idCard = res.data.num;
+				this.item.sex = res.data.sex;
+				this.item.address = res.data.address;
+				this.item.nationality = res.data.nationality;
+				this.item.birth = res.data.birth;
+			} else {
+				this.item.endDate = res.data.end_date;
+			}
+		},
+		next() {
+			if (!this.item.p1 && !this.item.p2) {
+				uni.showModal({ content: '请先上传证件照', showCancel: false });
+				return;
+			}
+			this.step = 2;
+		},
 		save() {
 			let rule = [
 				{ name: 'name', checkType: 'notnull', errorMsg: '请输入姓名' },

+ 9 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/work/api/Api_CommonController.java

@@ -12,13 +12,13 @@ import com.ruoyi.common.utils.file.FileUtils;
 import com.ruoyi.common.utils.sign.Base64;
 import com.ruoyi.common.utils.uuid.IdUtils;
 import com.ruoyi.web.work.api.config.BaseController;
+import com.ruoyi.web.work.api.util.AppUtil;
+import com.ruoyi.web.work.domain.dto.OcrDto;
 import com.ruoyi.web.work.service.IUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.FastByteArrayOutputStream;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartHttpServletRequest;
 
 import javax.annotation.Resource;
@@ -69,6 +69,11 @@ public class Api_CommonController extends BaseController {
         }
     }
 
+    @PostMapping("/ocr")
+    public AjaxResult ocr(@Validated @RequestBody OcrDto dto) {
+        return AjaxResult.success(AppUtil.idCard(dto.getImageUrl(), dto.getSide()));
+    }
+
     //图形验证码
     @GetMapping("/captcha")
     public AjaxResult captcha() {

+ 50 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/api/util/AppUtil.java

@@ -1,10 +1,17 @@
 package com.ruoyi.web.work.api.util;
 
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.HttpUtils;
 import com.ruoyi.web.work.domain.User;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
 
 public class AppUtil {
     public static User getUser() {
@@ -12,4 +19,47 @@ public class AppUtil {
         HttpServletRequest request = sra.getRequest();
         return (User) request.getAttribute("user");
     }
+    /**
+     * 身份证OCR文字识别
+     *
+     * @param imgUrl
+     * @param side
+     * @return
+     */
+    public static JSONObject idCard(String imgUrl, String side) {
+        String host = "https://cardnumber.market.alicloudapi.com";
+        String path = "/rest/160601/ocr/ocr_idcard.json";
+        String appcode = "afda0d1b5d984f3bad99a2b362ec9285";
+        Map<String, String> headers = new HashMap<String, String>();
+        headers.put("Authorization", "APPCODE " + appcode);
+        //根据API的要求,定义相对应的Content-Type
+        headers.put("Content-Type", "application/json; charset=UTF-8");
+        Map<String, String> query = new HashMap<String, String>();
+        //configure配置
+        JSONObject configObj = new JSONObject();
+        configObj.put("side", side);
+        String config_str = configObj.toString();
+        // 拼装请求body的json字符串
+        JSONObject requestObj = new JSONObject();
+        requestObj.put("image", imgUrl);
+        if (configObj.size() > 0) {
+            requestObj.put("configure", config_str);
+        }
+        String body = requestObj.toString();
+        try {
+            HttpResponse response = HttpUtils.doPost(host, path, "POST", headers, query, body);
+            int stat = response.getStatusLine().getStatusCode();
+            if (stat != 200) {
+                System.out.println("Http code: " + stat);
+                System.out.println("http header error msg: " + response.getFirstHeader("X-Ca-Error-Message"));
+                System.out.println("Http body error msg:" + EntityUtils.toString(response.getEntity()));
+                return null;
+            }
+            String res = EntityUtils.toString(response.getEntity());
+            return JSON.parseObject(res);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
 }

+ 13 - 16
ruoyi-admin/src/main/java/com/ruoyi/web/work/controller/ContractController.java

@@ -1,25 +1,22 @@
 package com.ruoyi.web.work.controller;
 
-import java.util.Arrays;
-import java.util.List;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.web.work.domain.Contract;
 import com.ruoyi.web.work.service.IContractService;
-import com.ruoyi.common.core.page.TableDataInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * 合同模板
+ *
  * @author lsw
  * @date 2024-04-22
  */
@@ -31,7 +28,7 @@ public class ContractController extends BaseController {
 
     @PreAuthorize("@ss.hasPermi('work:contract:list')")
     @GetMapping("/list")
-    public TableDataInfo list(Contract contract){
+    public TableDataInfo list(Contract contract) {
         startPage();
         List<Contract> list = contractService.selectList(contract);
         return getDataTable(list);
@@ -39,28 +36,28 @@ public class ContractController extends BaseController {
 
     @PreAuthorize("@ss.hasPermi('work:contract:query')")
     @GetMapping(value = "/detail/{id}")
-    public AjaxResult detail(@PathVariable("id") Long id){
+    public AjaxResult detail(@PathVariable("id") Long id) {
         return AjaxResult.success(contractService.getById(id));
     }
 
     @PreAuthorize("@ss.hasPermi('work:contract:add')")
     @Log(title = "合同模板", businessType = BusinessType.INSERT)
     @PostMapping("/add")
-    public AjaxResult add(@RequestBody Contract contract){
+    public AjaxResult add(@RequestBody Contract contract) {
         return toAjax(contractService.save(contract));
     }
 
     @PreAuthorize("@ss.hasPermi('work:contract:edit')")
     @Log(title = "合同模板", businessType = BusinessType.UPDATE)
     @PostMapping("/edit")
-    public AjaxResult edit(@RequestBody Contract contract){
+    public AjaxResult edit(@RequestBody Contract contract) {
         return toAjax(contractService.updateById(contract));
     }
 
     @PreAuthorize("@ss.hasPermi('work:contract:remove')")
     @Log(title = "合同模板", businessType = BusinessType.DELETE)
     @GetMapping("/remove/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids){
+    public AjaxResult remove(@PathVariable Long[] ids) {
         return toAjax(contractService.removeByIds(Arrays.asList(ids)));
     }
 }

+ 15 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/OcrDto.java

@@ -0,0 +1,15 @@
+package com.ruoyi.web.work.domain.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class OcrDto {
+
+    @NotBlank(message = "参数不能为空")
+    private String imageUrl;
+
+    @NotBlank(message = "参数不能为空")
+    private String side;
+}

+ 0 - 2
ruoyi-admin/src/main/resources/mapper/work/ContractMapper.xml

@@ -8,8 +8,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select * from tb_contract
         <where>  
             <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
-            <if test="url != null  and url != ''"> and url = #{url}</if>
-            <if test="state != null "> and state = #{state}</if>
         </where>
     </select>
 

+ 51 - 0
ruoyi-admin/src/test/java/com/ruoyi/user.java

@@ -1,9 +1,14 @@
 package com.ruoyi;
 
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.HttpUtils;
 import com.ruoyi.web.work.domain.Notice;
 import com.ruoyi.web.work.domain.Relate;
 import com.ruoyi.web.work.service.INoticeService;
 import com.ruoyi.web.work.service.IRelateService;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -11,6 +16,9 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.HashMap;
+import java.util.Map;
+
 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = RuoYiApplication.class)
 public class user {
@@ -35,4 +43,47 @@ public class user {
 
         System.out.println("操作成功");
     }
+
+    @Test
+    public void tt() {
+        String host = "https://cardnumber.market.alicloudapi.com";
+        String path = "/rest/160601/ocr/ocr_idcard.json";
+        String appcode = "afda0d1b5d984f3bad99a2b362ec9285";
+        String method = "POST";
+        Map<String, String> headers = new HashMap<String, String>();
+        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
+        headers.put("Authorization", "APPCODE " + appcode);
+        //根据API的要求,定义相对应的Content-Type
+        headers.put("Content-Type", "application/json; charset=UTF-8");
+        Map<String, String> querys = new HashMap<String, String>();
+        // 对图像进行base64编码
+        String imgBase64 = "http://123.60.57.26/api/profile/upload/2024/04/22/1713726675590.jpg";
+        //configure配置
+        JSONObject configObj = new JSONObject();
+        configObj.put("side", "face");
+        String config_str = configObj.toString();
+        // 拼装请求body的json字符串
+        JSONObject requestObj = new JSONObject();
+        requestObj.put("image", imgBase64);
+        if (configObj.size() > 0) {
+            requestObj.put("configure", config_str);
+        }
+        String bodys = requestObj.toString();
+
+        try {
+            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
+            int stat = response.getStatusLine().getStatusCode();
+            if (stat != 200) {
+                System.out.println("Http code: " + stat);
+                System.out.println("http header error msg: " + response.getFirstHeader("X-Ca-Error-Message"));
+                System.out.println("Http body error msg:" + EntityUtils.toString(response.getEntity()));
+                return;
+            }
+            String res = EntityUtils.toString(response.getEntity());
+            JSONObject res_obj = JSON.parseObject(res);
+            System.out.println(res_obj.toJSONString());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 }

+ 288 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/HttpUtils.java

@@ -0,0 +1,288 @@
+package com.ruoyi.common.utils;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class HttpUtils {
+
+    /**
+     * get
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doGet(String host, String path, String method, Map<String, String> headers, Map<String, String> querys) throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpGet request = new HttpGet(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * post form
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param bodys
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, Map<String, String> bodys) throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPost request = new HttpPost(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (bodys != null) {
+            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
+
+            for (String key : bodys.keySet()) {
+                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
+            }
+            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
+            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
+            request.setEntity(formEntity);
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Post String
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, String body) throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPost request = new HttpPost(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (StringUtils.isNotBlank(body)) {
+            request.setEntity(new StringEntity(body, "utf-8"));
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Post stream
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, byte[] body) throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPost request = new HttpPost(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (body != null) {
+            request.setEntity(new ByteArrayEntity(body));
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Put String
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPut(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, String body) throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPut request = new HttpPut(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (StringUtils.isNotBlank(body)) {
+            request.setEntity(new StringEntity(body, "utf-8"));
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Put stream
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPut(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, byte[] body) throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPut request = new HttpPut(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (body != null) {
+            request.setEntity(new ByteArrayEntity(body));
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Delete
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doDelete(String host, String path, String method, Map<String, String> headers, Map<String, String> querys) throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        return httpClient.execute(request);
+    }
+
+    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
+        StringBuilder sbUrl = new StringBuilder();
+        sbUrl.append(host);
+        if (!StringUtils.isBlank(path)) {
+            sbUrl.append(path);
+        }
+        if (null != querys) {
+            StringBuilder sbQuery = new StringBuilder();
+            for (Map.Entry<String, String> query : querys.entrySet()) {
+                if (0 < sbQuery.length()) {
+                    sbQuery.append("&");
+                }
+                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
+                    sbQuery.append(query.getValue());
+                }
+                if (!StringUtils.isBlank(query.getKey())) {
+                    sbQuery.append(query.getKey());
+                    if (!StringUtils.isBlank(query.getValue())) {
+                        sbQuery.append("=");
+                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
+                    }
+                }
+            }
+            if (0 < sbQuery.length()) {
+                sbUrl.append("?").append(sbQuery);
+            }
+        }
+
+        return sbUrl.toString();
+    }
+
+    private static HttpClient wrapClient(String host) {
+        HttpClient httpClient = new DefaultHttpClient();
+        if (host.startsWith("https://")) {
+            sslClient(httpClient);
+        }
+
+        return httpClient;
+    }
+
+    private static void sslClient(HttpClient httpClient) {
+        try {
+            SSLContext ctx = SSLContext.getInstance("TLS");
+            X509TrustManager tm = new X509TrustManager() {
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+
+                public void checkClientTrusted(X509Certificate[] xcs, String str) {
+
+                }
+
+                public void checkServerTrusted(X509Certificate[] xcs, String str) {
+
+                }
+            };
+            ctx.init(null, new TrustManager[]{tm}, null);
+            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
+            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            ClientConnectionManager ccm = httpClient.getConnectionManager();
+            SchemeRegistry registry = ccm.getSchemeRegistry();
+            registry.register(new Scheme("https", 443, ssf));
+        } catch (KeyManagementException ex) {
+            throw new RuntimeException(ex);
+        } catch (NoSuchAlgorithmException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}