index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. <template>
  2. <div id="print">
  3. <el-tabs v-model="activeName" type="border-card" stretch @tab-click="handleClick">
  4. <el-tab-pane label="温湿度信息" name="first">
  5. <div id="body" :style="{width: width - 300 + 'px'}">
  6. <!-- 单据信息 -->
  7. <el-timeline>
  8. <el-timeline>
  9. <el-descriptions>
  10. <el-descriptions-item label="订单编号">{{this.basicData.billCode}}</el-descriptions-item>
  11. <el-descriptions-item label="车牌号">{{this.basicData.plateNumber}}</el-descriptions-item>
  12. </el-descriptions>
  13. <el-descriptions>
  14. <el-descriptions-item label="开始时间">{{this.basicData.startTime}}</el-descriptions-item>
  15. <el-descriptions-item label="结束时间">{{this.basicData.endTime}}</el-descriptions-item>
  16. </el-descriptions>
  17. <!--导出按钮-->
  18. <el-button class="OutCss" v-print="'#print'" type="primary">导出</el-button>
  19. </el-timeline>
  20. </el-timeline>
  21. <el-timeline>
  22. <!-- 数据表 -->
  23. <h2>订单温湿度列表</h2>
  24. <el-table :data="tableData2" stripe border style="width: 97%">
  25. <el-table-column prop="measuringPointName" label="车牌号或保温箱" align="center" min-width="150" />
  26. <el-table-column prop="measuringPointAddr" label="探头" align="center" min-width="90" />
  27. <el-table-column prop="temperature" label="温度" align="center" min-width="80" />
  28. <el-table-column prop="hisDate" label="时间点" align="center" min-width="200" />
  29. <el-table-column prop="measuringPointName1" label="车牌号或保温箱" align="center" min-width="150" />
  30. <el-table-column prop="measuringPointAddr1" label="探头" align="center" min-width="90" />
  31. <el-table-column prop="temperature1" label="温度" align="center" min-width="80" />
  32. <el-table-column prop="hisDate1" label="时间点" align="center" min-width="200" />
  33. <!-- <el-table-column prop="address" label="地址" width="400" /> -->
  34. </el-table>
  35. </el-timeline>
  36. </div>
  37. <br>
  38. <div id="body" :style="{width: width - 300 + 'px'}">
  39. <el-timeline>
  40. <h2>订单温度折线图</h2>
  41. <div class="echart" id="mychart" :style="myChartStyle"></div>
  42. </el-timeline>
  43. </div>
  44. </el-tab-pane>
  45. <el-tab-pane label="运输信息" name="second">
  46. <div id="body" :style="{width: width - 300 + 'px'}">
  47. <!-- 单据信息 -->
  48. <el-timeline>
  49. <el-timeline>
  50. <el-descriptions>
  51. <el-descriptions-item label="订单编号">{{this.basicData.billCode}}</el-descriptions-item>
  52. <el-descriptions-item label="车牌号">{{this.basicData.plateNumber}}</el-descriptions-item>
  53. </el-descriptions>
  54. <el-descriptions>
  55. <el-descriptions-item label="开始时间">{{this.basicData.startTime}}</el-descriptions-item>
  56. <el-descriptions-item label="结束时间">{{this.basicData.endTime}}</el-descriptions-item>
  57. </el-descriptions>
  58. </el-timeline>
  59. </el-timeline>
  60. <!-- 地图 -->
  61. <div id="container"></div>
  62. <!-- 订单温湿度列表 -->
  63. <el-timeline>
  64. <br>
  65. <h2>订单温湿度列表</h2>
  66. <el-table :data="tableData1" height="200" style="width: 97%">
  67. <el-table-column prop="maxTemperature" label="温度最大值" align="center" min-width="100" />
  68. <el-table-column prop="avgTemperature" label="温度平均值" align="center" min-width="100" />
  69. <el-table-column prop="minTemperature" label="温度最小值" align="center" min-width="100" />
  70. <el-table-column prop="maxHumidity" label="湿度最大值" align="center" min-width="100" />
  71. <el-table-column prop="avgHumidity" label="湿度平均值" align="center" min-width="100" />
  72. <el-table-column prop="minHumidity" label="湿度最小值" align="center" min-width="100" />
  73. <el-table-column prop="startTime" label="开始时间" align="center" min-width="250" />
  74. <el-table-column prop="endTime" label="结束时间" align="center" min-width="250" />
  75. </el-table>
  76. </el-timeline>
  77. </div>
  78. </el-tab-pane>
  79. </el-tabs>
  80. </div>
  81. </template>
  82. <script>
  83. import AMapLoader from '@amap/amap-jsapi-loader'
  84. window._AMapSecurityConfig = {
  85. securityJsCode: '8e23904a0cf421675353f31fd1fc213c'
  86. }
  87. import historyApi from '@/api/WMS/historical-route'
  88. import * as echarts from "echarts";
  89. export default {
  90. data() {
  91. return {
  92. width: document.documentElement.clientWidth - 10,
  93. param: this.$route.query,
  94. basicData: {
  95. billCode: "",
  96. plateNumber: "",
  97. startTime: "",
  98. endTime: ""
  99. },
  100. //标签页
  101. activeName: 'first',
  102. //地图对象
  103. map: null,
  104. //图表
  105. myChart: {},
  106. xData: [], //横坐标
  107. temperatureData: [], //温度数据
  108. humidityData: [], //湿度数据
  109. myChartStyle: {
  110. float: "left",
  111. width: "100%",
  112. height: "400px"
  113. }, //图表样式
  114. //运输信息表单数据
  115. tableData1: [],
  116. //运输信息表单数据准备
  117. modelData1: [{
  118. maxTemperature: "",
  119. avgTemperature: "",
  120. minTemperature: "",
  121. maxHumidity: "",
  122. avgHumidity: "",
  123. minHumidity: "",
  124. startTime: "",
  125. endTime: ""
  126. }],
  127. //温湿度信息表单数据
  128. tableData2: [],
  129. resData: [],
  130. carMessage: {
  131. billCode: "",
  132. plateNumber: "",
  133. boxCode: [],
  134. startTime: "",
  135. endTime: ""
  136. },
  137. option: {},
  138. //表单各值
  139. maxT: 0,
  140. maxH: 0,
  141. minT: 0,
  142. minH: 0,
  143. aggT: 0,
  144. aggH: 0,
  145. avgT: 0,
  146. avgH: 0
  147. };
  148. },
  149. mounted() {
  150. //DOM初始化完成进行地图初始化
  151. this.initMap();
  152. },
  153. created() {
  154. //把传参中的保温箱转换成数组
  155. this.carMessage = this.$route.query;
  156. if (this.carMessage.boxCode != null) {
  157. this.carMessage.boxCode = this.$route.query.boxCode.split(',');
  158. }
  159. //当结束时间为空时,默认为当前时间
  160. if (this.carMessage.endTime == '' || this.carMessage.endTime == null) {
  161. this.carMessage.endTime = this.formatDateTime(this.getCurrentTime(), 'yyyy-MM-dd HH:mm:ss');
  162. }
  163. console.log(this.carMessage, 'this.carMessage')
  164. this.handleGeocodeRepo(this.carMessage);
  165. },
  166. methods: {
  167. //通过传参查询数据
  168. handleGeocodeRepo(data) {
  169. historyApi.queryAddress(data).then(res => {
  170. console.log(res, 'res-----------------');
  171. if (res.code == 200) {
  172. //定义路线数组
  173. let path = [];
  174. //筛选含经纬度的数组
  175. let latitudeLongitude = [];
  176. let count = 0;
  177. for (let i = 0; i < res.data.length; i++) {
  178. if (res.data[i].gpsLatitude != 0 && res.data[i].gpsLongitude != 0) {
  179. latitudeLongitude[count++] = res.data[i];
  180. }
  181. }
  182. //定义整数递增值,并且绘制初始路径
  183. if (latitudeLongitude.length >= 14) {
  184. this.increment = Math.trunc(latitudeLongitude.length / 14);
  185. for (let i = 0; i < latitudeLongitude.length; i = i + this.increment) {
  186. path.push([latitudeLongitude[i].gpsLongitude, latitudeLongitude[i].gpsLatitude]);
  187. }
  188. } else {
  189. for (let i = 0; i < latitudeLongitude.length; i++) {
  190. path.push([latitudeLongitude[i].gpsLongitude, latitudeLongitude[i].gpsLatitude]);
  191. }
  192. }
  193. //计算各值
  194. this.calculate(res.data);
  195. //对订单温湿度列表进行赋值
  196. this.assignmentTable1(res.data);
  197. //提取探头种类数量
  198. let probeSum = [];
  199. let probe = [];
  200. for (let i = 0; i < latitudeLongitude.length; i++) {
  201. probeSum[i] = latitudeLongitude[i].measuringPointAddr;
  202. }
  203. probe = Array.from(new Set(probeSum));
  204. //车辆温度数组
  205. let c, d;
  206. this.initEcharts();
  207. for (let i = 0; i < probe.length; i++) {
  208. let carForm = {
  209. name: this.carMessage.plateNumber + '/' + probe[i],
  210. data: [],
  211. type: "line",
  212. smooth: true,
  213. showSymbol: false,
  214. label: {
  215. show: true,
  216. position: "top",
  217. textStyle: {
  218. fontSize: 12
  219. }
  220. },
  221. markArea: {
  222. itemStyle: {
  223. color: 'rgba(255, 0, 0)'
  224. },
  225. data: [
  226. [{
  227. name: '冷藏温度警戒线',
  228. yAxis: '8'
  229. },
  230. {
  231. yAxis: '8.1'
  232. }
  233. ],
  234. [{
  235. name: '冷藏温度警戒线',
  236. yAxis: '2'
  237. },
  238. {
  239. yAxis: '1.9'
  240. }
  241. ],
  242. [{
  243. name: '冷冻温度警戒线',
  244. yAxis: '-15'
  245. },
  246. {
  247. yAxis: '-14.9'
  248. }
  249. ],
  250. [{
  251. name: '冷冻温度警戒线',
  252. yAxis: '-25'
  253. },
  254. {
  255. yAxis: '-25.1'
  256. }
  257. ]
  258. ]
  259. }
  260. }
  261. // count = 0;
  262. for (let j = 0; j < latitudeLongitude.length; j++) {
  263. if (carForm.name.indexOf(latitudeLongitude[j].measuringPointAddr) != -1) {
  264. c = latitudeLongitude[j].hisDate;
  265. d = latitudeLongitude[j].temperature;
  266. carForm.data.push([c, d]);
  267. }
  268. }
  269. this.option.series.push(carForm);
  270. this.option.legend.data.push(carForm.name);
  271. }
  272. //筛选保温箱的数组
  273. if (this.carMessage.boxCode != null) {
  274. let e, f;
  275. for (let i = 0; i < this.carMessage.boxCode.length; i++) {
  276. let boxForm = {
  277. name: this.carMessage.boxCode[i],
  278. data: [],
  279. type: "line",
  280. smooth: true,
  281. showSymbol: false,
  282. label: {
  283. show: true,
  284. position: "top",
  285. textStyle: {
  286. fontSize: 12
  287. }
  288. },
  289. markArea: {
  290. itemStyle: {
  291. color: 'rgba(255, 0, 0)'
  292. },
  293. data: [
  294. [{
  295. name: '冷藏温度警戒线',
  296. yAxis: '8'
  297. },
  298. {
  299. yAxis: '8.1'
  300. }
  301. ],
  302. [{
  303. name: '冷藏温度警戒线',
  304. yAxis: '2'
  305. },
  306. {
  307. yAxis: '1.9'
  308. }
  309. ],
  310. [{
  311. name: '冷冻温度警戒线',
  312. yAxis: '-15'
  313. },
  314. {
  315. yAxis: '-14.9'
  316. }
  317. ],
  318. [{
  319. name: '冷冻温度警戒线',
  320. yAxis: '-25'
  321. },
  322. {
  323. yAxis: '-25.1'
  324. }
  325. ]
  326. ]
  327. }
  328. }
  329. // count = 0;
  330. for (let j = 0; j < res.data.length; j++) {
  331. if (boxForm.name == res.data[j].measuringPointName) {
  332. e = res.data[j].hisDate;
  333. f = res.data[j].temperature;
  334. boxForm.data.push([e, f]);
  335. }
  336. }
  337. this.option.series.push(boxForm);
  338. this.option.legend.data.push(boxForm.name);
  339. }
  340. }
  341. //如果车辆温度数组为空,则其它数组前移一位
  342. for (let i = 1;;) {
  343. if (this.option.series[0].data.length == 0) {
  344. for (let j = 0; j < this.option.series.length - i; j++) {
  345. this.option.series[j] = this.option.series[j + 1];
  346. this.option.legend.data[j] = this.option.legend.data[j + 1];
  347. }
  348. this.option.series[this.option.series.length - i] = '';
  349. this.option.legend.data[this.option.series.length - i++] = '';
  350. }
  351. if (this.option.series[0].data.length != 0) {
  352. break;
  353. }
  354. }
  355. this.windowSize();
  356. //对基础数据进行赋值
  357. this.basicData.billCode = this.carMessage.billCode;
  358. this.basicData.plateNumber = this.carMessage.plateNumber;
  359. this.basicData.startTime = this.xData[0];
  360. this.basicData.endTime = this.xData[this.xData.length - 1];
  361. //基本地图加载
  362. this.loadMap(path);
  363. }
  364. })
  365. },
  366. handleClick(tab, event) {
  367. console.log(tab, event);
  368. this.handleGeocodeRepo(this.carMessage);
  369. },
  370. //地图初始化
  371. initMap() {
  372. AMapLoader.load({
  373. //申请好的Web端开发者Key,首次调用 load 时必填
  374. key: 'f953210b2d5276ffbf5a2bc01ef80f55',
  375. //指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
  376. version: '2.0',
  377. //需要使用的的插件列表,如比例尺'AMap.Scale'等
  378. plugins: ['']
  379. })
  380. .then(AMap => {
  381. this.map = new AMap.Map('container', {
  382. //设置地图容器id
  383. //是否为3D地图模式
  384. viewMode: '3D',
  385. //初始化地图级别
  386. zoom: 13,
  387. //初始化地图中心点位置
  388. center: [112.976376, 28.195318]
  389. })
  390. })
  391. .catch(e => {
  392. console.log(e)
  393. })
  394. },
  395. //基本地图加载
  396. loadMap(path) {
  397. var map, route;
  398. map = new AMap.Map("container", {
  399. resizeEnable: true
  400. });
  401. map.plugin("AMap.DragRoute", function () {
  402. //构造拖拽导航类
  403. route = new AMap.DragRoute(map, path, AMap.DrivingPolicy.LEAST_FEE);
  404. //查询导航路径并开启拖拽导航
  405. route.search();
  406. });
  407. },
  408. //图表属性赋值
  409. initEcharts() {
  410. this.option = {
  411. tooltip: {
  412. trigger: 'axis',
  413. axisPointer: {
  414. type: 'cross'
  415. }
  416. },
  417. grid: {
  418. x: 22,
  419. y: 30,
  420. x2: 20,
  421. y2: 18,
  422. borderWidth: 1,
  423. },
  424. toolbox: {
  425. //保存图
  426. // show: true,
  427. // feature: {
  428. // saveAsImage: {}
  429. // }
  430. },
  431. xAxis: {
  432. type: 'category',
  433. boundaryGap: false,
  434. data: this.xData
  435. },
  436. //图例
  437. legend: {
  438. data: [],
  439. // bottom: "0%"
  440. },
  441. yAxis: {
  442. name: '温度',
  443. // Y轴最大值
  444. max: 10,
  445. // Y轴最大值
  446. min: -30,
  447. splitNumber: 2,
  448. // 间隔值
  449. // interval: 3
  450. },
  451. //加上dataZoom可实现缩放
  452. dataZoom: [{
  453. //x轴
  454. type: 'slider',
  455. xAxisIndex: 0,
  456. },
  457. {
  458. //x轴
  459. type: 'inside',
  460. xAxisIndex: 0,
  461. /**
  462. * 如何触发缩放。可选值为:true:表示不按任何功能键,鼠标滚轮能触发缩放。false:表示鼠标滚轮不能触发缩放。
  463. * 'shift':表示按住 shift和鼠标滚轮能触发缩放。
  464. * 'ctrl':表示按住 ctrl 和鼠标滚轮能触发缩放。'alt':表示按住 alt 和鼠标滚轮能触发缩放。
  465. */
  466. zoomOnMouseWheel: 'true',
  467. },
  468. ],
  469. /**
  470. * series中的参数:
  471. * smooth:是否曲线,showSymbol:是否显示数据和数据点
  472. */
  473. series: [],
  474. }
  475. },
  476. //渲染图表
  477. windowSize() {
  478. this.myChart = echarts.init(document.getElementById("mychart"));
  479. this.myChart.setOption(this.option);
  480. window.addEventListener("resize", () => {
  481. this.myChart.resize();
  482. });
  483. },
  484. //计算各值
  485. calculate(array) {
  486. //数组中的温度湿度的字符串转成浮点
  487. for (let i = 0; i < array.length; i++) {
  488. array[i].temperature = parseFloat(array[i].temperature);
  489. array[i].humidity = parseFloat(array[i].humidity);
  490. }
  491. //定义初始值
  492. this.maxT = array[0].temperature;
  493. this.maxH = array[0].humidity;
  494. this.minT = array[0].temperature;
  495. this.minH = array[0].humidity;
  496. this.aggT = 0;
  497. this.aggH = 0;
  498. let x = [];
  499. for (let i = 0; i < array.length; i++) {
  500. //对X轴的时间进行赋值
  501. x[i] = array[i].hisDate;
  502. //对Y轴的温度进行赋值
  503. // this.temperatureData[i] = array[i].temperature;
  504. //温度最大值
  505. if (array[i].temperature > this.maxT) {
  506. this.maxT = array[i].temperature;
  507. }
  508. //湿度最大值
  509. if (array[i].humidity > this.maxH) {
  510. this.maxH = array[i].humidity;
  511. }
  512. //温度最小值
  513. if (array[i].temperature < this.minT) {
  514. this.minT = array[i].temperature
  515. }
  516. //湿度最小值
  517. if (array[i].humidity < this.minH) {
  518. this.minH = array[i].humidity
  519. }
  520. //温湿度合计值
  521. this.aggT += array[i].temperature;
  522. this.aggH += array[i].humidity;
  523. }
  524. //x数组去重
  525. x = Array.from(new Set(x));
  526. let xSort = [];
  527. for (let i = 0; i < x.length; i++) {
  528. xSort[i] = new Date(x[i]);
  529. }
  530. xSort.sort(function (a, b) {
  531. return a - b;
  532. })
  533. for (let i = 0; i < xSort.length; i++) {
  534. x[i] = this.formatDateTime(xSort[i], 'yyyy-MM-dd HH:mm:ss');
  535. }
  536. this.xData = x;
  537. //温湿度平均值
  538. this.avgT = this.aggT / array.length;
  539. this.avgH = this.aggH / array.length;
  540. },
  541. //对订单温湿度列表进行赋值
  542. assignmentTable1(array) {
  543. this.modelData1[0].maxTemperature = this.maxT;
  544. this.modelData1[0].maxHumidity = this.maxH;
  545. this.modelData1[0].minTemperature = this.minT;
  546. this.modelData1[0].minHumidity = this.minH;
  547. this.modelData1[0].avgTemperature = this.avgT.toFixed(2);
  548. this.modelData1[0].avgHumidity = this.avgH.toFixed(1);
  549. this.modelData1[0].startTime = array[0].hisDate;
  550. this.modelData1[0].endTime = array[array.length - 1].hisDate;
  551. this.tableData1 = this.modelData1;
  552. let median = (array.length / 2).toFixed(0);
  553. let table = []
  554. for (let i = 0; i < median; i++) {
  555. table[i] = {
  556. measuringPointName: '',
  557. measuringPointAddr: '',
  558. temperature: '',
  559. hisDate: '',
  560. measuringPointName1: '',
  561. measuringPointAddr1: '',
  562. temperature1: '',
  563. hisDate1: ''
  564. }
  565. }
  566. if (array.length % 2 == 0) {
  567. for (let i = 0, j = 0, z = 1; i < median; i++, j = j + 2, z = z + 2) {
  568. table[i].measuringPointName = array[j].measuringPointName;
  569. table[i].measuringPointAddr = array[j].measuringPointAddr;
  570. table[i].temperature = array[j].temperature;
  571. table[i].hisDate = array[j].hisDate;
  572. table[i].measuringPointName1 = array[z].measuringPointName;
  573. table[i].measuringPointAddr1 = array[z].measuringPointAddr;
  574. table[i].temperature1 = array[z].temperature;
  575. table[i].hisDate1 = array[z].hisDate;
  576. }
  577. } else {
  578. for (let i = 0, j = 0, z = 1; i < median; i++, j = j + 2, z = z + 2) {
  579. table[i].measuringPointName = array[j].measuringPointName;
  580. table[i].measuringPointAddr = array[j].measuringPointAddr;
  581. table[i].temperature = array[j].temperature;
  582. table[i].hisDate = array[j].hisDate;
  583. if (i != median - 1) {
  584. table[i].measuringPointName1 = array[z].measuringPointName;
  585. table[i].measuringPointAddr1 = array[z].measuringPointAddr;
  586. table[i].temperature1 = array[z].temperature;
  587. table[i].hisDate1 = array[z].hisDate;
  588. }
  589. }
  590. }
  591. this.tableData2 = table;
  592. },
  593. //获取当前时间
  594. getCurrentTime() {
  595. let date = new Date();
  596. return date;
  597. },
  598. //日期名称格式化
  599. formatDateTime(date, format) {
  600. const o = {
  601. 'M+': date.getMonth() + 1, // 月份
  602. 'd+': date.getDate(), // 日
  603. 'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, // 小时
  604. 'H+': date.getHours(), // 小时
  605. 'm+': date.getMinutes(), // 分
  606. 's+': date.getSeconds(), // 秒
  607. 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
  608. S: date.getMilliseconds(), // 毫秒
  609. a: date.getHours() < 12 ? '上午' : '下午', // 上午/下午
  610. A: date.getHours() < 12 ? 'AM' : 'PM', // AM/PM
  611. };
  612. if (/(y+)/.test(format)) {
  613. format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  614. }
  615. for (let k in o) {
  616. if (new RegExp('(' + k + ')').test(format)) {
  617. format = format.replace(
  618. RegExp.$1,
  619. RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
  620. );
  621. }
  622. }
  623. return format;
  624. },
  625. }
  626. };
  627. </script>
  628. <style scoped>
  629. #container {
  630. padding: 100px;
  631. margin: 10px;
  632. width: 1000;
  633. height: 800px;
  634. }
  635. .OutCss {
  636. float: right;
  637. }
  638. #body {
  639. /* padding: 0px 200px 0px 200px; */
  640. margin: 0 auto;
  641. }
  642. @media print {
  643. @page {
  644. margin: 0;
  645. size: portrait;
  646. /* size: A4 landscape; size: landscape横向,size: portrait;纵向,如果不设置,则页面有横向和纵向的选择框 */
  647. }
  648. #body {
  649. /* margin: 20cm; */
  650. margin: 0 auto;
  651. /* 打印时缩放,防止页面溢出 */
  652. zoom: 0.6;
  653. }
  654. }
  655. </style>