lzm il y a 3 ans
Parent
commit
984768cfe7
32 fichiers modifiés avec 3025 ajouts et 5 suppressions
  1. 51 0
      sp-admin/sa-frame/menu-list.js
  2. 138 0
      sp-admin/sa-view/tb-entity/tb-entity-add.html
  3. 70 0
      sp-admin/sa-view/tb-entity/tb-entity-info.html
  4. 153 0
      sp-admin/sa-view/tb-entity/tb-entity-list.html
  5. 17 0
      sp-admin/sa-view/tb-fee-statistics/dayStatsPrint.html
  6. 12 2
      sp-admin/sa-view/tb-fee-statistics/tb-fee-details-list.html
  7. 122 0
      sp-admin/sa-view/tb-invoice-info/tb-invoice-info-add.html
  8. 72 0
      sp-admin/sa-view/tb-invoice-info/tb-invoice-info-info.html
  9. 231 0
      sp-admin/sa-view/tb-invoice-info/tb-invoice-info-list.html
  10. 120 0
      sp-admin/sa-view/tb-invoice-order/tb-invoice-order-add.html
  11. 71 0
      sp-admin/sa-view/tb-invoice-order/tb-invoice-order-info.html
  12. 267 0
      sp-admin/sa-view/tb-invoice-order/tb-invoice-order-list.html
  13. 21 0
      sp-admin/static/sa.js
  14. 20 0
      sp-server/src/main/java/com/pj/current/config/OcrConfig.java
  15. 101 0
      sp-server/src/main/java/com/pj/project/tb_entity/TbEntity.java
  16. 111 0
      sp-server/src/main/java/com/pj/project/tb_entity/TbEntityController.java
  17. 56 0
      sp-server/src/main/java/com/pj/project/tb_entity/TbEntityMapper.java
  18. 108 0
      sp-server/src/main/java/com/pj/project/tb_entity/TbEntityMapper.xml
  19. 55 0
      sp-server/src/main/java/com/pj/project/tb_entity/TbEntityService.java
  20. 7 3
      sp-server/src/main/java/com/pj/project/tb_fee_details/TbFeeDetailsMapper.xml
  21. 137 0
      sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfo.java
  22. 136 0
      sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoController.java
  23. 56 0
      sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoMapper.java
  24. 116 0
      sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoMapper.xml
  25. 133 0
      sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoService.java
  26. 110 0
      sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrder.java
  27. 113 0
      sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderController.java
  28. 56 0
      sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderMapper.java
  29. 113 0
      sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderMapper.xml
  30. 192 0
      sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderService.java
  31. 7 0
      sp-server/src/main/java/com/pj/project/tb_order/TbOrderService.java
  32. 53 0
      sp-server/src/main/java/com/pj/utils/OcrUtils.java

+ 51 - 0
sp-admin/sa-frame/menu-list.js

@@ -653,5 +653,56 @@ var menuList = [{
 			},
 		]
 	},
+	// {
+	// 	id: 'tb-entity',
+	// 	name: '开票主体',
+	// 	icon: 'el-icon-folder-opened',
+	// 	parent: true,
+	// 	childList: [
+	// 		{id: 'tb-entity-list', name: '开票主体列表', url: 'sa-view/tb-entity/tb-entity-list.html'},
+	// 	]
+	// },
+	// {
+	// 	id: 'tb-invoice-order',
+	// 	name: '开票订单',
+	// 	icon: 'el-icon-folder-opened',
+	// 	parent: true,
+	// 	childList: [
+	// 		{id: 'tb-invoice-order-list', name: '开票订单列表', url: 'sa-view/tb-invoice-order/tb-invoice-order-list.html'},
+	// 	]
+	// },
+	// {
+	// 	id: 'tb-invoice-info',
+	// 	name: '开票信息',
+	// 	icon: 'el-icon-folder-opened',
+	// 	parent: true,
+	// 	childList: [
+	// 		{id: 'tb-invoice-info-list', name: '开票信息列表', url: 'sa-view/tb-invoice-info/tb-invoice-info-list.html'},
+	// 	]
+	// },
+	{
+		id: 'tb-invoice-info',
+		name: '开票管理',
+		icon: 'el-icon-folder-opened',
+		parent: true,
+		childList: [
+			{
+				id: 'tb-entity-list',
+				name: '开票主体',
+				url: 'sa-view/tb-entity/tb-entity-list.html'
+			},
+			{
+				id: 'tb-invoice-order-list',
+				name: '开票订单',
+				url: 'sa-view/tb-invoice-order/tb-invoice-order-list.html'
+			},
+			{
+				id: 'tb-invoice-info-list',
+				name: '开票信息',
+				url: 'sa-view/tb-invoice-info/tb-invoice-info-list.html'
+			},
+		]
+	},
+
 
 ]

+ 138 - 0
sp-admin/sa-view/tb-entity/tb-entity-add.html

@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票主体表-添加/修改</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+		<style type="text/css">
+			.c-panel .el-form .c-label{width: 7em !important;}
+			.c-panel .el-form .el-input, .c-panel .el-form .el-textarea__inner{width: 250px;}
+		</style>
+	</head>
+	<body>
+		<div class="vue-box" :class="{sbot: id}" style="display: none;" :style="'display: block;'">
+			<!-- ------- 内容部分 ------- -->
+			<div class="s-body">
+				<div class="c-panel">
+                    <div class="c-title" v-if="id == 0">数据添加</div>
+					<div class="c-title" v-else>数据修改</div>
+					<el-form v-if="m">
+						<sa-item type="text" name="企业名称" v-model="m.name" br></sa-item>
+						<sa-item type="text" name="税号" v-model="m.taxIdNo" br></sa-item>
+						<sa-item type="text" name="地址" v-model="m.address" br></sa-item>
+						<sa-item type="text" name="电话" v-model="m.phone" br></sa-item>
+						<sa-item type="text" name="开户银行" v-model="m.bank" br></sa-item>
+						<sa-item type="text" name="银行账号" v-model="m.bankNo" br></sa-item>
+						<sa-item type="text" name="邮箱" v-model="m.email" br></sa-item>
+						<sa-item name="" class="s-ok" br>
+							<el-button type="primary" icon="el-icon-plus" @click="ok()">保存</el-button>
+						</sa-item>
+					</el-form>
+				</div>
+			</div>
+			<!-- ------- 底部按钮 ------- -->
+			<div class="s-foot">
+				<el-button type="primary" @click="ok()">确定</el-button>
+				<el-button @click="sa.closeCurrIframe()">取消</el-button>
+			</div>
+		</div>
+        <script>
+			
+			var app = new Vue({
+				components: {
+					"sa-item": httpVueLoader('../../sa-frame/com/sa-item.vue')
+				},
+				el: '.vue-box',
+				data: {
+					id: sa.p('id', 0),		// 获取超链接中的id参数(0=添加,非0=修改) 
+					m: null,		// 实体对象 
+				},
+				methods: {
+					// 创建一个 默认Model 
+					createModel: function() {
+						return {
+							id: '',		// 主键
+							customerId: sa.p('customerId', ''),
+							name: '',		// 企业名称 
+							taxIdNo: '',		// 税号 
+							address: '',		// 地址 
+							phone: '',		// 电话 
+							bank: '',		// 开户银行 
+							bankNo: '',		// 银行账号 
+							email: '',		// 邮箱
+							createTime: '',		// 创建时间 
+							updateTime: '',		// 更新时间 
+						}
+					},
+					// 提交数据 
+					ok: function(){
+						// 表单校验 
+						let m = this.m;
+						sa.checkNull(m.name, '请输入 [企业名称]');
+						sa.checkNull(m.taxIdNo, '请输入 [税号]');
+						sa.checkNull(m.address, '请输入 [地址]');
+						sa.checkNull(m.phone, '请输入 [电话]');
+						sa.checkNull(m.bank, '请输入 [开户银行]');
+						sa.checkNull(m.bankNo, '请输入 [银行账号]');
+						sa.checkNull(m.email, '请输入 [邮箱]');
+						if (!sa.isTel(m.phone)) {
+							sa.error('联系号码不正确')
+							return;
+						}
+						if (!sa.isEmail(m.email)) {
+							sa.error('邮箱不正确')
+							return;
+						}
+						if (!sa.isTaxId(m.taxIdNo)) {
+							sa.error('税号不正确')
+							return;
+						}
+				
+						// 开始增加或修改
+						if(this.id <= 0) {	// 添加
+							sa.ajax('/TbEntity/add', m, function(res){
+								sa.alert('增加成功', this.clean); 
+							}.bind(this));
+						} else {	// 修改
+							sa.ajax('/TbEntity/update', m, function(res){
+								sa.alert('修改成功', this.clean);
+							}.bind(this));
+						}
+					},
+					// 添加/修改 完成后的动作
+					clean: function() {
+						if(this.id == 0) {
+							this.m = this.createModel();
+						} else {
+							parent.app.f5();		// 刷新父页面列表
+							sa.closeCurrIframe();	// 关闭本页 
+						}
+					}
+				},
+				mounted: function(){
+					// 初始化数据 
+					if(this.id <= 0) {	
+						this.m = this.createModel();
+					} else {	
+						sa.ajax('/TbEntity/getById?id=' + this.id, function(res) {
+							this.m = res.data;
+							if(res.data == null) {
+								sa.alert('未能查找到 id=' + this.id + " 详细数据");
+							}
+						}.bind(this))
+					}
+				}
+			})
+			
+		</script>
+	</body>
+</html>

+ 70 - 0
sp-admin/sa-view/tb-entity/tb-entity-info.html

@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票主体表-详情</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+		<style type="text/css">
+			.c-panel .c-label{width: 8em;}
+		</style>
+	</head>
+	<body>
+		<div class="vue-box sbot" style="display: none;" :style="'display: block;'">
+			<!-- ------- 内容部分 ------- -->
+			<div class="s-body">
+				<div class="c-panel">
+					<el-form v-if="m">
+<!--						<sa-info name="主键" br>{{m.id}}</sa-info>-->
+<!--						<sa-info name="客户id" br>{{m.customerId}}</sa-info>-->
+						<sa-info name="企业名称" br>{{m.name}}</sa-info>
+						<sa-info name="税号" br>{{m.taxIdNo}}</sa-info>
+						<sa-info name="地址" br>{{m.address}}</sa-info>
+						<sa-info name="电话" br>{{m.phone}}</sa-info>
+						<sa-info name="开户银行" br>{{m.bank}}</sa-info>
+						<sa-info name="银行账号" br>{{m.bankNo}}</sa-info>
+						<sa-info name="邮箱" br>{{m.email}}</sa-info>
+						<sa-info name="创建时间" br>{{m.createTime}}</sa-info>
+						<sa-info name="更新时间" br>{{m.updateTime}}</sa-info>
+					</el-form>
+				</div>
+			</div>
+			<!-- ------- 底部按钮 ------- -->
+			<div class="s-foot">
+				<el-button type="success" @click="sa.closeCurrIframe()">确定</el-button>
+				<el-button @click="sa.closeCurrIframe()">取消</el-button>
+			</div>
+		</div>
+		<script>
+			var app = new Vue({
+				components: {
+					"sa-info": httpVueLoader('../../sa-frame/com/sa-info.vue')
+				},
+				el: '.vue-box',
+				data: {
+					id: sa.p('id', 0),	// 获取数据ID 
+					m: null
+				},
+				methods: {
+				},
+				mounted: function() {
+					sa.ajax('/TbEntity/getById?id=' + this.id, function(res) {
+						this.m = res.data;
+						if(res.data == null) {
+							sa.alert('未能查找到 id=' + this.id + " 详细数据");
+						}
+					}.bind(this))
+				}
+			})
+			
+		</script>
+	</body>
+</html>

+ 153 - 0
sp-admin/sa-view/tb-entity/tb-entity-list.html

@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票主体表-列表</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css & js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+	</head>
+	<body>
+		<div class="vue-box" style="display: none;" :style="'display: block;'">
+			<div class="c-panel">
+				<!-- ------------- 检索参数 ------------- -->
+				<div class="c-title">检索参数</div>
+				<el-form ref="form" :model='p' @submit.native.prevent>
+					<sa-item type="text" name="企业名称" v-model="p.name"></sa-item>
+					<el-button type="primary" icon="el-icon-search" @click="p.pageNo = 1; f5()">查询</el-button>
+					<br />
+				</el-form>
+				<!-- ------------- 快捷按钮 ------------- -->
+				<sa-item type="fast-btn" show="add,reset"></sa-item>
+				<!-- ------------- 数据列表 ------------- -->
+				<el-table class="data-table" ref="data-table" :data="dataList" >
+<!--					<sa-td type="selection"></sa-td>-->
+<!--					<sa-td name="主键" prop="id" ></sa-td>-->
+<!--					<sa-td name="客户id" prop="customerId" ></sa-td>-->
+					<sa-td name="企业名称" prop="name" ></sa-td>
+					<sa-td name="税号" prop="taxIdNo" ></sa-td>
+					<sa-td name="地址" prop="address" ></sa-td>
+					<sa-td name="电话" prop="phone" ></sa-td>
+					<sa-td name="开户银行" prop="bank" ></sa-td>
+					<sa-td name="银行账号" prop="bankNo" ></sa-td>
+					<sa-td name="邮箱" prop="email" ></sa-td>
+<!--					<sa-td name="创建时间" prop="createTime" ></sa-td>-->
+<!--					<sa-td name="更新时间" prop="updateTime" ></sa-td>-->
+					<el-table-column label="操作"  width="240px">
+						<template slot-scope="s">
+							<el-button class="c-btn" type="success" icon="el-icon-view" @click="get(s.row)">查看</el-button>
+							<el-button class="c-btn" type="primary" icon="el-icon-edit" @click="update(s.row)">修改</el-button>
+							<el-button class="c-btn" type="danger" icon="el-icon-delete" @click="del(s.row)">删除</el-button>
+						</template>
+					</el-table-column>
+				</el-table>
+				<!-- ------------- 分页 ------------- -->
+				<sa-item type="page" :curr.sync="p.pageNo" :size.sync="p.pageSize" :total="dataCount" @change="f5()"></sa-item>
+			</div>
+		</div>
+		<script>
+			var app = new Vue({
+				components: {
+					"sa-item": httpVueLoader('../../sa-frame/com/sa-item.vue'),  
+					"sa-td": httpVueLoader('../../sa-frame/com/sa-td.vue'),		
+				},
+				el: '.vue-box',
+				data: {
+					p: { // 查询参数  
+						id: '',		// 主键 
+						customerId: '',		// 客户id 
+						name: '',		// 企业名称 
+						taxIdNo: '',		// 税号 
+						address: '',		// 地址 
+						phone: '',		// 电话 
+						bank: '',		// 开户银行 
+						bankNo: '',		// 银行账号 
+						email: '',		// 邮箱
+						createTime: '',		// 创建时间 
+						updateTime: '',		// 更新时间 
+						pageNo: 1,		// 当前页 
+						pageSize: 10,	// 页大小 
+						sortType: 0		// 排序方式 
+					},
+					dataCount: 0,
+					dataList: [], // 数据集合
+					currentCustomerId: '1',
+				},
+				methods: {
+					getCustomer() {
+						sa.ajax('/TbCostomer/getCurrentCustomerId', function(resp) {
+							this.currentCustomerId = resp.data;
+						}.bind(this));
+					},
+					// 刷新
+					f5: function() {
+						sa.ajax('/TbEntity/getList', sa.removeNull(this.p), function(res) {
+							this.dataList = res.data; // 数据
+							this.dataCount = res.dataCount; // 数据总数 
+							sa.f5TableHeight();		// 刷新表格高度 
+						}.bind(this));
+					},
+					// 查看
+					get: function(data) {
+						sa.showIframe('数据详情', 'tb-entity-info.html?id=' + data.id, '1050px', '90%');
+					},
+					// 查看 - 根据选中的
+					getBySelect: function(data) {
+						var selection = this.$refs['data-table'].selection;
+						if(selection.length == 0) {
+							return sa.msg('请选择一条数据')
+						}
+						this.get(selection[0]);
+					},
+					// 修改
+					update: function(data) {
+						sa.showIframe('修改数据', 'tb-entity-add.html?id=' + data.id, '550px', '80%');
+					},
+					// 新增
+					add: function(data) {
+						sa.showIframe('新增数据', 'tb-entity-add.html?id=-1&customerId=' + this.currentCustomerId, '550px', '80%');
+					},
+					// 删除
+					del: function(data) {
+						sa.confirm('是否删除,此操作不可撤销', function() {
+							sa.ajax('/TbEntity/delete?id=' + data.id, function(res) {
+								sa.arrayDelete(this.dataList, data);
+								sa.ok('删除成功');
+								sa.f5TableHeight();		// 刷新表格高度 
+							}.bind(this))
+						}.bind(this));
+					},
+					// 批量删除
+					deleteByIds: function() {
+						// 获取选中元素的id列表 
+						let selection = this.$refs['data-table'].selection;
+						let ids = sa.getArrayField(selection, 'id');
+						if(selection.length == 0) {
+							return sa.msg('请至少选择一条数据')
+						}
+						// 提交删除 
+						sa.confirm('是否批量删除选中数据?此操作不可撤销', function() {
+							sa.ajax('/TbEntity/deleteByIds', {ids: ids.join(',')}, function(res) {
+								sa.arrayDelete(this.dataList, selection);
+								sa.ok('删除成功');
+								sa.f5TableHeight();		// 刷新表格高度 
+							}.bind(this))
+						}.bind(this));
+					},
+				},
+				created: function() {
+					this.f5();
+					this.getCustomer();
+					sa.onInputEnter();
+				}
+			})
+		</script>
+	</body>
+</html>

+ 17 - 0
sp-admin/sa-view/tb-fee-statistics/dayStatsPrint.html

@@ -65,6 +65,10 @@
                 &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
                 收费员:
               </SPAN>
+              <br/><br/>
+              <SPAN id="leader" style=";font-size:15px">
+
+              </SPAN>
             </div>
 
     </div>
@@ -106,6 +110,19 @@
       $("#unit").attr('colspan', 5);
       $("#td_time").attr('colspan', 3);
     }
+    if(isMonth!=null || isYear!=null){
+      $("#leader").html("运营负责人:\n" +
+              "                &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp\n" +
+              "                &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp\n" +
+              "                &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp\n" +
+              "                运营分管领导:");
+    }else{
+      $("#leader").html("运营负责人:\n" +
+              "                &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp\n" +
+              "                &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp\n" +
+              "                &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp\n" +
+              "                &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp");
+    }
 
 
     var beginDay = getUrlParam('beginDay');

+ 12 - 2
sp-admin/sa-view/tb-fee-statistics/tb-fee-details-list.html

@@ -83,6 +83,15 @@
 										format="yyyy 年 MM 月 dd 日" value-format="yyyy-MM-dd">
 						</el-date-picker>
 					</div>
+					<div class="c-item">
+						<label class="c-label">是否开票:</label>
+						<el-select v-model="p.isInvoice" placeholder="请选择" filterable>
+							<el-option label="全部" value=""></el-option>
+							<el-option label="未开票" value="0"></el-option>
+							<el-option label="已开票" value="1"></el-option>
+						</el-select>
+					</div>
+
 
 					<el-button type="primary" icon="el-icon-search" @click="p.pageNo = 1; f5()">查询</el-button>
 					<br />
@@ -156,8 +165,8 @@
 						</template>
 					</el-table-column>
 					<sa-td name="作业编号" prop="businessItemNo" width="145px" ></sa-td>
+					<sa-td name="发票号" prop="invoice" width="145px"></sa-td>
 					<sa-td name="企业名称" prop="pickCustomerName" ></sa-td>
-					<sa-td name="发票号" prop="" ></sa-td>
 					<sa-td name="生成时间" prop="createTime" width="150px" ></sa-td>
 					<sa-td name="付款时间" prop="payTime"  width="150px" ></sa-td>
 					<sa-td name="备注" prop="remark" ></sa-td>
@@ -240,7 +249,8 @@
 						pageNo: 1,		// 当前页 
 						pageSize: 10,	// 页大小
 						sortType: 11,		// 排序方式
-						type: ''
+						type: '',
+						isInvoice: '',   //是否开票
 					},
 					dataCount: 0,
 					dataList: [], // 数据集合

+ 122 - 0
sp-admin/sa-view/tb-invoice-info/tb-invoice-info-add.html

@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票信息表-添加/修改</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+		<style type="text/css">
+			.c-panel .el-form .c-label{width: 7em !important;}
+			.c-panel .el-form .el-input, .c-panel .el-form .el-textarea__inner{width: 250px;}
+		</style>
+	</head>
+	<body>
+		<div class="vue-box" :class="{sbot: id}" style="display: none;" :style="'display: block;'">
+			<!-- ------- 内容部分 ------- -->
+			<div class="s-body">
+				<div class="c-panel">
+                    <div class="c-title" v-if="id == 0">数据添加</div>
+					<div class="c-title" v-else>主体修改</div>
+					<el-form v-if="m">
+						<sa-item type="text" name="主体名称" v-model="m.entityName" br></sa-item>
+						<sa-item type="text" name="税号" v-model="m.taxIdNo" br></sa-item>
+						<sa-item type="text" name="地址" v-model="m.address" br></sa-item>
+						<sa-item type="text" name="电话" v-model="m.phone" br></sa-item>
+						<sa-item type="text" name="开户银行" v-model="m.bank" br></sa-item>
+						<sa-item type="text" name="银行账号" v-model="m.bankNo" br></sa-item>
+						<sa-item type="text" name="邮箱" v-model="m.email" br></sa-item>
+						<sa-item name="" class="s-ok" br>
+							<el-button type="primary" icon="el-icon-plus" @click="ok()">保存</el-button>
+						</sa-item>
+					</el-form>
+				</div>
+			</div>
+			<!-- ------- 底部按钮 ------- -->
+			<div class="s-foot">
+				<el-button type="primary" @click="ok()">确定</el-button>
+				<el-button @click="sa.closeCurrIframe()">取消</el-button>
+			</div>
+		</div>
+        <script>
+			
+			var app = new Vue({
+				components: {
+					"sa-item": httpVueLoader('../../sa-frame/com/sa-item.vue')
+				},
+				el: '.vue-box',
+				data: {
+					id: sa.p('id', 0),		// 获取超链接中的id参数(0=添加,非0=修改) 
+					m: {
+						id: '',		// 主键
+						customerId: '',		// 客户id
+						customerName: '',		// 客户名称
+						totalMoney: '',		// 账单金额
+						status: '',		// 支付状态(0=未开票,1=已开票)
+						invoiceTime: '',		// 开票时间
+						invoiceNo: '',		// 发票号
+						entityId: '',		// 主体id
+						entityName: '',		// 主体名称
+						taxIdNo: '',		// 税号
+						address: '',		// 地址
+						phone: '',		// 电话
+						bank: '',		// 开户银行
+						bankNo: '',		// 银行账号
+						email: '',		// 邮箱
+						createTime: '',		// 创建时间
+						beginTime: '', //查询开始时间
+						endTime: '', //查询结束时间
+					},		// 实体对象
+					entityList: [],
+				},
+				methods: {
+
+					// 提交数据 
+					ok: function(){
+						// 表单校验 
+						let m = this.m;
+						sa.checkNull(m.entityName, '请输入 [主体名称]');
+						sa.checkNull(m.taxIdNo, '请输入 [税号]');
+						sa.checkNull(m.address, '请输入 [地址]');
+						sa.checkNull(m.phone, '请输入 [电话]');
+						sa.checkNull(m.bank, '请输入 [开户银行]');
+						sa.checkNull(m.bankNo, '请输入 [银行账号]');
+						sa.checkNull(m.email, '请输入 [邮箱]');
+						// 开始增加或修改
+						if(this.id <= 0) {} else {	// 修改
+							sa.ajax('/TbInvoiceInfo/update', sa.removeNull(m), function(res){
+								sa.alert('修改成功', this.clean);
+							}.bind(this));
+						}
+					},
+					// 添加/修改 完成后的动作
+					clean: function() {
+						if(this.id == 0) {} else {
+							parent.app.f5();		// 刷新父页面列表
+							sa.closeCurrIframe();	// 关闭本页 
+						}
+					}
+				},
+				mounted: function(){
+					// 初始化数据 
+					if(this.id <= 0) {} else {
+						sa.ajax('/TbInvoiceInfo/getById?id=' + this.id, function(res) {
+							this.m = res.data;
+							if(res.data == null) {
+								sa.alert('未能查找到 id=' + this.id + " 详细数据");
+							}
+						}.bind(this))
+					}
+				}
+			})
+			
+		</script>
+	</body>
+</html>

+ 72 - 0
sp-admin/sa-view/tb-invoice-info/tb-invoice-info-info.html

@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票信息表-详情</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+		<style type="text/css">
+			.c-panel .c-label{width: 8em;}
+		</style>
+	</head>
+	<body>
+		<div class="vue-box sbot" style="display: none;" :style="'display: block;'">
+			<!-- ------- 内容部分 ------- -->
+			<div class="s-body">
+				<div class="c-panel">
+					<el-form v-if="m">
+						<sa-info name="客户名称" br>{{m.customerName}}</sa-info>
+						<sa-info name="账单金额" br>{{m.totalMoney}}</sa-info>
+						<sa-info type="enum" name="支付状态" :value="m.status" :jv="{0: '未开票', 1: '已开票'}" br></sa-info>
+						<sa-info name="开票时间" br>{{m.invoiceTime}}</sa-info>
+						<sa-info name="发票号" br>{{m.invoiceNo}}</sa-info>
+						<sa-info name="主体名称" br>{{m.entityName}}</sa-info>
+						<sa-info name="税号" br>{{m.taxIdNo}}</sa-info>
+						<sa-info name="地址" br>{{m.address}}</sa-info>
+						<sa-info name="电话" br>{{m.phone}}</sa-info>
+						<sa-info name="开户银行" br>{{m.bank}}</sa-info>
+						<sa-info name="银行账号" br>{{m.bankNo}}</sa-info>
+						<sa-info name="邮箱" br>{{m.email}}</sa-info>
+						<sa-info name="创建时间" br>{{m.createTime}}</sa-info>
+					</el-form>
+				</div>
+			</div>
+			<!-- ------- 底部按钮 ------- -->
+			<div class="s-foot">
+				<el-button type="success" @click="sa.closeCurrIframe()">确定</el-button>
+				<el-button @click="sa.closeCurrIframe()">取消</el-button>
+			</div>
+		</div>
+		<script>
+			var app = new Vue({
+				components: {
+					"sa-info": httpVueLoader('../../sa-frame/com/sa-info.vue')
+				},
+				el: '.vue-box',
+				data: {
+					id: sa.p('id', 0),	// 获取数据ID 
+					m: null
+				},
+				methods: {
+				},
+				mounted: function() {
+					sa.ajax('/TbInvoiceInfo/getEntityById?id=' + this.id, function(res) {
+						this.m = res.data;
+						if(res.data == null) {
+							sa.alert('未能查找到 id=' + this.id + " 详细数据");
+						}
+					}.bind(this))
+				}
+			})
+			
+		</script>
+	</body>
+</html>

+ 231 - 0
sp-admin/sa-view/tb-invoice-info/tb-invoice-info-list.html

@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票信息表-列表</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css & js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+	</head>
+	<body>
+		<div class="vue-box" style="display: none;" :style="'display: block;'">
+			<div class="c-panel">
+				<!-- ------------- 检索参数 ------------- -->
+				<div class="c-title">检索参数</div>
+				<el-form ref="form" :model='p' @submit.native.prevent>
+
+					<sa-item type="text" name="客户名称" v-model="p.customerName"></sa-item>
+					<div class="c-item">
+						<label class="c-label">开票状态:</label>
+						<el-select v-model="p.status" placeholder="请选择">
+							<el-option label="不限" value=""></el-option>
+							<el-option label="未开票" :value="0"></el-option>
+							<el-option label="已开票" :value="1"></el-option>
+						</el-select>
+					</div>
+					<div class="c-item">
+						<label class="c-label">开票时间:</label>
+						<el-date-picker size="mini" v-model="selectTime" type="daterange"
+										range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
+										format="yyyy 年 MM 月 dd 日" value-format="yyyy-MM-dd">
+						</el-date-picker>
+					</div>
+					<el-button type="primary" icon="el-icon-search" @click="p.pageNo = 1; f5()">查询</el-button>
+					<el-button size="mini" type="info" @click="sa.f5()">刷新</el-button>
+					<br />
+				</el-form>
+				<!-- ------------- 快捷按钮 ------------- -->
+
+				<!-- ------------- 数据列表 ------------- -->
+				<el-table class="data-table" ref="data-table" :data="dataList" >
+					<sa-td type="selection"></sa-td>
+					<sa-td name="编号" prop="no" width="129"></sa-td>
+					<sa-td name="客户名称" prop="customerName" ></sa-td>
+					<sa-td name="账单金额" prop="totalMoney" ></sa-td>
+					<sa-td name="开票状态" prop="status" type="enum" :jv="{0: '未开票', 1: '已开票'}"></sa-td>
+					<sa-td name="开票种类" prop="isElec" type="enum" :jv="{0: '纸质发票', 1: '电子发票'}"></sa-td>
+					<sa-td name="开票时间" prop="invoiceTime" ></sa-td>
+					<sa-td name="发票号" prop="invoiceNo" width="150"></sa-td>
+					<el-table-column label="主体名称">
+						<template slot-scope="s">
+							<span>{{s.row.entityName}}</span>
+						</template>
+					</el-table-column>
+					<el-table-column label="税号" width="156">
+						<template slot-scope="s">
+							<span>{{s.row.taxIdNo}}</span>
+						</template>
+					</el-table-column>
+<!--					<sa-td name="地址" prop="address" ></sa-td>-->
+<!--					<sa-td name="电话" prop="phone" ></sa-td>-->
+<!--					<sa-td name="开户银行" prop="bank" ></sa-td>-->
+<!--					<sa-td name="银行账号" prop="bankNo" ></sa-td>-->
+<!--					<sa-td name="邮箱" prop="email" ></sa-td>-->
+					<el-table-column label="操作"  width="240px">
+						<template slot-scope="s">
+							<el-button v-if="s.row.status==0 && currentCustomerId==1" class="c-btn" type="primary"  @click="completeFn(s.row.id)">完成开票</el-button>
+							<el-button class="c-btn" type="success" icon="el-icon-view" @click="get(s.row)">查看</el-button>
+							<el-button v-if="s.row.status==0" class="c-btn" type="primary" icon="el-icon-edit" @click="update(s.row)">修改</el-button>
+							<el-button v-if="s.row.status==0 && currentCustomerId==1" class="c-btn" type="danger" icon="el-icon-delete" @click="del(s.row)">删除</el-button>
+						</template>
+					</el-table-column>
+				</el-table>
+				<!-- ------------- 分页 ------------- -->
+				<sa-item type="page" :curr.sync="p.pageNo" :size.sync="p.pageSize" :total="dataCount" @change="f5()"></sa-item>
+			</div>
+			<el-dialog title="完成开票" :visible.sync="completeDate.visible" width="38%">
+				<div class="c-item">
+					<label class="c-label">开票时间:</label>
+					<el-date-picker type="datetime" value-format="yyyy-MM-dd HH:mm:ss" v-model="completeDate.form.invoiceTime"></el-date-picker>
+				</div>
+				<sa-item type="text" name="发票号" v-model="completeDate.form.invoiceNo"></sa-item>
+				<span slot="footer" class="dialog-footer">
+					<el-button @click="emodel.visible = false">取 消</el-button>
+					<el-button type="primary" @click="complete">确 定</el-button>
+				</span>
+			</el-dialog>
+		</div>
+		<script>
+			var app = new Vue({
+				components: {
+					"sa-item": httpVueLoader('../../sa-frame/com/sa-item.vue'),  
+					"sa-td": httpVueLoader('../../sa-frame/com/sa-td.vue'),		
+				},
+				el: '.vue-box',
+				data: {
+					p: { // 查询参数  
+						id: '',		// 主键 
+						customerId: '',		// 客户id 
+						customerName: '',		// 客户名称 
+						totalMoney: '',		// 账单金额 
+						status: '',		// 支付状态(0=未开票,1=已开票) 
+						invoiceTime: '',		// 开票时间 
+						invoiceNo: '',		// 发票号 
+						entityId: '',		// 主体id 
+						entityName: '',		// 主体名称 
+						taxIdNo: '',		// 税号 
+						address: '',		// 地址 
+						phone: '',		// 电话 
+						bank: '',		// 开户银行 
+						bankNo: '',		// 银行账号 
+						email: '',		// 邮箱 
+						createTime: '',		// 创建时间
+						beginTime: '', //查询开始时间
+						endTime: '', //查询结束时间
+						pageNo: 1,		// 当前页 
+						pageSize: 10,	// 页大小 
+						sortType: 0		// 排序方式 
+					},
+					dataCount: 0,
+					dataList: [], // 数据集合
+					completeDate: {
+						visible: false,
+						form: {
+							id:'',
+							invoiceTime: '',
+							invoiceNo: '',
+						},
+					},
+					currentCustomerId: '1',
+					selectTime:[],
+					selectTimeRange: {
+						beginTime: '', //查询开始时间
+						endTime: '', //查询结束时间
+					},
+				},
+				methods: {
+					completeFn(id){
+						this.completeDate.visible = true;
+						this.completeDate.form.id = id;
+					},
+					complete(){
+						sa.checkNull(this.completeDate.form.invoiceTime, '请选择 [开票时间]');
+						sa.checkNull(this.completeDate.form.invoiceNo, '输入 [发票号]');
+						sa.ajax('/TbInvoiceInfo/complete?' , this.completeDate.form, function(res) {
+							sa.alert('开票成功');
+							this.completeDate.visible = false;
+							this.f5();
+						}.bind(this))
+					},
+					getCustomer() {
+						sa.ajax('/TbCostomer/getCurrentCustomerId', function(resp) {
+							this.currentCustomerId = resp.data;
+						}.bind(this));
+					},
+					// 刷新
+					f5: function() {
+						if ( this.selectTime != null && this.selectTime.length != 0) {
+							this.p.beginTime = this.selectTime[0];
+							this.p.endTime = this.selectTime[1];
+						}
+						sa.ajax('/TbInvoiceInfo/getList', sa.removeNull(this.p), function(res) {
+							this.dataList = res.data; // 数据
+							this.dataCount = res.dataCount; // 数据总数
+
+							sa.f5TableHeight();		// 刷新表格高度 
+						}.bind(this));
+					},
+					// 查看
+					get: function(data) {
+						sa.showIframe('数据详情', 'tb-invoice-info-info.html?id=' + data.id, '550px', '80%');
+					},
+					// 查看 - 根据选中的
+					getBySelect: function(data) {
+						var selection = this.$refs['data-table'].selection;
+						if(selection.length == 0) {
+							return sa.msg('请选择一条数据')
+						}
+						this.get(selection[0]);
+					},
+					// 修改
+					update: function(data) {
+						sa.showIframe('主体信息修改', 'tb-invoice-info-add.html?id=' + data.id, '550px', '80%');
+					},
+					// 新增
+					add: function(data) {
+						sa.showIframe('新增数据', 'tb-invoice-info-add.html?id=-1&customerId=' + this.currentCustomerId, '550px', '80%');
+					},
+					// 删除
+					del: function(data) {
+						sa.confirm('是否删除,此操作不可撤销', function() {
+							sa.ajax('/TbInvoiceInfo/delete?id=' + data.id, function(res) {
+								sa.arrayDelete(this.dataList, data);
+								sa.ok('删除成功');
+								sa.f5TableHeight();		// 刷新表格高度 
+							}.bind(this))
+						}.bind(this));
+					},
+					// 批量删除
+					deleteByIds: function() {
+						// 获取选中元素的id列表 
+						let selection = this.$refs['data-table'].selection;
+						let ids = sa.getArrayField(selection, 'id');
+						if(selection.length == 0) {
+							return sa.msg('请至少选择一条数据')
+						}
+						// 提交删除 
+						sa.confirm('是否批量删除选中数据?此操作不可撤销', function() {
+							sa.ajax('/TbInvoiceInfo/deleteByIds', {ids: ids.join(',')}, function(res) {
+								sa.arrayDelete(this.dataList, selection);
+								sa.ok('删除成功');
+								sa.f5TableHeight();		// 刷新表格高度 
+							}.bind(this))
+						}.bind(this));
+					},
+				},
+				created: function() {
+					this.f5();
+					this.getCustomer();
+					sa.onInputEnter();
+				}
+			})
+		</script>
+	</body>
+</html>

+ 120 - 0
sp-admin/sa-view/tb-invoice-order/tb-invoice-order-add.html

@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票订单表-添加/修改</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+		<script src="../../static/kj/upload-util.js"></script>
+		<style type="text/css">
+			.c-panel .el-form .c-label{width: 7em !important;}
+			.c-panel .el-form .el-input, .c-panel .el-form .el-textarea__inner{width: 250px;}
+		</style>
+	</head>
+	<body>
+		<div class="vue-box" :class="{sbot: id}" style="display: none;" :style="'display: block;'">
+			<!-- ------- 内容部分 ------- -->
+			<div class="s-body">
+				<div class="c-panel">
+                    <div class="c-title" v-if="id == 0">上传账单</div>
+					<div class="c-title" v-else>数据修改</div>
+					<el-form v-if="m">
+<!--						<sa-item type="text" name="微信支付订单号" v-model="m.transactionId" br></sa-item>-->
+<!--						<sa-item type="text" name="账单金额" v-model="m.billMoney" br></sa-item>-->
+						<sa-item type="img" name="账单截图" v-model="m.billImage" br></sa-item>
+						<sa-item name="" class="s-ok" br>
+							<el-button type="primary" icon="el-icon-plus" @click="ok()">保存</el-button>
+						</sa-item>
+					</el-form>
+				</div>
+			</div>
+			<!-- ------- 底部按钮 ------- -->
+			<div class="s-foot">
+				<el-button type="primary" @click="ok()">确定</el-button>
+				<el-button @click="sa.closeCurrIframe()">取消</el-button>
+			</div>
+		</div>
+        <script>
+			
+			var app = new Vue({
+				components: {
+					"sa-item": httpVueLoader('../../sa-frame/com/sa-item.vue')
+				},
+				el: '.vue-box',
+				data: {
+					id: sa.p('id', 0),		// 获取超链接中的id参数(0=添加,非0=修改) 
+					m: null,		// 实体对象 
+				},
+				methods: {
+					// 创建一个 默认Model 
+					createModel: function() {
+						return {
+							id: '',		// 主键
+							customerId: sa.p('customerId', ''),
+							businessId: '',		// 业务订单id 
+							businessName: '',		// 业务名称 
+							businessNo: '',		// 业务订单号 
+							transactionId: '',		// 微信支付订单号 
+							billMoney: '',		// 账单金额 
+							billImage: '',		// 账单截图 
+							status: '',		// 支付状态(0=未开票,1=已开票) 
+							invoiceTime: '',		// 开票时间 
+							createTime: '',		// 创建时间 
+							infoId: '',		// 开票信息id 
+						}
+					},
+					// 提交数据 
+					ok: function(){
+						// 表单校验 
+						let m = this.m;
+						// sa.checkNull(m.transactionId, '请输入 [微信支付订单号]');
+						// sa.checkNull(m.billMoney, '请输入 [账单金额]');
+						sa.checkNull(m.billImage, '请输入 [账单截图]');
+				
+						// 开始增加或修改
+						if(this.id <= 0) {	// 添加
+							sa.ajax('/TbInvoiceOrder/add', m, function(res){
+								sa.alert('增加成功', this.clean); 
+							}.bind(this));
+						} else {	// 修改
+							sa.ajax('/TbInvoiceOrder/update', m, function(res){
+								sa.alert('修改成功', this.clean);
+							}.bind(this));
+						}
+					},
+					// 添加/修改 完成后的动作
+					clean: function() {
+						if(this.id == 0) {
+							this.m = this.createModel();
+						} else {
+							parent.app.f5();		// 刷新父页面列表
+							sa.closeCurrIframe();	// 关闭本页 
+						}
+					}
+				},
+				mounted: function(){
+					// 初始化数据 
+					if(this.id <= 0) {	
+						this.m = this.createModel();
+					} else {	
+						sa.ajax('/TbInvoiceOrder/getById?id=' + this.id, function(res) {
+							this.m = res.data;
+							if(res.data == null) {
+								sa.alert('未能查找到 id=' + this.id + " 详细数据");
+							}
+						}.bind(this))
+					}
+				}
+			})
+			
+		</script>
+	</body>
+</html>

+ 71 - 0
sp-admin/sa-view/tb-invoice-order/tb-invoice-order-info.html

@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票订单表-详情</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+		<style type="text/css">
+			.c-panel .c-label{width: 8em;}
+		</style>
+	</head>
+	<body>
+		<div class="vue-box sbot" style="display: none;" :style="'display: block;'">
+			<!-- ------- 内容部分 ------- -->
+			<div class="s-body">
+				<div class="c-panel">
+					<el-form v-if="m">
+						<sa-info name="主键" br>{{m.id}}</sa-info>
+						<sa-info name="客户id" br>{{m.customerId}}</sa-info>
+						<sa-info name="业务订单id" br>{{m.businessId}}</sa-info>
+						<sa-info name="业务名称" br>{{m.businessName}}</sa-info>
+						<sa-info name="业务订单号" br>{{m.businessNo}}</sa-info>
+						<sa-info name="微信支付订单号" br>{{m.transactionId}}</sa-info>
+						<sa-info name="账单金额" br>{{m.billMoney}}</sa-info>
+						<sa-info type="img" name="账单截图" :value="m.billImage" br></sa-info>
+						<sa-info type="enum" name="开票状态" :value="m.status" :jv="{0: '未申请', 1: '已申请', 2: '已开票'}" br></sa-info>
+						<sa-info name="开票时间" br>{{m.invoiceTime}}</sa-info>
+						<sa-info name="创建时间" br>{{m.createTime}}</sa-info>
+						<sa-info name="开票信息id" br>{{m.infoId}}</sa-info>
+					</el-form>
+				</div>
+			</div>
+			<!-- ------- 底部按钮 ------- -->
+			<div class="s-foot">
+				<el-button type="success" @click="sa.closeCurrIframe()">确定</el-button>
+				<el-button @click="sa.closeCurrIframe()">取消</el-button>
+			</div>
+		</div>
+		<script>
+			var app = new Vue({
+				components: {
+					"sa-info": httpVueLoader('../../sa-frame/com/sa-info.vue')
+				},
+				el: '.vue-box',
+				data: {
+					id: sa.p('id', 0),	// 获取数据ID 
+					m: null
+				},
+				methods: {
+				},
+				mounted: function() {
+					sa.ajax('/TbInvoiceOrder/getById?id=' + this.id, function(res) {
+						this.m = res.data;
+						if(res.data == null) {
+							sa.alert('未能查找到 id=' + this.id + " 详细数据");
+						}
+					}.bind(this))
+				}
+			})
+			
+		</script>
+	</body>
+</html>

+ 267 - 0
sp-admin/sa-view/tb-invoice-order/tb-invoice-order-list.html

@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>开票订单表-列表</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<!-- 所有的 css & js 资源 -->
+		<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
+		<link rel="stylesheet" href="../../static/sa.css">
+		<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
+		<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
+		<script src="https://unpkg.com/http-vue-loader@1.4.2/src/httpVueLoader.js"></script>
+		<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"></script>
+		<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
+		<script src="../../static/sa.js"></script>
+	</head>
+	<style>
+		.c1-label{width: 7em; color: #333; padding-right: 4px; display: inline-block; text-align: right; vertical-align: top;}
+	</style>
+	<body>
+		<div class="vue-box" style="display: none;" :style="'display: block;'">
+			<div class="c-panel">
+				<!-- ------------- 检索参数 ------------- -->
+				<div class="c-title">检索参数</div>
+				<el-form ref="form" :model='p' @submit.native.prevent>
+					<div class="c-item">
+						<label class="c1-label">开票信息编号:</label>
+						<el-input type="text" v-model="p.infoNo"></el-input>
+					</div>
+					<div class="c-item">
+						<label class="c1-label">微信支付订单:</label>
+						<el-input type="text" v-model="p.transactionId"></el-input>
+					</div>
+					<div class="c-item">
+						<label class="c-label">开票状态:</label>
+						<el-select v-model="p.status" placeholder="请选择">
+							<el-option label="不限" value=""></el-option>
+							<el-option label="待申请" :value="0"></el-option>
+							<el-option label="已申请" :value="1"></el-option>
+							<el-option label="已开票" :value="2"></el-option>
+						</el-select>
+					</div>
+					<el-button type="primary" icon="el-icon-search" @click="p.pageNo = 1; f5()">查询</el-button>
+					<el-button size="mini" type="info" @click="sa.f5()">刷新</el-button>
+					<br />
+				</el-form>
+				<!-- ------------- 快捷按钮 ------------- -->
+				<el-form ref="form" :model='p' @submit.native.prevent>
+					<el-button style="display: inline;" type="primary"  @click="add()">上传账单截图</el-button>
+					<el-button style="display: inline;" type="primary"  @click="applyFn()">申请开票</el-button>
+				</el-form>
+				<!-- ------------- 数据列表 ------------- -->
+				<el-table class="data-table" ref="data-table" :data="dataList" >
+					<sa-td type="selection"></sa-td>
+
+					<sa-td name="业务名称" prop="businessName" ></sa-td>
+					<el-table-column label="业务订单号" width="150px">
+						<template slot-scope="s">
+							<el-tooltip :content="s.row.businessNo"placement="bottom"effect="light">
+								<el-button class="keyButton">{{ s.row.businessNo }}</el-button>
+							</el-tooltip>
+						</template>
+					</el-table-column>
+<!--					<sa-td name="业务订单号" prop="businessNo" width="150" ></sa-td>-->
+
+					<sa-td name="微信支付订单号" prop="transactionId" width="210px"></sa-td>
+					<sa-td name="账单金额" prop="billMoney" ></sa-td>
+					<sa-td name="账单截图" prop="billImage" type="img"></sa-td>
+					<sa-td name="开票状态" prop="status" type="enum" :jv="{0: '待申请', 1: '已申请', 2: '已开票'}"></sa-td>
+					<sa-td name="开票时间" prop="invoiceTime" ></sa-td>
+					<sa-td name="开票信息" prop="infoNo" width="130"></sa-td>
+					<el-table-column label="操作" fixed="right"  width="240px">
+						<template slot-scope="s">
+							<el-button class="c-btn" type="success" icon="el-icon-view" @click="get(s.row)">查看</el-button>
+							<el-button v-if="s.row.status==0" class="c-btn" type="danger" icon="el-icon-delete" @click="del(s.row)">删除</el-button>
+						</template>
+					</el-table-column>
+				</el-table>
+				<!-- ------------- 分页 ------------- -->
+				<sa-item type="page" :curr.sync="p.pageNo" :size.sync="p.pageSize" :total="dataCount" @change="f5()"></sa-item>
+			</div>
+			<el-dialog title="申请开票" :visible.sync="applyDate.visible" width="38%">
+				<sa-item name="发票总额" v-model="applyDate.form.totalMoney" type="num" :disabled="true"></sa-item>
+				<sa-item name="电子发票" v-model="applyDate.form.isElec" type="enum" :jv="{1: '是', 0: '否'}"></sa-item>
+				<div class="c-item">
+					<label class="c-label">开票主体:</label>
+					<el-select v-model="applyDate.form.entityId" placeholder="请选择" filterable @change="changeEntity">
+						<el-option v-for="item in entityList" :key="item.id"
+								   :label="item.name" :value="item.id">
+						</el-option>
+					</el-select>
+				</div>
+				<sa-item type="text" name="企业名称" v-model="applyDate.entity.name":disabled="true"></sa-item>
+				<sa-item type="text" name="税号" v-model="applyDate.entity.taxIdNo" :disabled="true"></sa-item>
+				<sa-item type="text" name="地址" v-model="applyDate.entity.address" :disabled="true"></sa-item>
+				<sa-item type="text" name="电话" v-model="applyDate.entity.phone" :disabled="true"></sa-item>
+				<sa-item type="text" name="开户银行" v-model="applyDate.entity.bank" :disabled="true"></sa-item>
+				<sa-item type="text" name="银行账号" v-model="applyDate.entity.bankNo" :disabled="true"></sa-item>
+				<span slot="footer" class="dialog-footer">
+					<el-button @click="emodel.visible = false">取 消</el-button>
+					<el-button type="primary" @click="apply">确 定</el-button>
+				</span>
+			</el-dialog>
+		</div>
+		<script>
+			var app = new Vue({
+				components: {
+					"sa-item": httpVueLoader('../../sa-frame/com/sa-item.vue'),  
+					"sa-td": httpVueLoader('../../sa-frame/com/sa-td.vue'),		
+				},
+				el: '.vue-box',
+				data: {
+					p: { // 查询参数  
+						id: '',		// 主键 、
+
+						customerId: '',		// 客户id 
+						businessId: '',		// 业务订单id 
+						businessName: '',		// 业务名称 
+						businessNo: '',		// 业务订单号 
+						transactionId: '',		// 微信支付订单号 
+						billMoney: '',		// 账单金额 
+						status: '',		// 支付状态(0=未开票,1=已开票) 
+						invoiceTime: '',		// 开票时间 
+						createTime: '',		// 创建时间 
+						infoId: '',		// 开票信息id
+						infoNo: '',     // 开票信息no
+						pageNo: 1,		// 当前页 
+						pageSize: 10,	// 页大小 
+						sortType: 0		// 排序方式 
+					},
+					dataCount: 0,
+					dataList: [], // 数据集合
+					entityList: [],
+					applyDate: {
+						visible: false,
+						form: {
+							ids: '',
+							entityId: '',
+							isElec: 1,
+							totalMoney: 0,
+							customerId: '',
+							customerName: '',
+						},
+						entity:{},
+					},
+					currentCustomerId: '1',
+					currentCustomerName: '',
+				},
+				methods: {
+					apply(){
+						sa.checkNull(this.applyDate.form.entityId, '请选择 [主体信息]');
+						sa.checkNull(this.applyDate.form.isElec, '请选择 [电子发票]');
+
+						sa.ajax('/TbInvoiceInfo/generate', this.applyDate.form, function(res){
+							sa.alert('成功生成开票信息');
+							this.applyDate.visible = false;
+							this.f5();
+						}.bind(this));
+					},
+					applyFn(){
+						let selection = this.$refs['data-table'].selection;
+						if(selection.length == 0) {
+							return sa.msg('请至少选择一条数据')
+						}
+						var ids = sa.getArrayField(selection, 'id');
+						for(var i=0; i<ids.length; i++){
+							if(this.dataList[i].status == 1){
+								return sa.msg('请选择未开票的订单')
+							}
+						}
+						let billMoneys = sa.getArrayField(selection, 'billMoney');
+						var totalMoney = 0;
+						for (var i=billMoneys.length-1; i>=0; i--) {
+							totalMoney += billMoneys[i];
+						}
+						this.applyDate.form.totalMoney = totalMoney;
+						this.applyDate.visible = true;
+						this.applyDate.form.ids = ids.join(',');
+						this.getEntityList();
+					},
+					changeEntity(value){
+						let entity = this.entityList.filter(obj => obj.id == value).pop();
+						this.applyDate.entity = entity;
+					},
+					getEntityList(){
+						sa.ajax('/TbEntity/getList', function(res) {
+							this.entityList = res.data; // 数据
+						}.bind(this));
+					},
+					getCustomer() {
+						sa.ajax('/TbCostomer/getCurrentCustomer', function(resp) {
+							this.currentCustomerId = resp.data.id;
+							this.currentCustomerName = resp.data.name;
+							this.applyDate.form.customerId = resp.data.id;
+							this.applyDate.form.customerName = resp.data.name;
+							console.log(resp.data)
+							console.log(this.currentCustomerId)
+							console.log(this.currentCustomerName)
+							console.log(this.applyDate.form.customerId)
+							console.log(this.applyDate.form.customerName)
+						}.bind(this));
+					},
+					// 刷新
+					f5: function() {
+						sa.ajax('/TbInvoiceOrder/getList', sa.removeNull(this.p), function(res) {
+							this.dataList = res.data; // 数据
+							this.dataCount = res.dataCount; // 数据总数 
+							sa.f5TableHeight();		// 刷新表格高度 
+						}.bind(this));
+					},
+					// 查看
+					get: function(data) {
+						sa.showIframe('数据详情', 'tb-invoice-order-info.html?id=' + data.id, '1050px', '90%');
+					},
+					// 查看 - 根据选中的
+					getBySelect: function(data) {
+						var selection = this.$refs['data-table'].selection;
+						if(selection.length == 0) {
+							return sa.msg('请选择一条数据')
+						}
+						this.get(selection[0]);
+					},
+					// 修改
+					update: function(data) {
+						sa.showIframe('修改数据', 'tb-invoice-order-add.html?id=' + data.id, '550px', '80%');
+					},
+					// 新增
+					add: function(data) {
+						sa.showIframe('新增数据', 'tb-invoice-order-add.html?id=-1&customerId=' + this.currentCustomerId, '550px', '80%');
+					},
+					// 删除
+					del: function(data) {
+						sa.confirm('是否删除,此操作不可撤销', function() {
+							sa.ajax('/TbInvoiceOrder/delete?id=' + data.id, function(res) {
+								sa.arrayDelete(this.dataList, data);
+								sa.ok('删除成功');
+								sa.f5TableHeight();		// 刷新表格高度 
+							}.bind(this))
+						}.bind(this));
+					},
+					// 批量删除
+					deleteByIds: function() {
+						// 获取选中元素的id列表 
+						let selection = this.$refs['data-table'].selection;
+						let ids = sa.getArrayField(selection, 'id');
+						if(selection.length == 0) {
+							return sa.msg('请至少选择一条数据')
+						}
+						// 提交删除 
+						sa.confirm('是否批量删除选中数据?此操作不可撤销', function() {
+							sa.ajax('/TbInvoiceOrder/deleteByIds', {ids: ids.join(',')}, function(res) {
+								sa.arrayDelete(this.dataList, selection);
+								sa.ok('删除成功');
+								sa.f5TableHeight();		// 刷新表格高度 
+							}.bind(this))
+						}.bind(this));
+					},
+				},
+				created: function() {
+					this.f5();
+					this.getCustomer();
+					sa.onInputEnter();
+				}
+			})
+		</script>
+	</body>
+</html>

+ 21 - 0
sp-admin/static/sa.js

@@ -744,6 +744,13 @@ var sa = {
 			} 
 			return false;
 		}
+		me.isTel = function(str) {
+			str = str + '';
+			if((/^1[345678]\d{9}$/.test(str))||(/0\d{2,3}-\d{7,8}/.test(str))){
+				return true;
+			}
+			return false;
+		}
 		me.isCarNo=function(str){
 			str=str+'';
 			let reg=/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/
@@ -759,6 +766,20 @@ var sa = {
 			} 
 			return false;
 		}
+		me.isEmail = function(str) {
+			str = str + '';
+			if((/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(str))){
+				return true;
+			}
+			return false;
+		}
+		me.isTaxId = function(str) {
+			str = str + '';
+			if((/^[A-Z0-9]{15}$|^[A-Z0-9]{18}$|^[A-Z0-9]{20}$/.test(str))){
+				return true;
+			}
+			return false;
+		}
 		
 		
 		// 产生随机字符串

+ 20 - 0
sp-server/src/main/java/com/pj/current/config/OcrConfig.java

@@ -0,0 +1,20 @@
+package com.pj.current.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Auther: lzm
+ * @Date: 2022/07/11/16:35
+ * @Description:
+ */
+@ConfigurationProperties(prefix = "ocr-config")
+@Component
+@Data
+public class OcrConfig {
+
+    private String bash;
+    private String analysis;
+
+}

+ 101 - 0
sp-server/src/main/java/com/pj/project/tb_entity/TbEntity.java

@@ -0,0 +1,101 @@
+package com.pj.project.tb_entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_entity -- 开票主体表
+ * @author lzm 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbEntity.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbEntity implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_entity";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-entity";	
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	public String id;
+
+
+
+	/**
+	 * 客户id 
+	 */
+	public String customerId;
+
+	/**
+	 * 企业名称 
+	 */
+	public String name;	
+
+	/**
+	 * 税号 
+	 */
+	public String taxIdNo;	
+
+	/**
+	 * 地址 
+	 */
+	public String address;	
+
+	/**
+	 * 电话 
+	 */
+	public String phone;	
+
+	/**
+	 * 开户银行 
+	 */
+	public String bank;	
+
+	/**
+	 * 银行账号 
+	 */
+	public String bankNo;	
+
+	/**
+	 * 邮箱 
+	 */
+	public String email;
+
+	/**
+	 * 创建时间 
+	 */
+	public Date createTime;
+
+	/**
+	 * 更新时间 
+	 */
+	public Date updateTime;
+
+
+
+
+
+	
+
+
+}

+ 111 - 0
sp-server/src/main/java/com/pj/project/tb_entity/TbEntityController.java

@@ -0,0 +1,111 @@
+package com.pj.project.tb_entity;
+
+import java.util.List;
+
+import cn.hutool.core.util.StrUtil;
+import com.pj.constants.UserTypeEnum;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_entity -- 开票主体表
+ * @author lzm 
+ */
+@RestController
+@RequestMapping("/TbEntity/")
+public class TbEntityController {
+
+	/** 底层 Service 对象 */
+	@Autowired
+	TbEntityService tbEntityService;
+
+	/** 增 */  
+	@RequestMapping("add")
+	@SaCheckPermission(TbEntity.PERMISSION_CODE)
+	@Transactional(rollbackFor = Exception.class)
+	public AjaxJson add(TbEntity t){
+		tbEntityService.add(t);
+		t = tbEntityService.getById(SP.publicMapper.getPrimarykey());
+		return AjaxJson.getSuccessData(t);
+	}
+
+	/** 删 */  
+	@RequestMapping("delete")
+	@SaCheckPermission(TbEntity.PERMISSION_CODE)
+	public AjaxJson delete(Long id){
+		int line = tbEntityService.delete(id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 删 - 根据id列表 */  
+	@RequestMapping("deleteByIds")
+	@SaCheckPermission(TbEntity.PERMISSION_CODE)
+	public AjaxJson deleteByIds(){
+		List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+		int line = SP.publicMapper.deleteByIds(TbEntity.TABLE_NAME, ids);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 改 */  
+	@RequestMapping("update")
+	@SaCheckPermission(TbEntity.PERMISSION_CODE)
+	public AjaxJson update(TbEntity t){
+		int line = tbEntityService.update(t);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 查 - 根据id */  
+	@RequestMapping("getById")
+	public AjaxJson getById(Long id){
+		TbEntity t = tbEntityService.getById(id);
+		return AjaxJson.getSuccessData(t);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	@RequestMapping("getList")
+	public AjaxJson getList() { 
+		SoMap so = SoMap.getRequestSoMap();
+        String cusotmerId = StpUserUtil.getCustomerId();
+        if (!StrUtil.equals(UserTypeEnum.PLATFORM_ADMIN.getCustomerId(), cusotmerId)) {
+            so.put("cusotmerId", cusotmerId);
+        }
+		List<TbEntity> list = tbEntityService.getList(so.startPage());
+		return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+	
+	
+	
+	
+	// ------------------------- 前端接口 -------------------------
+	
+	
+	/** 改 - 不传不改 [G] */
+	@RequestMapping("updateByNotNull")
+	public AjaxJson updateByNotNull(Long id){
+		AjaxError.throwBy(true, "如需正常调用此接口,请删除此行代码");
+		// 鉴别身份,是否为数据创建者 
+		long userId = SP.publicMapper.getColumnByIdToLong(TbEntity.TABLE_NAME, "user_id", id);
+		AjaxError.throwBy(userId != StpUserUtil.getLoginIdAsLong(), "此数据您无权限修改");
+		// 开始修改 (请只保留需要修改的字段)
+		SoMap so = SoMap.getRequestSoMap();
+		so.clearNotIn("id", "customerId", "name", "taxIdNo", "address", "phone", "bank", "bankNo", "eMail", "createTime", "updateTime").clearNull().humpToLineCase();	
+		int line = SP.publicMapper.updateBySoMapById(TbEntity.TABLE_NAME, so, id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	
+	
+	
+	
+	
+
+}

+ 56 - 0
sp-server/src/main/java/com/pj/project/tb_entity/TbEntityMapper.java

@@ -0,0 +1,56 @@
+package com.pj.project.tb_entity;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_entity -- 开票主体表
+ * @author lzm 
+ */
+
+@Mapper
+@Repository
+public interface TbEntityMapper extends BaseMapper<TbEntity> {
+
+	/**
+	 * 增  
+	 * @param t 实体对象 
+	 * @return 受影响行数 
+	 */
+	int add(TbEntity t);
+
+	/**
+	 * 删  
+	 * @param id 要删除的数据id  
+	 * @return 受影响行数 
+	 */
+	int delete(Long id);	 
+
+	/** 
+	 * 改  
+	 * @param t 实体对象 
+	 * @return 受影响行数 
+	 */
+	int update(TbEntity t);
+
+	/** 
+	 * 查 - 根据id  
+	 * @param id 要查询的数据id 
+	 * @return 实体对象 
+	 */
+	TbEntity getById(Long id);	 
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * @param so 参数集合 
+	 * @return 数据列表 
+	 */
+	List<TbEntity> getList(SoMap so);
+
+
+}

+ 108 - 0
sp-server/src/main/java/com/pj/project/tb_entity/TbEntityMapper.xml

@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_entity.TbEntityMapper">
+
+	<!-- 增 [G] -->
+	<insert id="add">
+		insert into 
+		tb_entity (id, customer_id, name, tax_id_no, address, phone, bank, bank_no, email, create_time, update_time)
+		values (#{id}, #{customerId}, #{name}, #{taxIdNo}, #{address}, #{phone}, #{bank}, #{bankNo}, #{email}, #{createTime}, #{updateTime})
+	</insert>
+
+	<!-- 删 -->
+	<delete id="delete">
+		delete from tb_entity 
+		where id = #{id}
+	</delete>
+
+	<!-- 改 [G] -->
+	<update id="update">
+		update tb_entity set
+		id = #{id}, 
+		customer_id = #{customerId}, 
+		name = #{name}, 
+		tax_id_no = #{taxIdNo}, 
+		address = #{address}, 
+		phone = #{phone}, 
+		bank = #{bank}, 
+		bank_no = #{bankNo}, 
+		email = #{email},
+		create_time = #{createTime}, 
+		update_time = #{updateTime}
+		where id = #{id}
+	</update>
+
+
+	<!-- ================================== 查询相关 ================================== -->
+	<!-- select id, customer_id, name, tax_id_no, address, phone, bank, bank_no, e_mail, create_time, update_time from tb_entity  -->
+	
+	<!-- 通用映射:手动模式 -->
+	<resultMap id="model" type="com.pj.project.tb_entity.TbEntity">
+		<result property="id" column="id" />
+		<result property="customerId" column="customer_id" />
+		<result property="name" column="name" />
+		<result property="taxIdNo" column="tax_id_no" />
+		<result property="address" column="address" />
+		<result property="phone" column="phone" />
+		<result property="bank" column="bank" />
+		<result property="bankNo" column="bank_no" />
+		<result property="email" column="email" />
+		<result property="createTime" column="create_time" />
+		<result property="updateTime" column="update_time" />
+	</resultMap>
+	
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select * 
+		from tb_entity 
+	</sql>
+	
+	<!-- 查 - 根据id -->
+	<select id="getById" resultMap="model">
+		<include refid="select_sql"></include>
+		where id = #{id}
+	</select>
+	
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+			<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("cusotmerId") '> and customer_id = #{cusotmerId} </if>
+			<if test=' this.has("name") '> and name like concat('%', #{name}, '%') </if>
+			<if test=' this.has("taxIdNo") '> and tax_id_no = #{taxIdNo} </if>
+			<if test=' this.has("address") '> and address = #{address} </if>
+			<if test=' this.has("phone") '> and phone = #{phone} </if>
+			<if test=' this.has("bank") '> and bank = #{bank} </if>
+			<if test=' this.has("bankNo") '> and bank_no = #{bankNo} </if>
+			<if test=' this.has("email") '> and email = #{email} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("updateTime") '> and update_time = #{updateTime} </if>
+		</where>
+		order by
+		<choose>
+			<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> customer_id desc </when>
+			<when test='sortType == 3'> name desc </when>
+			<when test='sortType == 4'> tax_id_no desc </when>
+			<when test='sortType == 5'> address desc </when>
+			<when test='sortType == 6'> phone desc </when>
+			<when test='sortType == 7'> bank desc </when>
+			<when test='sortType == 8'> bank_no desc </when>
+			<when test='sortType == 9'> email desc </when>
+			<when test='sortType == 10'> create_time desc </when>
+			<when test='sortType == 11'> update_time desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+	
+	
+	
+	
+	
+	
+	
+	
+	
+
+</mapper>

+ 55 - 0
sp-server/src/main/java/com/pj/project/tb_entity/TbEntityService.java

@@ -0,0 +1,55 @@
+package com.pj.project.tb_entity;
+
+import java.util.Date;
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.pj.utils.sg.*;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Service: tb_entity -- 开票主体表
+ * @author lzm 
+ */
+@Service
+@Transactional
+public class TbEntityService extends ServiceImpl<TbEntityMapper, TbEntity> implements IService<TbEntity> {
+
+	/** 底层 Mapper 对象 */
+	@Autowired
+	TbEntityMapper tbEntityMapper;
+
+	/** 增 */
+	int add(TbEntity t){
+        t.setCreateTime(new Date());
+		return tbEntityMapper.add(t);
+	}
+
+	/** 删 */
+	int delete(Long id){
+		return tbEntityMapper.delete(id);
+	}
+
+	/** 改 */
+	int update(TbEntity t){
+        t.setUpdateTime(new Date());
+	    return tbEntityMapper.update(t);
+	}
+
+	/** 查 */
+	TbEntity getById(Long id){
+		return tbEntityMapper.getById(id);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	List<TbEntity> getList(SoMap so) {
+		return tbEntityMapper.getList(so);	
+	}
+	
+
+}

+ 7 - 3
sp-server/src/main/java/com/pj/project/tb_fee_details/TbFeeDetailsMapper.xml

@@ -85,10 +85,14 @@
 			<if test=' this.has("payType") '> and pay_type = #{payType} </if>
 			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
             <if test=' this.has("beginTime") and this.has("endTime") '>
-                and pay_day >= #{beginTime}
-                and pay_day  &lt;= #{endTime}
-            </if>
+            and pay_day >= #{beginTime}
+            and pay_day  &lt;= #{endTime}
+        </if>
             <if test=' this.has("type")'> and fee_type in (${type}) </if>
+            <if test=' this.has("isInvoice")'>
+                <if test=' isInvoice == 0'> and invoice is null</if>
+                <if test=' isInvoice == 1'> and invoice is not null</if>
+            </if>
 		</where>
 		order by
 		<choose>

+ 137 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfo.java

@@ -0,0 +1,137 @@
+package com.pj.project.tb_invoice_info;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.pj.project.tb_entity.TbEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_invoice_info -- 开票信息表
+ * @author lzm 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbInvoiceInfo.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbInvoiceInfo implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_invoice_info";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-invoice-info";
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+    private String id;
+
+    private String no;
+
+	/**
+	 * 客户id 
+	 */
+	public String customerId;
+
+	/**
+	 * 客户名称 
+	 */
+    private String customerName;
+
+	/**
+	 * 账单金额 
+	 */
+    private BigDecimal totalMoney;
+
+	/**
+	 * 支付状态(0=未开票,1=已开票) 
+	 */
+    private Integer status;
+
+    /**
+     * 电子发票(0=否,1=是)
+     */
+    private String isElec;
+
+	/**
+	 * 开票时间 
+	 */
+    private Date invoiceTime;
+
+	/**
+	 * 发票号 
+	 */
+    private String invoiceNo;
+
+	/**
+	 * 主体id 
+	 */
+    private String  entityId;
+
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+
+
+    /**
+     * 主体名称
+     */
+    private String  entityName;
+
+    /**
+     * 税号
+     */
+    public String taxIdNo;
+
+    /**
+     * 地址
+     */
+    public String address;
+
+    /**
+     * 电话
+     */
+    public String phone;
+
+    /**
+     * 开户银行
+     */
+    public String bank;
+
+    /**
+     * 银行账号
+     */
+    public String bankNo;
+
+    /**
+     * 邮箱
+     */
+    public String email;
+
+
+
+
+
+	
+
+
+}

+ 136 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoController.java

@@ -0,0 +1,136 @@
+package com.pj.project.tb_invoice_info;
+
+import java.util.List;
+
+import cn.hutool.core.util.StrUtil;
+import com.pj.constants.UserTypeEnum;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_invoice_info -- 开票信息表
+ * @author lzm 
+ */
+@RestController
+@RequestMapping("/TbInvoiceInfo/")
+public class TbInvoiceInfoController {
+
+	/** 底层 Service 对象 */
+	@Autowired
+	TbInvoiceInfoService tbInvoiceInfoService;
+
+	/** 增 */  
+	@RequestMapping("add")
+	@SaCheckPermission(TbInvoiceInfo.PERMISSION_CODE)
+	@Transactional(rollbackFor = Exception.class)
+	public AjaxJson add(TbInvoiceInfo t){
+		tbInvoiceInfoService.add(t);
+		t = tbInvoiceInfoService.getById(SP.publicMapper.getPrimarykey());
+		return AjaxJson.getSuccessData(t);
+	}
+
+	/** 删 */  
+	@RequestMapping("delete")
+	@SaCheckPermission(TbInvoiceInfo.PERMISSION_CODE)
+	public AjaxJson delete(Long id){
+		int line = tbInvoiceInfoService.delete(id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 删 - 根据id列表 */  
+	@RequestMapping("deleteByIds")
+	@SaCheckPermission(TbInvoiceInfo.PERMISSION_CODE)
+	public AjaxJson deleteByIds(){
+		List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+		int line = SP.publicMapper.deleteByIds(TbInvoiceInfo.TABLE_NAME, ids);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 改 */  
+	@RequestMapping("update")
+	@SaCheckPermission(TbInvoiceInfo.PERMISSION_CODE)
+	public AjaxJson update(TbInvoiceInfo t){
+		int line = tbInvoiceInfoService.update(t);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 查 - 根据id */  
+	@RequestMapping("getById")
+	public AjaxJson getById(Long id){
+		TbInvoiceInfo t = tbInvoiceInfoService.getById(id);
+		return AjaxJson.getSuccessData(t);
+	}
+
+    /** 查 - 根据id */
+    @RequestMapping("getEntityById")
+    public AjaxJson getEntityById(Long id){
+        TbInvoiceInfo t = tbInvoiceInfoService.getEntityById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	@RequestMapping("getList")
+	public AjaxJson getList() { 
+		SoMap so = SoMap.getRequestSoMap();
+        String cusotmerId = StpUserUtil.getCustomerId();
+        if (!StrUtil.equals(UserTypeEnum.PLATFORM_ADMIN.getCustomerId(), cusotmerId)) {
+            so.put("customerId", cusotmerId);
+        }
+		List<TbInvoiceInfo> list = tbInvoiceInfoService.getList(so.startPage());
+		return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+
+    /** 生成信息 */
+    @RequestMapping("generate")
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxJson generate(){
+        SoMap so = SoMap.getRequestSoMap();
+        tbInvoiceInfoService.generate(so);
+        return AjaxJson.getSuccess();
+    }
+
+    /** 生成信息 */
+    @RequestMapping("complete")
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxJson complete(){
+        SoMap so = SoMap.getRequestSoMap();
+        tbInvoiceInfoService.complete(so);
+        return AjaxJson.getSuccess();
+    }
+	
+	
+	
+	
+	// ------------------------- 前端接口 -------------------------
+	
+	
+	/** 改 - 不传不改 [G] */
+	@RequestMapping("updateByNotNull")
+	public AjaxJson updateByNotNull(Long id){
+		AjaxError.throwBy(true, "如需正常调用此接口,请删除此行代码");
+		// 鉴别身份,是否为数据创建者 
+		long userId = SP.publicMapper.getColumnByIdToLong(TbInvoiceInfo.TABLE_NAME, "user_id", id);
+		AjaxError.throwBy(userId != StpUserUtil.getLoginIdAsLong(), "此数据您无权限修改");
+		// 开始修改 (请只保留需要修改的字段)
+		SoMap so = SoMap.getRequestSoMap();
+		so.clearNotIn("id", "customerId", "customerName", "totalMoney", "status", "invoiceTime", "invoiceNo", "entityId", "entityName", "taxIdNo", "address", "phone", "bank", "bankNo", "email", "createTime").clearNull().humpToLineCase();	
+		int line = SP.publicMapper.updateBySoMapById(TbInvoiceInfo.TABLE_NAME, so, id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	
+	
+	
+	
+	
+
+}

+ 56 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoMapper.java

@@ -0,0 +1,56 @@
+package com.pj.project.tb_invoice_info;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_invoice_info -- 开票信息表
+ * @author lzm 
+ */
+
+@Mapper
+@Repository
+public interface TbInvoiceInfoMapper extends BaseMapper<TbInvoiceInfo> {
+
+	/**
+	 * 增  
+	 * @param t 实体对象 
+	 * @return 受影响行数 
+	 */
+	int add(TbInvoiceInfo t);
+
+	/**
+	 * 删  
+	 * @param id 要删除的数据id  
+	 * @return 受影响行数 
+	 */
+	int delete(Long id);	 
+
+	/** 
+	 * 改  
+	 * @param t 实体对象 
+	 * @return 受影响行数 
+	 */
+	int update(TbInvoiceInfo t);
+
+	/** 
+	 * 查 - 根据id  
+	 * @param id 要查询的数据id 
+	 * @return 实体对象 
+	 */
+	TbInvoiceInfo getById(Long id);	 
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * @param so 参数集合 
+	 * @return 数据列表 
+	 */
+	List<TbInvoiceInfo> getList(SoMap so);
+
+
+}

+ 116 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoMapper.xml

@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_invoice_info.TbInvoiceInfoMapper">
+
+	<!-- 增 [G] -->
+	<insert id="add">
+		insert into
+		tb_invoice_info (id, no, customer_id, customer_name, total_money, status, invoice_time, invoice_no, entity_id, entity_name, tax_id_no, address, phone, bank, bank_no, email, create_time)
+		values (#{id}, #{no}, #{customerId}, #{customerName}, #{totalMoney}, #{status}, #{invoiceTime}, #{invoiceNo}, #{entityId}, #{entityName}, #{taxIdNo}, #{address}, #{phone}, #{bank}, #{bankNo}, #{email}, #{createTime})
+	</insert>
+
+	<!-- 删 -->
+	<delete id="delete">
+		delete from tb_invoice_info
+		where id = #{id}
+	</delete>
+
+	<!-- 改 [G] -->
+	<update id="update">
+		update tb_invoice_info set
+		id = #{id},
+		no = #{no},
+		customer_id = #{customerId},
+		customer_name = #{customerName},
+		total_money = #{totalMoney},
+		status = #{status},
+		invoice_time = #{invoiceTime},
+		invoice_no = #{invoiceNo},
+		entity_id = #{entityId},
+		entity_name = #{entityName},
+		tax_id_no = #{taxIdNo},
+		address = #{address},
+		phone = #{phone},
+		bank = #{bank},
+		bank_no = #{bankNo},
+		email = #{email},
+		create_time = #{createTime}
+		where id = #{id}
+	</update>
+
+
+	<!-- ================================== 查询相关 ================================== -->
+	<!-- select id, customer_id, customer_name, total_money, status, invoice_time, invoice_no, entity_id, entity_name, tax_id_no, address, phone, bank, bank_no, email, create_time from tb_invoice_info  -->
+
+	<!-- 通用映射:手动模式 -->
+	<resultMap id="model" type="com.pj.project.tb_invoice_info.TbInvoiceInfo">
+		<result property="id" column="id" />
+        <result property="no" column="no" />
+		<result property="customerId" column="customer_id" />
+		<result property="customerName" column="customer_name" />
+		<result property="totalMoney" column="total_money" />
+		<result property="status" column="status" />
+		<result property="invoiceTime" column="invoice_time" />
+		<result property="invoiceNo" column="invoice_no" />
+		<result property="entityId" column="entity_id" />
+        <result property="entityName" column="entity_Name" />
+        <result property="taxIdNo" column="tax_id_no" />
+        <result property="address" column="address" />
+        <result property="phone" column="phone" />
+        <result property="bank" column="bank" />
+        <result property="bankNo" column="bank_no" />
+        <result property="email" column="email" />
+		<result property="createTime" column="create_time" />
+	</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *
+		from tb_invoice_info
+	</sql>
+
+	<!-- 查 - 根据id -->
+	<select id="getById" resultMap="model">
+		<include refid="select_sql"></include>
+		where id = #{id}
+	</select>
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+			<if test=' this.has("id") '> and id = #{id} </if>
+            <if test=' this.has("no") '> and no = #{no} </if>
+			<if test=' this.has("customerId") '> and customer_id = #{customerId} </if>
+			<if test=' this.has("customerName") '> and customer_name like concat('%', #{customerName}, '%') </if>
+			<if test=' this.has("totalMoney") '> and total_money = #{totalMoney} </if>
+			<if test=' this.has("status") '> and status = #{status} </if>
+			<if test=' this.has("invoiceTime") '> and invoice_time = #{invoiceTime} </if>
+			<if test=' this.has("invoiceNo") '> and invoice_no = #{invoiceNo} </if>
+			<if test=' this.has("entityId") '> and entity_id = #{entityId} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+            <if test=' this.has("beginTime") and this.has("endTime") '>
+                and invoice_time >= #{beginTime}
+                and invoice_time  &lt;= #{endTime}
+            </if>
+		</where>
+		order by
+		<choose>
+			<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 5'> status desc </when>
+			<when test='sortType == 6'> invoice_time desc </when>
+			<when test='sortType == 16'> create_time desc </when>
+			<otherwise> create_time desc </otherwise>
+		</choose>
+	</select>
+	
+	
+	
+	
+	
+	
+	
+	
+	
+
+</mapper>

+ 133 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_info/TbInvoiceInfoService.java

@@ -0,0 +1,133 @@
+package com.pj.project.tb_invoice_info;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pj.project.tb_entity.TbEntity;
+import com.pj.project.tb_entity.TbEntityService;
+import com.pj.project.tb_fee_details.TbFeeDetails;
+import com.pj.project.tb_fee_details.TbFeeDetailsService;
+import com.pj.project.tb_invoice_order.TbInvoiceOrder;
+import com.pj.project.tb_invoice_order.TbInvoiceOrderService;
+import com.pj.utils.so.SoMap;
+import org.springframework.stereotype.Service;
+
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+/**
+ * Service: tb_invoice_info -- 开票信息表
+ * @author lzm 
+ */
+@Service
+@Transactional
+public class TbInvoiceInfoService extends ServiceImpl<TbInvoiceInfoMapper, TbInvoiceInfo> implements IService<TbInvoiceInfo> {
+
+	/** 底层 Mapper 对象 */
+    @Resource
+	TbInvoiceInfoMapper tbInvoiceInfoMapper;
+
+	@Resource
+    TbInvoiceOrderService tbInvoiceOrderService;
+    @Resource
+    TbEntityService tbEntityService;
+    @Resource
+    TbFeeDetailsService tbFeeDetailsService;
+
+
+	/** 增 */
+	int add(TbInvoiceInfo t){
+		return tbInvoiceInfoMapper.add(t);
+	}
+
+	/** 删 */
+	int delete(Long id){
+        List<TbInvoiceOrder> iOrderList = tbInvoiceOrderService.findByInfoId(id + "");
+        for (TbInvoiceOrder order : iOrderList) {
+            order.setInfoId("").setInfoNo("").setStatus(0);
+        }
+        tbInvoiceOrderService.updateBatchById(iOrderList);
+        return tbInvoiceInfoMapper.delete(id);
+	}
+
+	/** 改 */
+	int update(TbInvoiceInfo t){
+		return tbInvoiceInfoMapper.update(t);
+	}
+
+    /** 查 */
+    TbInvoiceInfo getById(Long id){
+        return tbInvoiceInfoMapper.getById(id);
+    }
+
+	/** 查 */
+	TbInvoiceInfo getEntityById(Long id){
+        TbInvoiceInfo t = tbInvoiceInfoMapper.getById(id);
+        return t;
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	List<TbInvoiceInfo> getList(SoMap so) {
+        List<TbInvoiceInfo> list = tbInvoiceInfoMapper.getList(so);
+        return list;
+	}
+
+
+    public void generate(SoMap so) {
+	    String orderIds = so.getString("ids");
+	    String entityId = so.getString("entityId");
+        String isElec = so.getString("isElec");
+        BigDecimal totalMoney = new BigDecimal(so.getString("totalMoney"));
+        String customerId = so.getString("customerId");
+        String customerName = so.getString("customerName");
+
+        TbEntity entity = tbEntityService.getById(entityId);
+        TbInvoiceInfo t = new TbInvoiceInfo();
+        t.setEntityId(entityId).setIsElec(isElec).setTotalMoney(totalMoney)
+        .setCustomerId(customerId).setCustomerName(customerName)
+        .setStatus(0)
+        .setCreateTime(new Date())
+        .setNo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + RandomUtil.randomNumbers(4))
+        .setEntityName(entity.getName()).setTaxIdNo(entity.getTaxIdNo()).setAddress(entity.getAddress())
+        .setBank(entity.getBank()).setBankNo(entity.getBankNo()).setEmail(entity.getEmail()).setPhone(entity.getPhone());
+        this.save(t);
+
+        List<String> orderIdList = Arrays.asList(orderIds.split(","));
+        List<TbInvoiceOrder> orderList = tbInvoiceOrderService.listByIds(orderIdList);
+        for (TbInvoiceOrder invoiceOrder : orderList) {
+            invoiceOrder.setInfoId(t.getId()).setInfoNo(t.getNo()).setStatus(1);
+        }
+        tbInvoiceOrderService.updateBatchById(orderList);
+    }
+
+    public void complete(SoMap so) {
+	    String id = so.getString("id");
+        Date invoiceTime = so.getDateTime("invoiceTime");
+        String invoiceNo = so.getString("invoiceNo");
+        TbInvoiceInfo t = this.getById(id);
+        t.setInvoiceTime(invoiceTime).setInvoiceNo(invoiceNo).setStatus(1);
+        this.updateById(t);
+        List<TbInvoiceOrder> invoiceOrderList = tbInvoiceOrderService.findByInfoId(id);
+        for (TbInvoiceOrder invoiceOrder : invoiceOrderList) {
+            List<TbFeeDetails> feeDetailsList = tbFeeDetailsService.findByTransactionId(invoiceOrder.getTransactionId());
+            for (TbFeeDetails detail : feeDetailsList) {
+                String invoice = detail.getInvoice();
+                invoice = StrUtil.isEmpty(invoice) ? invoiceNo : invoice+","+invoiceNo;
+                detail.setInvoice(invoice);
+            }
+            tbFeeDetailsService.updateBatchById(feeDetailsList);
+            invoiceOrder.setStatus(2).setInvoiceTime(new Date());
+        }
+        tbInvoiceOrderService.updateBatchById(invoiceOrderList);
+    }
+
+}

+ 110 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrder.java

@@ -0,0 +1,110 @@
+package com.pj.project.tb_invoice_order;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_invoice_order -- 开票订单表
+ * @author lzm 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbInvoiceOrder.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbInvoiceOrder implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_invoice_order";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-invoice-order";	
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	public String id;
+
+	/**
+	 * 客户id 
+	 */
+	public String customerId;
+
+	/**
+	 * 业务订单id 
+	 */
+	public String businessId;	
+
+	/**
+	 * 业务名称 
+	 */
+	public String businessName;	
+
+	/**
+	 * 业务订单号 
+	 */
+	public String businessNo;	
+
+	/**
+	 * 微信支付订单号 
+	 */
+	public String transactionId;	
+
+	/**
+	 * 账单金额 
+	 */
+	public BigDecimal billMoney;
+
+	/**
+	 * 账单截图 
+	 */
+	public String billImage;	
+
+	/**
+	 * 支付状态(0=未申请,1=已申请,2=已开票)
+	 */
+	public Integer status;
+
+	/**
+	 * 开票时间 
+	 */
+	public Date invoiceTime;
+
+	/**
+	 * 创建时间 
+	 */
+	public Date createTime;
+
+	/**
+	 * 开票信息id 
+	 */
+	public String infoId;
+
+    /**
+     * 开票信息id
+     */
+    public String infoNo;
+
+
+
+
+
+
+
+
+}

+ 113 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderController.java

@@ -0,0 +1,113 @@
+package com.pj.project.tb_invoice_order;
+
+import java.util.List;
+
+import cn.hutool.core.util.StrUtil;
+import com.pj.constants.UserTypeEnum;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_invoice_order -- 开票订单表
+ * @author lzm 
+ */
+@RestController
+@RequestMapping("/TbInvoiceOrder/")
+public class TbInvoiceOrderController {
+
+	/** 底层 Service 对象 */
+	@Autowired
+	TbInvoiceOrderService tbInvoiceOrderService;
+
+	/** 增 */  
+	@RequestMapping("add")
+	@SaCheckPermission(TbInvoiceOrder.PERMISSION_CODE)
+	@Transactional(rollbackFor = Exception.class)
+	public AjaxJson add(TbInvoiceOrder t){
+		tbInvoiceOrderService.add(t);
+		t = tbInvoiceOrderService.getById(SP.publicMapper.getPrimarykey());
+		return AjaxJson.getSuccessData(t);
+	}
+
+	/** 删 */  
+	@RequestMapping("delete")
+	@SaCheckPermission(TbInvoiceOrder.PERMISSION_CODE)
+	public AjaxJson delete(Long id){
+		int line = tbInvoiceOrderService.delete(id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 删 - 根据id列表 */  
+	@RequestMapping("deleteByIds")
+	@SaCheckPermission(TbInvoiceOrder.PERMISSION_CODE)
+	public AjaxJson deleteByIds(){
+		List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+		int line = SP.publicMapper.deleteByIds(TbInvoiceOrder.TABLE_NAME, ids);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 改 */  
+	@RequestMapping("update")
+	@SaCheckPermission(TbInvoiceOrder.PERMISSION_CODE)
+	public AjaxJson update(TbInvoiceOrder t){
+		int line = tbInvoiceOrderService.update(t);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 查 - 根据id */  
+	@RequestMapping("getById")
+	public AjaxJson getById(Long id){
+		TbInvoiceOrder t = tbInvoiceOrderService.getById(id);
+		return AjaxJson.getSuccessData(t);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	@RequestMapping("getList")
+	public AjaxJson getList() { 
+		SoMap so = SoMap.getRequestSoMap();
+        String cusotmerId = StpUserUtil.getCustomerId();
+        if (!StrUtil.equals(UserTypeEnum.PLATFORM_ADMIN.getCustomerId(), cusotmerId)) {
+            so.put("customerId", cusotmerId);
+        }
+		List<TbInvoiceOrder> list = tbInvoiceOrderService.getList(so.startPage());
+		return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+
+
+	
+	
+	
+	
+	// ------------------------- 前端接口 -------------------------
+	
+	
+	/** 改 - 不传不改 [G] */
+	@RequestMapping("updateByNotNull")
+	public AjaxJson updateByNotNull(Long id){
+		AjaxError.throwBy(true, "如需正常调用此接口,请删除此行代码");
+		// 鉴别身份,是否为数据创建者 
+		long userId = SP.publicMapper.getColumnByIdToLong(TbInvoiceOrder.TABLE_NAME, "user_id", id);
+		AjaxError.throwBy(userId != StpUserUtil.getLoginIdAsLong(), "此数据您无权限修改");
+		// 开始修改 (请只保留需要修改的字段)
+		SoMap so = SoMap.getRequestSoMap();
+		so.clearNotIn("id", "customerId", "businessId", "businessName", "businessNo", "transactionId", "billMoney", "billImage", "status", "invoiceTime", "createTime", "infoId").clearNull().humpToLineCase();	
+		int line = SP.publicMapper.updateBySoMapById(TbInvoiceOrder.TABLE_NAME, so, id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	
+	
+	
+	
+	
+
+}

+ 56 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderMapper.java

@@ -0,0 +1,56 @@
+package com.pj.project.tb_invoice_order;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_invoice_order -- 开票订单表
+ * @author lzm 
+ */
+
+@Mapper
+@Repository
+public interface TbInvoiceOrderMapper extends BaseMapper<TbInvoiceOrder> {
+
+	/**
+	 * 增  
+	 * @param t 实体对象 
+	 * @return 受影响行数 
+	 */
+	int add(TbInvoiceOrder t);
+
+	/**
+	 * 删  
+	 * @param id 要删除的数据id  
+	 * @return 受影响行数 
+	 */
+	int delete(Long id);	 
+
+	/** 
+	 * 改  
+	 * @param t 实体对象 
+	 * @return 受影响行数 
+	 */
+	int update(TbInvoiceOrder t);
+
+	/** 
+	 * 查 - 根据id  
+	 * @param id 要查询的数据id 
+	 * @return 实体对象 
+	 */
+	TbInvoiceOrder getById(Long id);	 
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * @param so 参数集合 
+	 * @return 数据列表 
+	 */
+	List<TbInvoiceOrder> getList(SoMap so);
+
+
+}

+ 113 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderMapper.xml

@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_invoice_order.TbInvoiceOrderMapper">
+
+	<!-- 增 [G] -->
+	<insert id="add">
+		insert into 
+		tb_invoice_order (id, customer_id, business_id, business_name, business_no, transaction_id, bill_money, bill_image, status, invoice_time, create_time, info_id, info_no)
+		values (#{id}, #{customerId}, #{businessId}, #{businessName}, #{businessNo}, #{transactionId}, #{billMoney}, #{billImage}, #{status}, #{invoiceTime}, #{createTime}, #{infoId},#{infoNo})
+	</insert>
+
+	<!-- 删 -->
+	<delete id="delete">
+		delete from tb_invoice_order 
+		where id = #{id}
+	</delete>
+
+	<!-- 改 [G] -->
+	<update id="update">
+		update tb_invoice_order set
+		id = #{id}, 
+		customer_id = #{customerId}, 
+		business_id = #{businessId}, 
+		business_name = #{businessName}, 
+		business_no = #{businessNo}, 
+		transaction_id = #{transactionId}, 
+		bill_money = #{billMoney}, 
+		bill_image = #{billImage}, 
+		status = #{status}, 
+		invoice_time = #{invoiceTime}, 
+		create_time = #{createTime}, 
+		info_id = #{infoId},
+		info_no = #{infoNo}
+		where id = #{id}
+	</update>
+
+
+	<!-- ================================== 查询相关 ================================== -->
+	<!-- select id, customer_id, business_id, business_name, business_no, transaction_id, bill_money, bill_image, status, invoice_time, create_time, info_id from tb_invoice_order  -->
+	
+	<!-- 通用映射:手动模式 -->
+	<resultMap id="model" type="com.pj.project.tb_invoice_order.TbInvoiceOrder">
+		<result property="id" column="id" />
+		<result property="customerId" column="customer_id" />
+		<result property="businessId" column="business_id" />
+		<result property="businessName" column="business_name" />
+		<result property="businessNo" column="business_no" />
+		<result property="transactionId" column="transaction_id" />
+		<result property="billMoney" column="bill_money" />
+		<result property="billImage" column="bill_image" />
+		<result property="status" column="status" />
+		<result property="invoiceTime" column="invoice_time" />
+		<result property="createTime" column="create_time" />
+		<result property="infoId" column="info_id" />
+        <result property="infoNo" column="info_no" />
+	</resultMap>
+	
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select * 
+		from tb_invoice_order 
+	</sql>
+	
+	<!-- 查 - 根据id -->
+	<select id="getById" resultMap="model">
+		<include refid="select_sql"></include>
+		where id = #{id}
+	</select>
+	
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+			<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("customerId") '> and customer_id = #{customerId} </if>
+			<if test=' this.has("businessId") '> and business_id = #{businessId} </if>
+			<if test=' this.has("businessName") '> and business_name = #{businessName} </if>
+			<if test=' this.has("businessNo") '> and business_no = #{businessNo} </if>
+			<if test=' this.has("transactionId") '> and transaction_id = #{transactionId} </if>
+			<if test=' this.has("billMoney") '> and bill_money = #{billMoney} </if>
+			<if test=' this.has("status") '> and status = #{status} </if>
+			<if test=' this.has("invoiceTime") '> and invoice_time = #{invoiceTime} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("infoId") '> and info_id = #{infoId} </if>
+            <if test=' this.has("infoNo") '> and info_no = #{infoNo} </if>
+		</where>
+		order by
+		<choose>
+			<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> customer_id desc </when>
+			<when test='sortType == 3'> business_id desc </when>
+			<when test='sortType == 4'> business_name desc </when>
+			<when test='sortType == 5'> business_no desc </when>
+			<when test='sortType == 6'> transaction_id desc </when>
+			<when test='sortType == 7'> bill_money desc </when>
+			<when test='sortType == 8'> status desc </when>
+			<when test='sortType == 9'> invoice_time desc </when>
+			<when test='sortType == 10'> create_time desc </when>
+			<when test='sortType == 11'> info_id desc </when>
+			<otherwise> create_time desc </otherwise>
+		</choose>
+	</select>
+	
+	
+	
+	
+	
+	
+	
+	
+	
+
+</mapper>

+ 192 - 0
sp-server/src/main/java/com/pj/project/tb_invoice_order/TbInvoiceOrderService.java

@@ -0,0 +1,192 @@
+package com.pj.project.tb_invoice_order;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.time.Month;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import cn.hutool.core.io.file.FileReader;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pj.api.wx.bo.Attach;
+import com.pj.api.wx.bo.PriceBO;
+import com.pj.current.config.MyConfig;
+import com.pj.current.config.OcrConfig;
+import com.pj.project.tb_business.TbBusiness;
+import com.pj.project.tb_business.TbBusinessService;
+import com.pj.project.tb_business_car.TbBusinessCar;
+import com.pj.project.tb_business_car.TbBusinessCarService;
+import com.pj.project.tb_goods.TbGoods;
+import com.pj.project.tb_goods.TbGoodsService;
+import com.pj.project.tb_order.TbOrder;
+import com.pj.project.tb_order.TbOrderService;
+import com.pj.project4sp.global.BusinessException;
+import com.pj.project4sp.uploadfile.UploadUtil;
+import com.pj.utils.OcrUtils;
+import com.pj.utils.so.SoMap;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+/**
+ * Service: tb_invoice_order -- 开票订单表
+ * @author lzm 
+ */
+@Service
+@Transactional
+@Slf4j
+public class TbInvoiceOrderService extends ServiceImpl<TbInvoiceOrderMapper, TbInvoiceOrder> implements IService<TbInvoiceOrder> {
+
+	/** 底层 Mapper 对象 */
+    @Resource
+	TbInvoiceOrderMapper tbInvoiceOrderMapper;
+	@Resource
+    TbOrderService tbOrderService;
+	@Resource
+    TbBusinessService tbBusinessService;
+	@Resource
+    TbGoodsService tbGoodsService;
+    @Resource
+    TbBusinessCarService tbBusinessCarService;
+    @Resource
+    MyConfig myConfig;
+    @Resource
+    OcrConfig ocrConfig;
+
+	/** 增 */
+	int add(TbInvoiceOrder t){
+        String result = orcImage(t.getBillImage());
+        String transactionId = getTransId(result);
+//        if(StrUtil.isEmpty(t.getTransactionId())){
+//            String result = orcImage(t.getBillImage());
+//            transactionId = getTransId(result);
+//        }else{
+//            transactionId = t.getTransactionId();
+//        }
+
+        TbInvoiceOrder InOrder = findByTransactionId(transactionId);
+        if(InOrder != null){
+            throw new BusinessException("该账单已生成开票订单");
+        }
+        List<String> businessNameList = new ArrayList<>();
+        List<String> businessNoList = new ArrayList<>();
+        TbOrder tbOrder = tbOrderService.findByTransactionId(transactionId);
+        if(tbOrder == null){
+            throw new BusinessException("不存在该交易单号的业务订单");
+        }
+        BigDecimal billMoney = new BigDecimal(tbOrder.getPrice());
+        String attachStr = tbOrder.getAttach();
+        Attach attach = JSONUtil.toBean(attachStr, Attach.class);
+        String businessId = attach.getB();
+        if (StrUtil.isNotEmpty(businessId)) {
+            List<String> businessIds = StrUtil.splitTrim(businessId, ",");
+            List<TbBusiness> businessList = tbBusinessService.listByIds(businessIds);
+            for (TbBusiness tbBusiness : businessList) {
+                businessNoList.add(tbBusiness.getNo());
+                TbGoods good = tbGoodsService.getById(tbBusiness.getGoodsId());
+                businessNameList.add(good.getName());
+            }
+        }
+        List<PriceBO> cars = JSONUtil.toList(attach.getC(), PriceBO.class);
+        if(cars.size()>0){
+            businessNameList.add("停车费");
+            for (PriceBO bo1 : cars) {
+                TbBusinessCar car = tbBusinessCarService.getById(bo1.getId());
+                businessNoList.add(car.getNo());
+            }
+        }
+
+        String businessNameStr = businessNameList.stream().map(String::valueOf).collect(Collectors.joining(","));
+        String businessNoStr = businessNoList.stream().map(String::valueOf).collect(Collectors.joining(","));
+        t.setBusinessName(businessNameStr).setBusinessNo(businessNoStr).setStatus(1)
+                .setTransactionId(transactionId).setBillMoney(billMoney)
+                .setStatus(0).setCreateTime(new Date());
+        return tbInvoiceOrderMapper.add(t);
+	}
+
+	/** 删 */
+	int delete(Long id){
+		return tbInvoiceOrderMapper.delete(id);
+	}
+
+	/** 改 */
+	int update(TbInvoiceOrder t){
+		return tbInvoiceOrderMapper.update(t);
+	}
+
+	/** 查 */
+	TbInvoiceOrder getById(Long id){
+		return tbInvoiceOrderMapper.getById(id);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	List<TbInvoiceOrder> getList(SoMap so) {
+		return tbInvoiceOrderMapper.getList(so);	
+	}
+
+    public TbInvoiceOrder findByTransactionId(String transactionId) {
+        QueryWrapper<TbInvoiceOrder> ew = new QueryWrapper<>();
+        ew.eq("transaction_id", transactionId);
+        return getOne(ew);
+    }
+
+    public List<TbInvoiceOrder> findByInfoId(String infoId) {
+        QueryWrapper<TbInvoiceOrder> ew = new QueryWrapper<>();
+        ew.eq("info_id", infoId);
+        return list(ew);
+    }
+
+    private String orcImage(String billImageUrl){
+        String separator = File.separator;
+        int startIndex = StrUtil.lastIndexOf(billImageUrl, "/", billImageUrl.length(), false);
+        int endIndex = StrUtil.lastIndexOf(billImageUrl, ".", billImageUrl.length(), false);
+        String picName =  StrUtil.sub(billImageUrl, startIndex+1, endIndex);
+        String rootPath = UploadUtil.uploadConfig.rootFolder + separator + UploadUtil.uploadConfig.httpPrefix;
+        String prefix = myConfig.getDomain() + UploadUtil.uploadConfig.httpPrefix;
+        String path = billImageUrl.replaceAll(prefix, rootPath);
+        String command = "sh " + ocrConfig.getBash() + " " + path + " " + picName;
+        OcrUtils.exceShell(command);
+        String analyPath = ocrConfig.getAnalysis().replace("PIC_NAME", picName);
+        FileReader reader = new FileReader(analyPath);
+        String result = reader.readString();
+        result = result.replace("\n","").replace(" ","");
+        return result;
+    }
+    private static String getTransId(String content) {
+        int index = StrUtil.indexOf(content, "420000", 0, false);
+        String sub = StrUtil.sub(content, index, index+28);
+        sub=sub.trim();
+        String transId = "";
+        for (int i=0; i<sub.length();i++){
+            if(sub.charAt(i)>=48 && sub.charAt(i)<=57){
+                transId += sub.charAt(i);
+            }
+        }
+        log.info("transId:" + transId);
+        return transId;
+    }
+    private static BigDecimal getMoney(String content) {
+
+        int index = StrUtil.indexOf(content, ".", 0, false);
+        String sub = StrUtil.sub(content, index -5, index+3);
+        sub=sub.trim();
+        String money = "";
+        for (int i=0; i<sub.length();i++){
+            if(sub.charAt(i)>=48 && sub.charAt(i)<=57 || sub.charAt(i) == '.'){
+                money += sub.charAt(i);
+            }
+        }
+        log.info("账单金额 :", money);
+        return new BigDecimal(money);
+    }
+
+}

+ 7 - 0
sp-server/src/main/java/com/pj/project/tb_order/TbOrderService.java

@@ -87,4 +87,11 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
         ew.eq("out_trade_no", outTradeNo);
         return getOne(ew);
     }
+
+    public TbOrder findByTransactionId(String transactionId) {
+        QueryWrapper<TbOrder> ew = new QueryWrapper<>();
+        ew.eq("transaction_id", transactionId);
+        ew.eq("order_status", "SUCCESS");
+        return getOne(ew);
+    }
 }

+ 53 - 0
sp-server/src/main/java/com/pj/utils/OcrUtils.java

@@ -0,0 +1,53 @@
+package com.pj.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Auther: lzm
+ */
+@Slf4j
+public class OcrUtils {
+
+    /**
+     * @param pathOrCommand 脚本路径或者命令
+     * @return
+     */
+    public static List<String> exceShell(String pathOrCommand) {
+
+        log.info("command :" + pathOrCommand);
+        List<String> result = new ArrayList<>();
+
+        try {
+            // 执行脚本
+            Process ps = Runtime.getRuntime().exec(pathOrCommand);
+            int exitValue = ps.waitFor();
+            if (0 != exitValue) {
+                //System.out.println("call shell failed. error code is :" + exitValue);
+                log.info("call shell failed. error code is :" + exitValue);
+            }
+
+            // 只能接收脚本echo打印的数据,并且是echo打印的最后一次数据
+            BufferedInputStream in = new BufferedInputStream(ps.getInputStream());
+            BufferedReader br = new BufferedReader(new InputStreamReader(in));
+            String line;
+            while ((line = br.readLine()) != null) {
+                //System.out.println("脚本返回的数据如下: " + line);
+                log.info("脚本返回的数据如下" + line);
+                result.add(line);
+            }
+            in.close();
+            br.close();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+
+}