| | |
| | | Vue.component("devp-card", { |
| | | template: ` |
| | | <div> |
| | | <div style="display: flex;margin-bottom: 10px;"> |
| | | <div style="width: 100%;">输送监控</div> |
| | | <div style="width: 100%;text-align: right;display: flex;"><el-input size="mini" v-model="searchStationId" placeholder="请输入站号"></el-input><el-button @click="getDevpStateInfo" size="mini">查询</el-button></div> |
| | | <div class="mc-root"> |
| | | <div class="mc-toolbar"> |
| | | <div class="mc-title">输送监控</div> |
| | | <div class="mc-search"> |
| | | <input class="mc-input" v-model="searchStationId" placeholder="请输入站号" /> |
| | | <button type="button" class="mc-btn mc-btn-ghost" @click="getDevpStateInfo">查询</button> |
| | | </div> |
| | | <div style="margin-bottom: 10px;" v-if="!readOnly"> |
| | | <div style="margin-bottom: 5px;"> |
| | | <el-button v-if="showControl" @click="openControl" size="mini">关闭控制中心</el-button> |
| | | <el-button v-else @click="openControl" size="mini">打开控制中心</el-button> |
| | | </div> |
| | | <div v-if="showControl" style="display: flex;justify-content: space-between;flex-wrap: wrap;"> |
| | | <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.stationId" placeholder="站号"></el-input></div> |
| | | <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.taskNo" placeholder="工作号"></el-input></div> |
| | | <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.targetStationId" placeholder="目标站"></el-input></div> |
| | | <div style="margin-bottom: 10px;"><el-button @click="controlCommand()" size="mini">下发</el-button></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div v-if="!readOnly" class="mc-control-toggle"> |
| | | <button type="button" class="mc-btn mc-btn-ghost" @click="openControl"> |
| | | {{ showControl ? '收起控制中心' : '打开控制中心' }} |
| | | </button> |
| | | </div> |
| | | |
| | | <div v-if="showControl" class="mc-control"> |
| | | <div class="mc-control-grid"> |
| | | <label class="mc-field"> |
| | | <span class="mc-field-label">站号</span> |
| | | <input class="mc-input" v-model="controlParam.stationId" placeholder="例如 101" /> |
| | | </label> |
| | | <label class="mc-field"> |
| | | <span class="mc-field-label">工作号</span> |
| | | <input class="mc-input" v-model="controlParam.taskNo" placeholder="输入工作号" /> |
| | | </label> |
| | | <label class="mc-field mc-span-2"> |
| | | <span class="mc-field-label">目标站</span> |
| | | <input class="mc-input" v-model="controlParam.targetStationId" placeholder="输入目标站号" /> |
| | | </label> |
| | | <div class="mc-action-row"> |
| | | <button type="button" class="mc-btn" @click="controlCommand">下发</button> |
| | | <button type="button" class="mc-btn mc-btn-soft" @click="resetCommand">复位</button> |
| | | </div> |
| | | </div> |
| | | <div style="max-height: 55vh; overflow:auto;"> |
| | | <el-collapse v-model="activeNames" accordion> |
| | | <el-collapse-item v-for="(item) in displayStationList" :name="item.stationId"> |
| | | <template slot="title"> |
| | | <div style="width: 100%;display: flex;"> |
| | | <div style="width: 50%;">{{ item.stationId }}站</div> |
| | | <div style="width: 50%;text-align: right;"> |
| | | <el-tag v-if="item.autoing" type="success" size="small">自动</el-tag> |
| | | <el-tag v-else type="warning" size="small">手动</el-tag> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="mc-collapse"> |
| | | <div |
| | | v-for="item in displayStationList" |
| | | :key="item.stationId" |
| | | :class="['mc-item', { 'is-open': isActive(item.stationId) }]" |
| | | > |
| | | <button type="button" class="mc-head" @click="toggleItem(item)"> |
| | | <div class="mc-head-main"> |
| | | <div class="mc-head-title">{{ item.stationId }}站</div> |
| | | <div class="mc-head-subtitle">任务 {{ orDash(item.taskNo) }} | 目标站 {{ orDash(item.targetStaNo) }}</div> |
| | | </div> |
| | | <div class="mc-head-right"> |
| | | <span :class="['mc-badge', 'is-' + getStatusTone(item)]">{{ getStatusLabel(item) }}</span> |
| | | <span class="mc-chevron">{{ isActive(item.stationId) ? '▾' : '▸' }}</span> |
| | | </div> |
| | | </button> |
| | | |
| | | <div v-if="isActive(item.stationId)" class="mc-body"> |
| | | <div class="mc-detail-grid"> |
| | | <div v-for="entry in buildDetailEntries(item)" :key="entry.label" class="mc-detail-cell"> |
| | | <div class="mc-detail-label">{{ entry.label }}</div> |
| | | <div v-if="entry.type === 'barcode'" class="mc-detail-value mc-code"> |
| | | <el-popover v-if="item.barcode" placement="top" width="460" trigger="hover"> |
| | | <div style="text-align: center;"> |
| | | <img |
| | | :src="getBarcodePreview(item.barcode)" |
| | | :alt="'barcode-' + item.barcode" |
| | | style="display: block; max-width: 100%; height: auto; margin: 0 auto; image-rendering: pixelated; background: #fff;" |
| | | /> |
| | | <div style="margin-top: 4px; font-size: 12px; word-break: break-all;">{{ item.barcode }}</div> |
| | | </div> |
| | | <span |
| | | slot="reference" |
| | | @click.stop="handleBarcodeClick(item)" |
| | | style="cursor: pointer; color: #4677a4; font-weight: 600;" |
| | | >{{ entry.value }}</span> |
| | | </el-popover> |
| | | <span |
| | | v-else |
| | | @click.stop="handleBarcodeClick(item)" |
| | | style="cursor: pointer; color: #4677a4; font-weight: 600;" |
| | | >{{ entry.value }}</span> |
| | | </div> |
| | | </template> |
| | | <el-descriptions border direction="vertical"> |
| | | <el-descriptions-item label="编号">{{ item.stationId }}</el-descriptions-item> |
| | | <el-descriptions-item label="工作号">{{ item.taskNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="目标站">{{ item.targetStaNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="模式">{{ item.autoing ? '自动' : '手动' }}</el-descriptions-item> |
| | | <el-descriptions-item label="有物">{{ item.loading ? '有' : '无' }}</el-descriptions-item> |
| | | <el-descriptions-item label="可入">{{ item.inEnable ? 'Y' : 'N' }}</el-descriptions-item> |
| | | <el-descriptions-item label="可出">{{ item.outEnable ? 'Y' : 'N' }}</el-descriptions-item> |
| | | <el-descriptions-item label="空板信号">{{ item.emptyMk ? 'Y' : 'N' }}</el-descriptions-item> |
| | | <el-descriptions-item label="满板信号">{{ item.fullPlt ? 'Y' : 'N' }}</el-descriptions-item> |
| | | <el-descriptions-item label="运行阻塞">{{ item.runBlock ? 'Y' : 'N' }}</el-descriptions-item> |
| | | <el-descriptions-item label="启动入库">{{ item.enableIn ? 'Y' : 'N' }}</el-descriptions-item> |
| | | <el-descriptions-item label="托盘高度">{{ item.palletHeight }}</el-descriptions-item> |
| | | <el-descriptions-item label="条码">{{ item.barcode }}</el-descriptions-item> |
| | | <el-descriptions-item label="重量">{{ item.weight }}</el-descriptions-item> |
| | | <el-descriptions-item label="故障代码">{{ item.error }}</el-descriptions-item> |
| | | <el-descriptions-item label="故障信息">{{ item.errorMsg }}</el-descriptions-item> |
| | | <el-descriptions-item label="扩展数据">{{ item.extend }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-collapse-item> |
| | | </el-collapse> |
| | | <div v-else class="mc-detail-value" :class="{ 'mc-code': entry.code }">{{ entry.value }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div style="display:flex; justify-content:flex-end; margin-top:8px;"> |
| | | <el-pagination |
| | | small |
| | | @current-change="handlePageChange" |
| | | @size-change="handleSizeChange" |
| | | :current-page="currentPage" |
| | | :page-size="pageSize" |
| | | :page-sizes="[10,20,50,100]" |
| | | layout="total, prev, pager, next" |
| | | :total="stationList.length"> |
| | | </el-pagination> |
| | | </div> |
| | | |
| | | <div v-if="displayStationList.length === 0" class="mc-empty">当前没有可展示的站点数据</div> |
| | | </div> |
| | | |
| | | <div class="mc-footer"> |
| | | <button type="button" class="mc-page-btn" :disabled="currentPage <= 1" @click="handlePageChange(currentPage - 1)">上一页</button> |
| | | <span>{{ currentPage }} / {{ totalPages }}</span> |
| | | <button type="button" class="mc-page-btn" :disabled="currentPage >= totalPages" @click="handlePageChange(currentPage + 1)">下一页</button> |
| | | </div> |
| | | </div> |
| | | `, |
| | | `, |
| | | props: { |
| | | param: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | autoRefresh: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | readOnly: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | param: { type: Object, default: function () { return {}; } }, |
| | | items: { type: Array, default: null }, |
| | | autoRefresh: { type: Boolean, default: true }, |
| | | readOnly: { type: Boolean, default: false } |
| | | }, |
| | | data() { |
| | | data: function () { |
| | | return { |
| | | stationList: [], |
| | | fullStationList: [], |
| | | activeNames: "", |
| | | searchStationId: "", |
| | | showControl: false, |
| | | controlParam: { |
| | | stationId: "", |
| | | taskNo: "", |
| | | targetStationId: "", |
| | | targetStationId: "" |
| | | }, |
| | | pageSize: 25, |
| | | barcodePreviewCache: {}, |
| | | pageSize: 12, |
| | | currentPage: 1, |
| | | timer: null |
| | | }; |
| | | }, |
| | | created() { |
| | | if (this.autoRefresh) { |
| | | this.timer = setInterval(() => { |
| | | this.getDevpStateInfo(); |
| | | }, 1000); |
| | | } |
| | | }, |
| | | beforeDestroy() { |
| | | if (this.timer) { |
| | | clearInterval(this.timer); |
| | | } |
| | | }, |
| | | computed: { |
| | | displayStationList() { |
| | | const start = (this.currentPage - 1) * this.pageSize; |
| | | const end = start + this.pageSize; |
| | | return this.stationList.slice(start, end); |
| | | sourceList: function () { |
| | | return Array.isArray(this.items) ? this.items : this.stationList; |
| | | }, |
| | | filteredStationList: function () { |
| | | var keyword = String(this.searchStationId || "").trim(); |
| | | if (!keyword) { |
| | | return this.sourceList; |
| | | } |
| | | return this.sourceList.filter(function (item) { |
| | | return String(item.stationId) === keyword; |
| | | }); |
| | | }, |
| | | displayStationList: function () { |
| | | var start = (this.currentPage - 1) * this.pageSize; |
| | | return this.filteredStationList.slice(start, start + this.pageSize); |
| | | }, |
| | | totalPages: function () { |
| | | return Math.max(1, Math.ceil(this.filteredStationList.length / this.pageSize) || 1); |
| | | } |
| | | }, |
| | | watch: { |
| | | param: { |
| | | handler(newVal, oldVal) { |
| | | if (newVal && newVal.stationId && newVal.stationId != 0) { |
| | | this.activeNames = newVal.stationId; |
| | | this.searchStationId = newVal.stationId; |
| | | } |
| | | }, |
| | | deep: true, // 深度监听嵌套属性 |
| | | immediate: true, // 立即触发一次(可选) |
| | | items: function () { |
| | | this.afterDataRefresh(); |
| | | }, |
| | | param: { |
| | | deep: true, |
| | | immediate: true, |
| | | handler: function (newVal) { |
| | | if (newVal && newVal.stationId && newVal.stationId !== 0) { |
| | | this.focusStation(newVal.stationId); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | created: function () { |
| | | MonitorCardKit.ensureStyles(); |
| | | if (this.autoRefresh) { |
| | | this.timer = setInterval(this.getDevpStateInfo, 1000); |
| | | } |
| | | }, |
| | | beforeDestroy: function () { |
| | | if (this.timer) { |
| | | clearInterval(this.timer); |
| | | this.timer = null; |
| | | } |
| | | }, |
| | | methods: { |
| | | handlePageChange(page) { |
| | | orDash: function (value) { |
| | | return MonitorCardKit.orDash(value); |
| | | }, |
| | | getStatusLabel: function (item) { |
| | | return item && item.autoing ? "自动" : "手动"; |
| | | }, |
| | | getStatusTone: function (item) { |
| | | return MonitorCardKit.statusTone(this.getStatusLabel(item)); |
| | | }, |
| | | isActive: function (stationId) { |
| | | return String(this.activeNames) === String(stationId); |
| | | }, |
| | | toggleItem: function (item) { |
| | | var next = String(item.stationId); |
| | | this.activeNames = this.activeNames === next ? "" : next; |
| | | }, |
| | | focusStation: function (stationId) { |
| | | this.searchStationId = String(stationId); |
| | | var index = this.filteredStationList.findIndex(function (item) { |
| | | return String(item.stationId) === String(stationId); |
| | | }); |
| | | this.currentPage = index >= 0 ? Math.floor(index / this.pageSize) + 1 : 1; |
| | | this.activeNames = String(stationId); |
| | | }, |
| | | afterDataRefresh: function () { |
| | | if (this.currentPage > this.totalPages) { |
| | | this.currentPage = this.totalPages; |
| | | } |
| | | if (this.activeNames) { |
| | | var exists = this.filteredStationList.some(function (item) { |
| | | return String(item.stationId) === String(this.activeNames); |
| | | }, this); |
| | | if (!exists) { |
| | | this.activeNames = ""; |
| | | } |
| | | } |
| | | }, |
| | | handlePageChange: function (page) { |
| | | if (page < 1 || page > this.totalPages) { |
| | | return; |
| | | } |
| | | this.currentPage = page; |
| | | }, |
| | | handleSizeChange(size) { |
| | | this.pageSize = size; |
| | | this.currentPage = 1; |
| | | }, |
| | | getDevpStateInfo() { |
| | | if (this.readOnly) { |
| | | // Frontend filtering for readOnly mode |
| | | if (this.searchStationId == "") { |
| | | this.stationList = this.fullStationList; |
| | | } else { |
| | | this.stationList = this.fullStationList.filter(item => item.stationId == this.searchStationId); |
| | | this.currentPage = 1; |
| | | } |
| | | } else if (this.$root.sendWs) { |
| | | getDevpStateInfo: function () { |
| | | if (this.$root && this.$root.sendWs) { |
| | | this.$root.sendWs(JSON.stringify({ |
| | | "url": "/console/latest/data/station", |
| | | "data": {} |
| | | url: "/console/latest/data/station", |
| | | data: {} |
| | | })); |
| | | } |
| | | }, |
| | | setStationList(res) { |
| | | let that = this; |
| | | if (res.code == 200) { |
| | | let list = res.data; |
| | | that.fullStationList = list; |
| | | if (that.searchStationId == "") { |
| | | that.stationList = list; |
| | | } else { |
| | | let tmp = []; |
| | | list.forEach((item) => { |
| | | if (item.stationId == that.searchStationId) { |
| | | tmp.push(item); |
| | | } |
| | | }); |
| | | that.stationList = tmp; |
| | | that.currentPage = 1; |
| | | } |
| | | setStationList: function (res) { |
| | | if (res && res.code === 200) { |
| | | this.stationList = res.data || []; |
| | | this.afterDataRefresh(); |
| | | } |
| | | }, |
| | | openControl() { |
| | | openControl: function () { |
| | | this.showControl = !this.showControl; |
| | | }, |
| | | controlCommand() { |
| | | let that = this; |
| | | //下发命令 |
| | | buildDetailEntries: function (item) { |
| | | return [ |
| | | { label: "编号", value: this.orDash(item.stationId) }, |
| | | { label: "工作号", value: this.orDash(item.taskNo) }, |
| | | { label: "目标站", value: this.orDash(item.targetStaNo) }, |
| | | { label: "模式", value: item.autoing ? "自动" : "手动" }, |
| | | { label: "有物", value: MonitorCardKit.yesNo(item.loading) }, |
| | | { label: "可入", value: MonitorCardKit.yesNo(item.inEnable) }, |
| | | { label: "可出", value: MonitorCardKit.yesNo(item.outEnable) }, |
| | | { label: "空板信号", value: MonitorCardKit.yesNo(item.emptyMk) }, |
| | | { label: "满板信号", value: MonitorCardKit.yesNo(item.fullPlt) }, |
| | | { label: "运行阻塞", value: MonitorCardKit.yesNo(item.runBlock) }, |
| | | { label: "启动入库", value: MonitorCardKit.yesNo(item.enableIn) }, |
| | | { label: "托盘高度", value: this.orDash(item.palletHeight) }, |
| | | { label: "条码", value: this.orDash(item.barcode), code: true, type: "barcode" }, |
| | | { label: "重量", value: this.orDash(item.weight) }, |
| | | { label: "任务可写区", value: this.orDash(item.taskWriteIdx) }, |
| | | { label: "故障代码", value: this.orDash(item.error) }, |
| | | { label: "故障信息", value: this.orDash(item.errorMsg) }, |
| | | { label: "扩展数据", value: this.orDash(item.extend) } |
| | | ]; |
| | | }, |
| | | postControl: function (url, payload) { |
| | | $.ajax({ |
| | | url: baseUrl + "/station/command/move", |
| | | url: baseUrl + url, |
| | | headers: { |
| | | token: localStorage.getItem("token"), |
| | | token: localStorage.getItem("token") |
| | | }, |
| | | contentType: "application/json", |
| | | method: "post", |
| | | data: JSON.stringify(that.controlParam), |
| | | success: (res) => { |
| | | if (res.code == 200) { |
| | | that.$message({ |
| | | message: res.msg, |
| | | type: "success", |
| | | }); |
| | | data: JSON.stringify(payload), |
| | | success: function (res) { |
| | | if (res && res.code === 200) { |
| | | MonitorCardKit.showMessage(this, res.msg || "操作成功", "success"); |
| | | } else { |
| | | that.$message({ |
| | | message: res.msg, |
| | | type: "warning", |
| | | }); |
| | | MonitorCardKit.showMessage(this, (res && res.msg) || "操作失败", "warning"); |
| | | } |
| | | }, |
| | | }.bind(this) |
| | | }); |
| | | }, |
| | | }, |
| | | handleBarcodeClick: function (item) { |
| | | if (this.readOnly || !item || item.stationId == null) { |
| | | return; |
| | | } |
| | | this.$prompt("请输入新的条码值(可留空清空)", "修改条码", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | inputValue: item.barcode || "", |
| | | inputPlaceholder: "请输入条码" |
| | | }).then(function (result) { |
| | | this.updateStationBarcode(item.stationId, result && result.value == null ? "" : String(result.value).trim()); |
| | | }.bind(this)).catch(function () {}); |
| | | }, |
| | | updateStationBarcode: function (stationId, barcode) { |
| | | $.ajax({ |
| | | url: baseUrl + "/station/command/barcode", |
| | | headers: { |
| | | token: localStorage.getItem("token") |
| | | }, |
| | | contentType: "application/json", |
| | | method: "post", |
| | | data: JSON.stringify({ |
| | | stationId: stationId, |
| | | barcode: barcode |
| | | }), |
| | | success: function (res) { |
| | | if (res && res.code === 200) { |
| | | this.syncLocalBarcode(stationId, barcode); |
| | | MonitorCardKit.showMessage(this, "条码修改成功", "success"); |
| | | } else { |
| | | MonitorCardKit.showMessage(this, (res && res.msg) || "条码修改失败", "warning"); |
| | | } |
| | | }.bind(this) |
| | | }); |
| | | }, |
| | | syncLocalBarcode: function (stationId, barcode) { |
| | | var update = function (list) { |
| | | if (!list || !list.length) { |
| | | return; |
| | | } |
| | | list.forEach(function (item) { |
| | | if (item.stationId == stationId) { |
| | | item.barcode = barcode; |
| | | } |
| | | }); |
| | | }; |
| | | update(this.stationList); |
| | | if (Array.isArray(this.items)) { |
| | | update(this.items); |
| | | } |
| | | }, |
| | | getBarcodePreview: function (barcode) { |
| | | var value = String(barcode || "").trim(); |
| | | if (!value) { |
| | | return ""; |
| | | } |
| | | if (this.barcodePreviewCache[value]) { |
| | | return this.barcodePreviewCache[value]; |
| | | } |
| | | var encodeResult = this.encodeCode128(value); |
| | | if (!encodeResult) { |
| | | return ""; |
| | | } |
| | | var svg = this.buildCode128Svg(encodeResult, value); |
| | | var dataUrl = "data:image/svg+xml;charset=UTF-8," + encodeURIComponent(svg); |
| | | this.$set(this.barcodePreviewCache, value, dataUrl); |
| | | return dataUrl; |
| | | }, |
| | | encodeCode128: function (value) { |
| | | if (!value) { |
| | | return null; |
| | | } |
| | | var isNumeric = /^\d+$/.test(value); |
| | | if (isNumeric && value.length % 2 === 0) { |
| | | return this.encodeCode128C(value); |
| | | } |
| | | return this.encodeCode128B(value); |
| | | }, |
| | | encodeCode128B: function (value) { |
| | | var codes = [104]; |
| | | for (var i = 0; i < value.length; i++) { |
| | | var code = value.charCodeAt(i) - 32; |
| | | if (code < 0 || code > 94) { |
| | | return null; |
| | | } |
| | | codes.push(code); |
| | | } |
| | | return this.buildCode128Pattern(codes); |
| | | }, |
| | | encodeCode128C: function (value) { |
| | | if (value.length % 2 !== 0) { |
| | | return null; |
| | | } |
| | | var codes = [105]; |
| | | for (var i = 0; i < value.length; i += 2) { |
| | | codes.push(parseInt(value.substring(i, i + 2), 10)); |
| | | } |
| | | return this.buildCode128Pattern(codes); |
| | | }, |
| | | buildCode128Pattern: function (codes) { |
| | | var patterns = this.getCode128Patterns(); |
| | | var checksum = codes[0]; |
| | | for (var i = 1; i < codes.length; i++) { |
| | | checksum += codes[i] * i; |
| | | } |
| | | var checkCode = checksum % 103; |
| | | var fullCodes = codes.concat([checkCode, 106]); |
| | | var bars = ""; |
| | | for (var j = 0; j < fullCodes.length; j++) { |
| | | if (patterns[fullCodes[j]] == null) { |
| | | return null; |
| | | } |
| | | bars += patterns[fullCodes[j]]; |
| | | } |
| | | bars += "11"; |
| | | return bars; |
| | | }, |
| | | buildCode128Svg: function (bars, text) { |
| | | var quietModules = 20; |
| | | var modules = quietModules * 2 + bars.split("").reduce(function (sum, n) { |
| | | return sum + parseInt(n, 10); |
| | | }, 0); |
| | | var moduleWidth = modules > 300 ? 1 : 2; |
| | | var width = modules * moduleWidth; |
| | | var barTop = 10; |
| | | var barHeight = 110; |
| | | var x = quietModules * moduleWidth; |
| | | var black = true; |
| | | var rects = ""; |
| | | for (var i = 0; i < bars.length; i++) { |
| | | var w = parseInt(bars[i], 10) * moduleWidth; |
| | | if (black) { |
| | | rects += '<rect x="' + x + '" y="' + barTop + '" width="' + w + '" height="' + barHeight + '" fill="#000" shape-rendering="crispEdges" />'; |
| | | } |
| | | x += w; |
| | | black = !black; |
| | | } |
| | | return '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="145" viewBox="0 0 ' + width + ' 145">' + |
| | | '<rect width="100%" height="100%" fill="#fff" />' + |
| | | rects + |
| | | '<text x="' + (width / 2) + '" y="136" text-anchor="middle" font-family="monospace" font-size="14" fill="#111">' + |
| | | this.escapeXml(text) + |
| | | "</text></svg>"; |
| | | }, |
| | | getCode128Patterns: function () { |
| | | return [ |
| | | "212222", "222122", "222221", "121223", "121322", "131222", "122213", "122312", "132212", "221213", |
| | | "221312", "231212", "112232", "122132", "122231", "113222", "123122", "123221", "223211", "221132", |
| | | "221231", "213212", "223112", "312131", "311222", "321122", "321221", "312212", "322112", "322211", |
| | | "212123", "212321", "232121", "111323", "131123", "131321", "112313", "132113", "132311", "211313", |
| | | "231113", "231311", "112133", "112331", "132131", "113123", "113321", "133121", "313121", "211331", |
| | | "231131", "213113", "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", |
| | | "314111", "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", |
| | | "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", "134111", |
| | | "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", "421211", "212141", |
| | | "214121", "412121", "111143", "111341", "131141", "114113", "114311", "411113", "411311", "113141", |
| | | "114131", "311141", "411131", "211412", "211214", "211232", "2331112" |
| | | ]; |
| | | }, |
| | | escapeXml: function (text) { |
| | | return String(text) |
| | | .replace(/&/g, "&") |
| | | .replace(/</g, "<") |
| | | .replace(/>/g, ">") |
| | | .replace(/"/g, """) |
| | | .replace(/'/g, "'"); |
| | | }, |
| | | controlCommand: function () { |
| | | this.postControl("/station/command/move", this.controlParam); |
| | | }, |
| | | resetCommand: function () { |
| | | this.postControl("/station/command/reset", this.controlParam); |
| | | } |
| | | } |
| | | }); |