主頁 > 企業開發 > 記錄--前端小票列印、網頁列印

記錄--前端小票列印、網頁列印

2023-05-27 07:43:25 企業開發

這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

 一、小票列印

目前市面上的小票列印機大多采用的列印指令集為ESC/POS指令,它可以使用ASCII碼、十進制、十六進制來控制列印,我們可以使用它來控制字體大小、列印排版、字體加粗、下劃線、走紙、切紙、控制錢箱等,下面以初始化列印機為例:

ASCII碼  ESC  @
十進制碼  27  64
十六進制  1B  40

小票列印紙的寬度一般可分58mm和80mm,這里指的是列印紙的寬度,但是在實際列印的時候,有效列印區域并沒有這么寬,

 列印機紙寬58mm,頁的寬度384,字符寬度為1,每行最多盛放32個字符
 列印機紙寬80mm,頁的寬度576,字符寬度為1,每行最多盛放48個字符

上面說的字符指的是列印到小票上的內容,其中數字和字母占1個字符,中文占2個字符,也就是說,如果使用58mm的列印紙,一行最多可以列印16個漢字或者32個數字 ,

當然這是在不改變字體大小的情況下,如果我們改變了字體大小,那么一行盛放的內容也會改變,

//控制字符大小

ASCII碼   GS  !   n
十進制碼  29  33  n
十六進制  1D  21  n

1.這里的n是一個變數, 0 ≤ n ≤ 255 

2.用二進制表示,n的取值范圍就是00000000到11111111,其中二進制的前四位用來控制寬度,后四位用來控制高度,0000表示不變0001表示放大2倍0002表示放大3倍,以此類推

3.該命令對所有字符(英數字符和漢字) 有效,

4.預設值:n = 0

 下面我們來看一下字符的不同放大倍數(這里的1倍,表示使用默認大小):

放大倍數n(二進制)n(十進制)
寬度1倍,高度1倍 00000000 0
寬度1倍,高度2倍 00000001 1
寬度1倍,高度3倍 00000002 2
寬度2倍,高度1倍 00010000 16
寬度2倍,高度2倍 00010001 17
寬度2倍,高度3倍 00010002 18
寬度3倍,高度1倍 00020000 32
寬度3倍,高度2倍 00020001 33
寬度3倍,高度3倍 00020002 34

 

PS:列印紙時間有些長,字跡有些模糊,見諒

 列印指令封裝

// 列印機紙寬58mm,頁的寬度384,字符寬度為1,每行最多盛放32個字符
// 列印機紙寬80mm,頁的寬度576,字符寬度為1,每行最多盛放48個字符
const PAGE_WIDTH = 576;
const MAX_CHAR_COUNT_EACH_LINE = 48;

//字串轉位元組序列
function stringToByte(str) {
  var bytes = new Array();
  var len, c;
  len = str.length;
  for (var i = 0; i < len; i++) {
    c = str.charCodeAt(i);
    if (c >= 0x010000 && c <= 0x10FFFF) {
      bytes.push(((c >> 18) & 0x07) | 0xF0);
      bytes.push(((c >> 12) & 0x3F) | 0x80);
      bytes.push(((c >> 6) & 0x3F) | 0x80);
      bytes.push((c & 0x3F) | 0x80);
    } else if (c >= 0x000800 && c <= 0x00FFFF) {
      bytes.push(((c >> 12) & 0x0F) | 0xE0);
      bytes.push(((c >> 6) & 0x3F) | 0x80);
      bytes.push((c & 0x3F) | 0x80);
    } else if (c >= 0x000080 && c <= 0x0007FF) {
      bytes.push(((c >> 6) & 0x1F) | 0xC0);
      bytes.push((c & 0x3F) | 0x80);
    } else {
      bytes.push(c & 0xFF);
    }
  }
  return bytes;
}

//位元組序列轉ASCII碼
//[0x24, 0x26, 0x28, 0x2A] ==> "$&C*"
function byteToString(arr) {
  if (typeof arr === 'string') {
    return arr;
  }
  var str = '',
    _arr = arr;
  for (var i = 0; i < _arr.length; i++) {
    var one = _arr[i].toString(2),
      v = one.match(/^1+?(?=0)/);
    if (v && one.length == 8) {
      var bytesLength = v[0].length;
      var store = _arr[i].toString(2).slice(7 - bytesLength);
      for (var st = 1; st < bytesLength; st++) {
        store += _arr[st + i].toString(2).slice(2);
      }
      str += String.fromCharCode(parseInt(store, 2));
      i += bytesLength - 1;
    } else {
      str += String.fromCharCode(_arr[i]);
    }
  }
  return str;
}
//居中
function Center() {
  var Center = [];
  Center.push(27);
  Center.push(97);
  Center.push(1);
  var strCenter = byteToString(Center);
  return strCenter;
}

//居左
function Left() {
  var Left = [];
  Left.push(27);
  Left.push(97);
  Left.push(0);
  var strLeft = byteToString(Left);
  return strLeft;
}
//居右
function Right() {
  var right = [];
  Left.push(27);
  Left.push(97);
  Left.push(2);
  var strRight = byteToString(right);
  return strRight;
}
//標準字體
function Size1() {
  var Size1 = [];
  Size1.push(29);
  Size1.push(33);
  Size1.push(0);
  var strSize1 = byteToString(Size1);
  return strSize1;
}
//大號字體
/*  放大1倍  n = 0
 *  長寬各放大2倍  n = 17 */
function Size2(n) {
  var Size2 = [];
  Size2.push(29);
  Size2.push(33);
  Size2.push(n);
  var strSize2 = byteToString(Size2);
  return strSize2;
}

// 字體加粗
function boldFontOn() {
  var arr = []
  arr.push(27)
  arr.push(69)
  arr.push(1)
  var cmd = byteToString(arr);
  return cmd
}
// 取消字體加粗
function boldFontOff() {
  var arr = []
  arr.push(27)
  arr.push(69)
  arr.push(0)
  var cmd = byteToString(arr);
  return cmd
}
// 列印并走紙n行
function feedLines(n = 1) {
  var feeds = []
  feeds.push(27)
  feeds.push(100)
  feeds.push(n)
  var printFeedsLines = byteToString(feeds);
  return printFeedsLines
}
// 切紙
function cutPaper() {
  var cut = []
  cut.push(29)
  cut.push(86)
  cut.push(49)
  var cutType = byteToString(cut);
  return cutType
}

// 開錢箱
function open_money_box() {
  var open = []
  open.push(27)
  open.push(112)
  open.push(0)
  open.push(60)
  open.push(255)
  var openType = byteToString(open)
  return openType
}

// 初始化列印機
function init() {
  var arr = []
  arr.push(27)
  arr.push(68)
  arr.push(0)
  var str = byteToString(arr)
  return str
}
/* 
 設定左邊距
 len:
 */

function setLeftMargin(len = 1) {
  var arr = []
  arr.push(29)
  arr.push(76)
  arr.push(len)
  var str = byteToString(arr)
  return str
}

// 設定列印區域寬度
function setPrintAreaWidth(width) {
  var arr = []
  arr.push(29)
  arr.push(87)
  arr.push(width)
  var str = byteToString(arr)
  return str
}

/**
 * @param str
 * @returns {boolean} str是否全是中文
 */
function isChinese(str) {
  return /^[\u4e00-\u9fa5]$/.test(str);
}

// str是否全含中文或者中文標點
function isHaveChina(str) {
  if (escape(str).indexOf("%u") < 0) {
    return 0
  } else {
    return 1
  }
}
/**
 * 回傳字串寬度(1個中文=2個英文字符)
 * @param str
 * @returns {number}
 */
function getStringWidth(str) {
  let width = 0;
  for (let i = 0, len = str.length; i < len; i++) {
    width += isHaveChina(str.charAt(i)) ? 2 : 1;
  }
  return width;
}

/**
 * 同一行輸出str1, str2,str1居左, str2居右
 * @param {string} str1 內容1
 * @param {string} str2 內容2
 * @param {string} fillWith str1 str2之間的填充字符
 * @param {number} fontWidth 字符寬度 1/2
 *
 */
function inline(str1, str2, fillWith = ' ', fontWidth = 1) {
  const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
  // 需要填充的字符數量
  let fillCount = lineWidth - (getStringWidth(str1) + getStringWidth(str2)) % lineWidth;
  let fillStr = new Array(fillCount).fill(fillWith.charAt(0)).join('');
  return str1 + fillStr + str2;
}
/**
 * 用字符填充一整行
 * @param {string} fillWith 填充字符
 * @param {number} fontWidth 字符寬度 1/2
 */
function fillLine(fillWith = '-', fontWidth = 1) {
  const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
  return new Array(lineWidth).fill(fillWith.charAt(0)).join('');
}

/**
 * 文字內容居中,左右用字符填充
 * @param {string} str 文字內容
 * @param {number} fontWidth 字符寬度 1/2
 * @param {string} fillWith str1 str2之間的填充字符
 */
function fillAround(str, fillWith = '-', fontWidth = 1) {
  const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
  let strWidth = getStringWidth(str);
  // 內容已經超過一行了,沒必要填充
  if (strWidth >= lineWidth) {
    return str;
  }
  // 需要填充的字符數量
  let fillCount = lineWidth - strWidth;
  // 左側填充的字符數量
  let leftCount = Math.round(fillCount / 2);
  // 兩側的填充字符,需要考慮左邊需要填充,右邊不需要填充的情況
  let fillStr = new Array(leftCount).fill(fillWith.charAt(0)).join('');
  return fillStr + str + fillStr.substr(0, fillCount - leftCount);
}

也就是說,如果我們使用的列印機采用的是ESC/POS指令集(我這里使用過佳博、芯燁、斯普瑞特列印機),只要我們想辦法把列印指令發送給列印機,列印機就可以識別到并且進行列印等操作,那么我們該如何發送呢?

1.藍牙列印機

參考掘金 zgt_不夢的文章 微信小程式連接藍牙列印機列印圖片示例

  • 初始化藍牙模塊 wx.openBluetoothAdapter()
  • 初始化完成后搜尋附近的藍牙設備 wx.startBluetoothDevicesDiscovery()
  • 監聽尋找到新設備的事件 wx.onBluetoothDeviceFound()
  • 在監聽尋找到新設備的事件回呼中獲取所有藍牙設備串列 wx.getBluetoothDevices()
  • 連接低功耗藍牙設備 wx.createBLEConnection()
  • 連接成功后獲取藍牙設備服務 wx.getBLEDeviceServices()
  • 在服務中取(notify=true || indicate=true) && write=true 的特征值的 uuid: wx.getBLEDeviceCharacteristics()
  • 完成后停止搜尋 wx.stopBluetoothDevicesDiscovery()
  • 向低功耗藍牙設備特征值中寫入二進制資料 wx.writeBLECharacteristicValue()
  • 離開頁面時取消藍牙連接 wx.closeBLEConnection()
  • 關閉藍牙模塊 wx.closeBluetoothAdapter()

親測,好使!在uniapp也可以,只需替換對應的API即可

2.網口列印機

這里我使用的scoket連接,相比于USB列印,這里需要保證列印機和安卓設備在同一局域網下,好處是安卓設備可以和列印機距離較遠(比如廚房列印),這里以斯普瑞特列印機為例:[斯普瑞特官網 www.sprinter.com.cn/ 在進行資料通信之前,我們需要知道列印機在此局域網下的 IP, 下圖為“一鍵配網”工具

image.png  通過這個工具我們可以方便快捷的查詢到列印機的IP,或者可以根據空閑的網段來修改默認分配的IP,斯普瑞特POS列印機的埠是9100,

image.png

如果是其他品牌的列印機,我們也可以使用arp命令來查看當前局域網下的IP

拿到列印機的IP之后我們怎么來測驗一下列印機呢?

我們可以使用telnet命令(這個在Windows系統一般默認是關閉的,需要我們手動打開)

//telnet + 空格 + ip + 空格 + 埠號
telnet 192.168.5.6 9100

打開命令列視窗輸入telnet命令,按下回車

image.png

 如果埠關倍訓者無法連接,則顯示不能打開到主機的鏈接,鏈接失敗;埠打開的情況下,鏈接成功,則進入telnet頁面(全黑的),證明埠可用,

連接成功后,我們輸入任何內容后,按下回車,列印機就會列印我們剛才輸入的內容,

接下來我們要使用scoket來連接安卓設備和列印機,這里我使用的是uniapp

/**
 * 呼叫tcp通信進行列印
 * @param {buffer}  buffer       列印資料
 * @param {object}  printerInfo  列印機物件{IP:'',PORT:''}
 */
function tcpWrite(buffer, printerInfo) {
  var Socket = plus.android.importClass("java.net.Socket");
  var PrintWriter = plus.android.importClass("java.io.PrintWriter");
  var BufferedWriter = plus.android.importClass("java.io.BufferedWriter");
  var OutputStreamWriter = plus.android.importClass("java.io.OutputStreamWriter");
  var BufferedReader = plus.android.importClass("java.io.BufferedReader");
  var InputStreamReader = plus.android.importClass("java.io.InputStreamReader");
  var InetSocketAddress = plus.android.importClass("java.net.InetSocketAddress");
  //連接  注意:這里的埠一定是數字型別
  var sk = null
  try {
    sk = new Socket(printerInfo.IP, Number(printerInfo.PORT));
    sk.setSoTimeout(5000);
  } catch (e) {
    console.log(e, 'ee')
    uni.showToast({
      icon: 'none',
      title: '列印機連接失敗'
    })
  }
  //發送
  try {
    var outputStreamWriter = new OutputStreamWriter(sk.getOutputStream(), "GBK");
    var bufferWriter = new BufferedWriter(outputStreamWriter);
    var out = new PrintWriter(bufferWriter, true);
    out.println(buffer);
    //關閉tcp連接
    out.close();
  } catch (e) {
    console.log(e, 'ee')
    uni.showToast({
      icon: 'none',
      title: '列印機資料傳輸失敗'
    })
  }
}

列印小票

目前我們已經可以開心的使用列印功能了,只需要組合一下列印指令即可,這里需要注意的是,如果我們在此之前設定了字符大小寬高均放大2倍,那么后面列印的字符都會被放大,所以如果后面我們想使用默認字符大小,我們還需要再次設定字符大小為默認來覆寫之前的指令

//這里的EscPosUtil.js就是上面封裝的列印指令

import Esc from './EscPosUtil.js';

// 列印文字格式
let strCenter = Esc.Center(); //文字居中
let strLeft = Esc.Left(); //文字靠左
let strSize1 = Esc.Size1(); //默認文字
let strSize2 = Esc.Size2(17); //文字放大兩倍(長寬均為兩倍)

let printerInfo = {
  IP:'192.168.5.6',
  PORT: 9100
}


let strCmd = strCenter + Esc.Size2(17) + Esc.boldFontOn() + '測驗門店'+ "\n";
  strCmd += strSize1 + Esc.fillLine(' ') + "\n"
  strCmd += strCenter + Esc.Size2(17) + Esc.boldFontOn() + '結賬單-堂食'  + "\n";
  strCmd += strSize1 + Esc.fillLine(' ') + "\n"
  strCmd += strLeft + Esc.Size2(17) + "取餐號:" + '62' + "\n";
  strCmd += Esc.inline('桌號:' + '牡丹廳', '人數:' + '6', ' ', 2) + "\n"
  strCmd += Esc.boldFontOff() + strSize1 + Esc.fillLine(' ') + "\n"
  strCmd += strLeft + strSize1 + "訂單號:" + '202305171749110001' + "\n";

  // 商品資訊
  strCmd += Esc.fillAround('商品') + "\n"
  // 票尾
  strCmd += Esc.fillLine(' ') + "\n"
  strCmd += strCenter + '歡迎下次光臨!' + "\n";
  strCmd += Esc.feedLines(4) + "\n"
  // 切紙
  strCmd += Esc.cutPaper()

tcpWrite(strCmd, printerInfo)

列印效果(這里僅為展示,非上述代碼列印)

image.png

3.USB列印機

這里我使用的是uniapp插件市場的插件,如果你了解安卓原生開發,你也可以自己制作一個原生插件,或者使用Native.js開發,使用原生插件在本地除錯需要先打包“自定義除錯基座”,在本地測驗后再打正式包,

uni-app基于nativejs實作USB-OTG通訊 - 簡書1,監聽USB拔出連接,判斷是否含有權限 2,獲取權限后,打開設備實作連接 3,讀寫發送接受資料 轉存失敗,建議直接上傳圖片檔案https://www.jianshu.com/p/7c308ffcd789

uni-app官網uni-app,uniCloud,serverless https://uniapp.dcloud.net.cn/plugin/native-plugin.html#%E6%9C%AC%E5%9C%B0%E6%8F%92%E4%BB%B6-%E9%9D%9E%E5%86%85%E7%BD%AE%E5%8E%9F%E7%94%9F%E6%8F%92%E4%BB%B6

Android USB介面熱敏小票列印機插件usbPrinter - DCloud 插件市場本插件提供安卓手機通過USB介面連接熱敏小票列印機進行列印的相關功能,通過USB連接相比使用藍牙連接更穩定, https://ext.dcloud.net.cn/plugin?id=7757

在使用USB插件后,我們可以監聽USB設備的插入和拔出,在初始化之后,我們可以進行資料通信,將上面封裝的列印指令傳給列印機即可

 二、網頁列印

由于是網頁運行在瀏覽器中,所以我們只能使用瀏覽器給我們提供的API

1.windows.print()

這個API在不同的瀏覽器中會有差異,其作用就是可以把網頁中的body元素列印出來,如果我們不想列印整個body元素,則需要將body的innerHTML替換,使用這種方式有時有些頁面樣式會和列印出來的不一樣,那么我們就要使用其他方式來優化,

//使用方法

document.body.innerHTML = newstr;  // 把需要列印的指定內容賦給body
window.print();

1.1使用媒體查詢

@media print {
  //把需要列印時才用到的樣式寫到這里
  p{
    font-size:16px;
  }
}
同理,你也可以直接在CSS檔案或者style標簽中加上 media="print"
<style media="print">
//CSS代碼
</style>

1.2監聽列印事件

//監聽列印之前的事件
window.onbeforeprint = function() {
  //可以修改元素樣式
}


//監聽列印之后的事件
window.onafterprint = function() {
   //恢復之前的樣式
}

1.3分頁符

  1.3.1 page-break-before  指定元素前插入分頁符

  1.3.2 page-break-after  指定元素后插入分頁符

描述
auto 默認,如果必要則在元素后插入分頁符,
always 在元素后插入分頁符,
avoid 避免在元素后插入分頁符,
left 在元素之后足夠的分頁符,一直到一張空白的左頁為止,
right 在元素之后足夠的分頁符,一直到一張空白的右頁為止,
inherit 規定應該從父元素繼承 page-break-after 屬性的設定,

1. 您不能對絕對定位的元素使用此屬性,

2. 請盡可能少地使用分頁屬性,并且避免在表格、浮動元素、帶有邊框的塊元素中使用分頁屬性,

3. 任何版本的Internet Explorer(包括IE8)支持屬性值"left","right",和"inherit",

4. Firefox,Chrome和Safari不支持屬性值"avoid","left"和"right",.

@media print {
    footer {page-break-after: always;}
}

1.3.3 page-break-inside  設定是否在指定元素中插入分頁符 

描述
auto 默認,如果必要則在元素內部插入分頁符,
avoid 避免在元素內部插入分頁符,
inherit 規定應該從父元素繼承 page-break-inside 屬性的設定,
  1. 您不能對絕對定位的元素使用此屬性,
  2. 請盡可能少地使用分頁屬性,并且避免在表格、浮動元素、帶有邊框的塊元素中使用分頁屬性,
  3. IE8 及更早IE版本不支持 "inherit" 屬性,
  4. Firefox, Chrome, 以及 Safari 不支持屬性值 "avoid".
//避免在 <pre> 與 <blockquote> 元素中插入分頁符:

@media print {
    pre, blockquote {page-break-inside: avoid;}
}

1.4設定紙張

@page:  用來設定頁面大小、邊距、方向等

//portrait:縱向;  landscape: 橫向

@page {
    size: A4 portrait;  //設定紙張及其方向    這里表示使用A4紙張,列印方向為縱向 
    margin: 3.7cm 2.6cm 3.5cm; //設定紙張外邊距
}
 
// 去除頁眉
@page { margin-top: 0; }
 
// 去除頁腳
@page { margin-bottom: 0; }

 值得注意的是,如果我們使用的列印機是黑白列印的,比如針式列印機,那么我們使用的顏色最好是 #000,如果使用 #999這種灰色,列印效果會很不清晰

本文轉載于:

https://juejin.cn/post/7237316724739457061

如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/553544.html

標籤:JavaScript

上一篇:深入理解 apply()方法

下一篇:返回列表

標籤雲
其他(159796) Python(38173) JavaScript(25458) Java(18138) C(15231) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7213) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5343) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4576) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1977) 功能(1967) Web開發(1951) HtmlCss(1948) C++(1922) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1862) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 記錄--前端小票列印、網頁列印

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、小票列印 目前市面上的小票列印機大多采用的列印指令集為ESC/POS指令,它可以使用ASCII碼、十進制、十六進制來控制列印,我們可以使用它來控制字體大小、列印排版、字體加粗、下劃線、走紙、切紙、控制錢箱等,下面以初始化列印機為例: ......

    uj5u.com 2023-05-27 07:43:25 more
  • 深入理解 apply()方法

    apply(thisArg) apply(thisArg, argsArray) thisArg 在 func 函式運行時使用的 this 值。請注意,this 可能不是該方法看到的實際值:如果這個函式處于非嚴格模式下,則指定為 null 或 undefined 時會自動替換為指向全域物件,原始值會 ......

    uj5u.com 2023-05-27 07:37:30 more
  • ArcMap手動新建矢量要素的方式

    本文介紹在ArcGIS下屬ArcMap軟體中,新建點、線、面等矢量要素圖層,并對新建圖層的空間范圍加以劃定的方法~ ......

    uj5u.com 2023-05-26 23:19:37 more
  • ArcMap手動新建矢量要素的方式

    本文介紹在ArcGIS下屬ArcMap軟體中,新建點、線、面等矢量要素圖層,并對新建圖層的空間范圍加以劃定的方法~ ......

    uj5u.com 2023-05-26 22:48:30 more
  • C#與Node JS互相實作DES加密解密

    具體的加密演算法可以可自行查詢其區別,這里只是拋磚引玉,大部分加密方法基本都能通過改變傳入引數來實作。 C#相關類檔案: System.Security.Cryptography 命名空間 | Microsoft Learn Node JS相關檔案:Crypto | Node.js v16.20.0 ......

    uj5u.com 2023-05-26 13:25:08 more
  • 搭建自動化 Web 頁面性能檢測系統 —— 設計篇

    >我們是[袋鼠云數堆疊 UED 團隊](http://ued.dtstack.cn/),致力于打造優秀的一站式資料中臺產品。我們始終保持工匠精神,探索前端道路,為社區積累并傳播經驗價值。。 >本文作者:琉易 [liuxianyu.cn](https://link.juejin.cn/?target=h ......

    uj5u.com 2023-05-26 13:24:33 more
  • JavaScript 格式化金額

    # JavaScript 格式化金額 ## 一、使用 `toLocaleString()` 要格式化金額,可以使用 JavaScript 的 `toLocaleString()` 方法。該方法可以將數字轉換為本地化的字串表示形式,并可以指定貨幣符號、小數點和千位分隔符等格式。 代碼如下: 1. 美 ......

    uj5u.com 2023-05-26 13:24:07 more
  • 【一步步開發AI運動小程式】八、利用body-calc進行姿態識別

    > 隨著人工智能技術的不斷發展,阿里體育等IT大廠,推出的“樂動力”、“天天跳繩”AI運動APP,讓**云上運動會、線上運動會、健身打卡、AI體育指導**等概念空前火熱。那么,能否將這些在APP成功應用的場景搬上小程式,分享這些概念的紅利呢?本系列文章就帶您一步一步從零開始開發一個AI運動小程式,本 ......

    uj5u.com 2023-05-26 13:10:31 more
  • Nodejs 應用編譯構建提速建議

    前端構建的提速是一項比較復雜且細節的工程, 目前產品上在持續跟蹤構建慢的應用, 努力優化編譯速度, 但前端本身擁有一個比較自由的技識訓境, 沒有統一的構建工具與流程, 另外語言本身的執行效率、單執行緒的構建也不好讓編譯機發揮其最大能力, 所以目前全域的通用優化手段還是會比較局限, 還是依賴專案自身的優... ......

    uj5u.com 2023-05-26 13:05:20 more
  • CSS中通配輸入文字的小技巧——如何在元素名中包含通配符

    CSS中,*的作用是通配表示“全部”。遺憾的是,并沒有一種通配元素名的方法。 例如,我有好幾個東西class都標記為了my-element-序號,就像這樣: ```html ... ``` 我現在希望讓所有這些class的東西都應用同一個css規則。可惜,css并不支持這么一種寫法: ```css ......

    uj5u.com 2023-05-26 13:05:15 more