| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755 |
- if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
- Promise.prototype.finally = function(callback) {
- const promise = this.constructor;
- return this.then(
- (value) => promise.resolve(callback()).then(() => value),
- (reason) => promise.resolve(callback()).then(() => {
- throw reason;
- })
- );
- };
- }
- ;
- if (typeof uni !== "undefined" && uni && uni.requireGlobal) {
- const global = uni.requireGlobal();
- ArrayBuffer = global.ArrayBuffer;
- Int8Array = global.Int8Array;
- Uint8Array = global.Uint8Array;
- Uint8ClampedArray = global.Uint8ClampedArray;
- Int16Array = global.Int16Array;
- Uint16Array = global.Uint16Array;
- Int32Array = global.Int32Array;
- Uint32Array = global.Uint32Array;
- Float32Array = global.Float32Array;
- Float64Array = global.Float64Array;
- BigInt64Array = global.BigInt64Array;
- BigUint64Array = global.BigUint64Array;
- }
- ;
- if (uni.restoreGlobal) {
- uni.restoreGlobal(Vue, weex, plus, setTimeout, clearTimeout, setInterval, clearInterval);
- }
- (function(vue) {
- "use strict";
- function requireNativePlugin(name) {
- return weex.requireModule(name);
- }
- function formatAppLog(type, filename, ...args) {
- if (uni.__log__) {
- uni.__log__(type, filename, ...args);
- } else {
- console[type].apply(console, [...args, filename]);
- }
- }
- const _imports_0 = "/static/logo.png";
- const _imports_1 = "/static/horn.png";
- const _export_sfc = (sfc, props) => {
- const target = sfc.__vccOpts || sfc;
- for (const [key, val] of props) {
- target[key] = val;
- }
- return target;
- };
- const _sfc_main$3 = {
- data() {
- return {
- currentTime: "",
- // 当前时间
- hhmmss: "",
- // 当前时间
- whatDay: "",
- //星期几
- timeTimer: null,
- // 时间更新定时器
- // WebSocket 实例
- ws: null,
- reconnectTimer: null,
- heartbeatTimer: null,
- // 心跳定时器
- heartbeatTimeout: null,
- // 心跳响应超时计时器
- heartbeatInterval: 3e4,
- // 30秒发一次心跳
- heartbeatTimeoutTime: 5e3,
- // 10秒内未响应视为超时
- isPongReceived: true,
- // 标记是否收到 pong
- // 连接状态
- connectionStatus: "connecting",
- // connecting, connected, disconnected
- statusText: {
- observing: "留观中",
- completed: "留观完成,可离开",
- warning: "提前离开",
- hasleft: "已离开"
- },
- // 可编辑的服务器地址
- serverIp: "192.168.0.41",
- serverPort: "8811",
- // 所有数据留观数据列表
- allData: [],
- // 当前页码
- currentPage: 1,
- // 每页显示条数(自适应计算)
- pageSize: 10,
- // 是否自动滚动
- autoScroll: true,
- // 自动滚动定时器
- autoScrollTimer: null,
- // 滚动间隔时间(毫秒)
- scrollInterval: 6e3,
- // 窗口高度
- windowHeight: 0,
- // 触摸相关
- touchStartX: 0,
- touchStartTime: 0,
- isTouching: false,
- touchStartY: 0,
- // 垂直滑动相关
- lastSwipeTime: 0,
- linkShow: false,
- ipArray: [],
- keyboardHeight: 0,
- now: /* @__PURE__ */ new Date(),
- timer: null,
- heartbeatRate: 0,
- isSend: true,
- reconnectionNum: 0
- };
- },
- computed: {
- connectionText() {
- const {
- connectionStatus,
- serverIp,
- serverPort
- } = this;
- return {
- connecting: `正在连接 ${serverIp}:${serverPort}...`,
- connected: `已连接到 ${serverIp}:${serverPort}`,
- disconnected: `连接已断开`
- }[connectionStatus];
- },
- // 特殊状态数据(状态1和2)
- specialStatusData() {
- return this.allData.filter((item) => item.status === 3 || item.status === 4 || item.IsOut == 1);
- },
- // 普通状态数据(状态0)
- normalData() {
- return this.allData.filter((item) => item.status === 0 || item.status === 1);
- },
- // 实际显示的条数(减去缓冲行)
- actualPageSize() {
- return Math.max(1, this.pageSize - 1);
- },
- // 总页数(基于普通数据计算)
- totalPages() {
- if (this.actualPageSize <= 0 || this.normalData.length === 0)
- return 1;
- return Math.ceil(this.normalData.length / this.actualPageSize);
- },
- // 显示的普通数据(包含缓冲行)
- displayNormalData() {
- const start = (this.currentPage - 1) * this.actualPageSize;
- const end = Math.min(start + this.pageSize, this.normalData.length);
- return this.normalData.slice(start, end).map((item) => {
- const expectedTime = new Date(item.outTime);
- const timeDiff = expectedTime - this.now;
- if (timeDiff > 0) {
- const minutes = Math.floor(timeDiff % (3600 * 1e3) / (60 * 1e3));
- const seconds = Math.floor(timeDiff % (60 * 1e3) / 1e3);
- var fzArr = "";
- if (minutes) {
- fzArr = `剩余${minutes}分钟`;
- } else {
- fzArr = `剩余${seconds}秒`;
- }
- return {
- ...item,
- remainingTime: fzArr
- };
- } else {
- return {
- ...item,
- remainingTime: "留观完成,可离开"
- };
- }
- });
- }
- },
- mounted() {
- this.reconnectionNum = 0;
- this.timer = setInterval(() => {
- this.now = /* @__PURE__ */ new Date();
- }, 1e3);
- this.getIpAddress();
- this.initPage();
- const lastIp = uni.getStorageSync("serverIp");
- const lastPort = uni.getStorageSync("serverPort");
- if (lastIp && lastPort) {
- this.serverIp = lastIp;
- this.serverPort = lastPort;
- }
- this.updateCurrentTime();
- this.timeTimer = setInterval(() => {
- this.updateCurrentTime();
- }, 1e3);
- },
- beforeDestroy() {
- if (this.timer) {
- this.timer = null;
- clearInterval(this.timer);
- }
- this.stopAutoScroll();
- uni.offWindowResize(this.handleWindowResize);
- if (this.ws) {
- this.ws.close();
- }
- if (this.reconnectTimer) {
- clearTimeout(this.reconnectTimer);
- }
- this.stopHeartbeat();
- if (this.timeTimer) {
- clearInterval(this.timeTimer);
- }
- },
- methods: {
- keyboardheightchange() {
- uni.onKeyboardHeightChange((res) => {
- this.keyboardHeight = res.height;
- });
- },
- findFirstWebSocketIp(ipList, index = 0, onSuccess, onAllFailed) {
- if (index >= ipList.length) {
- if (typeof onAllFailed === "function") {
- onAllFailed();
- }
- return;
- }
- const ip = ipList[index].trim();
- const port = this.serverPort;
- const url = `ws://${ip}:${port}/`;
- if (this.ws) {
- this.ws.close();
- this.ws = null;
- }
- this.ws = uni.connectSocket({
- url,
- success: (res) => {
- formatAppLog("log", "at pages/index/home.vue:299", "connectSocket success", res);
- },
- fail: (err) => {
- formatAppLog("error", "at pages/index/home.vue:302", "connectSocket 失败", err);
- this.connectionStatus = "disconnected";
- if (this.serverIp == ip) {
- this.heartbeatRate = 0;
- this.reconnectionNum++;
- }
- this.reconnectionNum++;
- this.isSend = true;
- this.heartbeatRate = 0;
- this.findFirstWebSocketIp(ipList, index + 1, onSuccess, onAllFailed);
- }
- });
- this.ws.onOpen((res) => {
- this.serverIp = ip;
- uni.setStorageSync("serverIp", this.serverIp);
- uni.setStorageSync("serverPort", this.serverPort);
- this.connectionStatus = "connected";
- this.ws.send({
- data: "link"
- });
- onSuccess(ip);
- this.startHeartbeat();
- uni.hideLoading();
- });
- this.ws.onMessage((res) => {
- if (res.data === "PONG" || res.data === '{"type":"PONG"}') {
- this.isSend = true;
- this.heartbeatRate = 0;
- this.isPongReceived = true;
- if (this.heartbeatTimeout) {
- clearTimeout(this.heartbeatTimeout);
- this.heartbeatTimeout = null;
- }
- return;
- }
- try {
- const data = JSON.parse(res.data);
- this.handleMessage(data);
- } catch (e) {
- formatAppLog("warn", "at pages/index/home.vue:354", "非 JSON 消息,已忽略", res.data);
- }
- });
- this.ws.onClose((res) => {
- formatAppLog("log", "at pages/index/home.vue:358", "WebSocket 连接关闭", res);
- this.connectionStatus = "disconnected";
- this.stopHeartbeat();
- var reconnectionTime = setTimeout(() => {
- clearTimeout(reconnectionTime);
- if (this.serverIp == ip)
- ;
- this.isSend = true;
- this.heartbeatRate = 0;
- this.reconnectionNum++;
- this.findFirstWebSocketIp(ipList, index + 1, onSuccess, onAllFailed);
- }, 2e3);
- });
- this.ws.onError((err) => {
- formatAppLog("error", "at pages/index/home.vue:380", "WebSocket 错误", err);
- this.connectionStatus = "disconnected";
- this.isSend = true;
- this.heartbeatRate = 0;
- this.reconnectionNum++;
- this.findFirstWebSocketIp(ipList, index + 1, onSuccess, onAllFailed);
- });
- },
- // 连接设置
- linkSet() {
- this.linkShow = true;
- },
- // 关闭弹窗
- getClose() {
- this.linkShow = false;
- },
- // 获取ip地址
- getIpAddress() {
- var deviceFinder = requireNativePlugin("Alikes-NetTools-DeviceFinder");
- deviceFinder.scan({}, (res) => {
- this.ipArray = res;
- this.ipArray.unshift(this.serverIp);
- this.startCheck();
- });
- },
- // 启动检查
- startCheck() {
- var ipArray = [];
- ipArray = this.ipArray;
- this.findFirstWebSocketIp(
- ipArray,
- 0,
- (ip) => {
- this.onDeviceFound(ip);
- this.linkShow = false;
- },
- () => {
- this.onNoDevice();
- }
- );
- },
- // 找到设备后的逻辑
- onDeviceFound(ip) {
- uni.showToast({
- title: "连接成功",
- icon: "success"
- });
- },
- // 无设备可用
- onNoDevice() {
- uni.showToast({
- title: "无设备响应",
- icon: "none",
- duration: 3e3
- });
- this.getIpAddress();
- },
- getClass(status) {
- var title = "";
- if (status == 0) {
- title = "observing";
- } else if (status == 1) {
- title = "completed";
- } else if (status == 3) {
- title = "warning";
- } else if (status == 4) {
- title = "hasleft";
- }
- return title;
- },
- // 获取状态文本
- getStatusText(item) {
- if (item.status == 0) {
- return item.remainingTime;
- } else if (item.status == 1) {
- return this.statusText.completed;
- } else if (item.status == 3) {
- return this.statusText.warning;
- } else if (item.status == 4) {
- return this.statusText.hasleft;
- }
- },
- // 初始化页面
- initPage() {
- this.calculatePageSize();
- this.handleWindowResize = this.debounce(this.calculatePageSize, 300);
- uni.onWindowResize(this.handleWindowResize);
- },
- // 计算自适应的页面大小
- calculatePageSize() {
- try {
- const systemInfo = uni.getSystemInfoSync();
- this.windowHeight = systemInfo.windowHeight;
- const headerHeight = uni.upx2px(130);
- const paginationHeight = uni.upx2px(100);
- const tableHeaderHeight = uni.upx2px(120);
- const specialDataHeight = this.specialStatusData.length > 0 ? uni.upx2px(80 * this.specialStatusData.length) : 0;
- const padding = uni.upx2px(0);
- const availableHeight = this.windowHeight - headerHeight - paginationHeight - tableHeaderHeight - specialDataHeight - padding;
- const rowHeightPx = uni.upx2px(140);
- const calculatedPageSize = Math.floor(availableHeight / rowHeightPx);
- this.pageSize = Math.max(4, Math.min(30, calculatedPageSize));
- this.validateCurrentPage();
- } catch (error) {
- formatAppLog("error", "at pages/index/home.vue:515", "计算页面大小失败:", error);
- this.pageSize = 10;
- }
- },
- // 防抖函数
- debounce(func, wait) {
- let timeout;
- return function executedFunction(...args) {
- const later = () => {
- clearTimeout(timeout);
- func(...args);
- };
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- };
- },
- // 验证当前页是否有效
- validateCurrentPage() {
- if (this.currentPage > this.totalPages && this.totalPages > 0) {
- this.currentPage = this.totalPages;
- }
- if (this.currentPage < 1) {
- this.currentPage = 1;
- }
- },
- // 构建 WebSocket URL
- getWebSocketUrl() {
- return `ws://${this.serverIp}:${this.serverPort}`;
- },
- onIpInput(value) {
- this.serverIp = value.detail.value;
- },
- // 输入
- onPortInput(value) {
- this.serverPort = value.detail.value;
- },
- // 处理重连
- handleReconnect() {
- uni.showLoading({
- title: "正在重连..."
- });
- this.linkShow = false;
- this.connectionStatus = "connecting";
- if (this.ws) {
- this.ws.close({
- success: () => {
- this.getIpAddress();
- },
- fail: () => {
- this.getIpAddress();
- }
- });
- } else {
- this.getIpAddress();
- }
- setTimeout(() => {
- uni.hideLoading();
- }, 2e3);
- },
- // 处理收到的消息
- handleMessage(data) {
- if (data.action == "link") {
- this.updateListWithArray(data.data);
- return;
- }
- if (typeof data === "object" && data !== null) {
- const action = data.action;
- if (!action) {
- formatAppLog("warn", "at pages/index/home.vue:603", "消息缺少 action 字段", data);
- return;
- }
- switch (action) {
- case "add":
- case "create":
- this.batchAdd(data.data);
- break;
- case "update":
- this.batchUpdate(data.data);
- break;
- case "remove":
- case "delete":
- this.batchRemove(data.data);
- break;
- default:
- formatAppLog("warn", "at pages/index/home.vue:619", "未知操作类型:", action);
- }
- } else {
- formatAppLog("warn", "at pages/index/home.vue:622", "收到未知格式消息:", data);
- }
- },
- // 批量新增
- batchAdd(data) {
- if (!data)
- return;
- const items = Array.isArray(data) ? data : [data];
- const validItems = items.filter((item) => item && item.id !== void 0);
- if (validItems.length === 0) {
- formatAppLog("warn", "at pages/index/home.vue:631", "没有有效数据用于新增", data);
- return;
- }
- const updated = [...this.allData];
- validItems.forEach((item) => {
- const index = updated.findIndex((i) => i.id == item.id);
- if (index > -1) {
- updated[index] = {
- ...updated[index],
- ...item
- };
- } else {
- updated.unshift(item);
- }
- });
- this.allData = updated;
- },
- // 批量修改
- batchUpdate(data) {
- if (!data)
- return;
- const items = Array.isArray(data) ? data : [data];
- const updated = [...this.allData];
- items.forEach((item) => {
- if (!item || item.id === void 0)
- return;
- const index = updated.findIndex((i) => i.id == item.id);
- if (index > -1) {
- updated[index] = {
- ...updated[index],
- ...item
- };
- }
- });
- this.allData = updated;
- },
- // 批量删除
- batchRemove(data) {
- let idsToRemove = [];
- if (Array.isArray(data.id)) {
- idsToRemove = data.id;
- } else if (data.id !== void 0) {
- idsToRemove = [data.id];
- } else if (Array.isArray(data.data)) {
- idsToRemove = data.data.map((item) => item.id).filter((id) => id !== void 0);
- } else {
- idsToRemove = [data.id];
- formatAppLog("warn", "at pages/index/home.vue:682", "无法解析删除指令", data);
- return;
- }
- if (idsToRemove.length === 0)
- return;
- const updated = this.allData.filter((item) => !idsToRemove.includes(item.id));
- this.allData = updated;
- },
- updateListWithArray(newList) {
- this.allData = [];
- if (!Array.isArray(newList))
- return;
- const map = /* @__PURE__ */ new Map();
- newList.forEach((item) => {
- if (item.id !== void 0) {
- map.set(item.id, item);
- }
- });
- const updated = [...this.allData];
- for (const [id, item] of map.entries()) {
- const index = updated.findIndex((i) => i.id == id);
- if (index > -1) {
- updated[index] = item;
- } else {
- updated.push(item);
- }
- }
- const final = updated.filter((item) => map.has(item.id));
- this.allData = final;
- },
- // 断线重连(指数退避)
- reconnect() {
- if (this.reconnectTimer)
- return;
- this.reconnectTimer = setTimeout(() => {
- this.connectWebSocket();
- this.reconnectTimer = null;
- }, 3e3);
- },
- // 启动心跳
- startHeartbeat() {
- var that = this;
- that.stopHeartbeat();
- that.heartbeatTimer = setInterval(() => {
- if (that.ws && that.connectionStatus === "connected") {
- if (!that.isSend && !that.isPongReceived) {
- that.heartbeatRate++;
- formatAppLog("warn", "at pages/index/home.vue:731", that.heartbeatRate, "上一次心跳未收到 pong,可能已断线新");
- if (that.heartbeatRate >= 3) {
- that.ws.close();
- return;
- }
- }
- that.isPongReceived = false;
- that.heartbeatTimeout = setTimeout(() => {
- if (that.isSend && !that.isPongReceived) {
- formatAppLog("warn", "at pages/index/home.vue:742", "⚠️ 心跳超时:未在规定时间内收到 pong,即将重连");
- uni.showToast({
- title: "连接异常,正在重连...",
- icon: "none",
- duration: 2e3
- });
- that.ws.close();
- }
- }, that.heartbeatTimeoutTime);
- if (that.isSend) {
- that.ws.send({
- data: "PING",
- success: () => {
- that.isSend = false;
- },
- fail: (err) => {
- formatAppLog("error", "at pages/index/home.vue:759", "ping 发送失败", err);
- that.ws.close();
- }
- });
- }
- }
- }, that.heartbeatInterval);
- },
- // 停止心跳(断开连接时调用)
- stopHeartbeat() {
- if (this.heartbeatTimer) {
- clearInterval(this.heartbeatTimer);
- this.heartbeatTimer = null;
- }
- if (this.heartbeatTimeout) {
- clearTimeout(this.heartbeatTimeout);
- this.heartbeatTimeout = null;
- }
- },
- // 格式化时间
- formatTime(dateTimeStr) {
- const date = new Date(dateTimeStr);
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const time = `${hours}:${minutes}`;
- return time;
- },
- // 上一页
- prevPage() {
- if (this.currentPage > 1) {
- this.currentPage--;
- this.resetAutoScroll();
- }
- },
- // 下一页
- nextPage() {
- if (this.currentPage < this.totalPages) {
- this.currentPage++;
- this.resetAutoScroll();
- }
- },
- // 触摸开始
- handleTouchStart(e) {
- this.touchStartX = e.touches[0].clientX;
- this.touchStartY = e.touches[0].clientY;
- this.touchStartTime = Date.now();
- this.isTouching = true;
- if (this.autoScroll) {
- this.stopAutoScroll();
- }
- },
- // 触摸移动
- handleTouchMove(e) {
- if (!this.isTouching)
- return;
- },
- // 触摸结束
- handleTouchEnd(e) {
- if (!this.isTouching)
- return;
- const touchEndX = e.changedTouches[0].clientX;
- const touchEndY = e.changedTouches[0].clientY;
- const touchEndTime = Date.now();
- const deltaX = touchEndX - this.touchStartX;
- const deltaY = touchEndY - this.touchStartY;
- const deltaTime = touchEndTime - this.touchStartTime;
- const now = Date.now();
- if (now - this.lastSwipeTime < 300) {
- this.isTouching = false;
- return;
- }
- const absDeltaX = Math.abs(deltaX);
- const absDeltaY = Math.abs(deltaY);
- if (absDeltaX > 50 && absDeltaX > absDeltaY && deltaTime < 500) {
- this.lastSwipeTime = now;
- if (deltaX > 0) {
- this.prevPage();
- } else {
- this.nextPage();
- }
- } else if (absDeltaY > 50 && absDeltaY > absDeltaX && deltaTime < 500) {
- this.lastSwipeTime = now;
- if (deltaY > 0) {
- this.prevPage();
- } else {
- this.nextPage();
- }
- }
- this.isTouching = false;
- if (this.autoScroll) {
- this.resetAutoScroll();
- }
- },
- // 添加鼠标滚轮支持(仅H5平台)
- // 切换自动滚动
- toggleAutoScroll(e) {
- this.autoScroll = e.detail.value;
- if (this.autoScroll) {
- this.startAutoScroll();
- } else {
- this.stopAutoScroll();
- }
- },
- // 开始自动滚动
- startAutoScroll() {
- this.stopAutoScroll();
- if (this.autoScroll && this.normalData.length > 0 && this.totalPages > 1) {
- this.autoScrollTimer = setInterval(() => {
- if (this.currentPage < this.totalPages) {
- this.currentPage++;
- } else {
- this.currentPage = 1;
- }
- }, this.scrollInterval);
- }
- },
- // 停止自动滚动
- stopAutoScroll() {
- if (this.autoScrollTimer) {
- clearInterval(this.autoScrollTimer);
- this.autoScrollTimer = null;
- }
- },
- // 重置自动滚动(手动操作后)
- resetAutoScroll() {
- if (this.autoScroll) {
- this.stopAutoScroll();
- setTimeout(() => {
- this.startAutoScroll();
- }, this.scrollInterval);
- }
- },
- // 当前时间
- updateCurrentTime() {
- const now = /* @__PURE__ */ new Date();
- const year = now.getFullYear();
- const month = String(now.getMonth() + 1).padStart(2, "0");
- const day = String(now.getDate()).padStart(2, "0");
- const hours = String(now.getHours()).padStart(2, "0");
- const minutes = String(now.getMinutes()).padStart(2, "0");
- const seconds = String(now.getSeconds()).padStart(2, "0");
- this.currentTime = `${year}-${month}-${day}`;
- this.hhmmss = `${hours}:${minutes}:${seconds}`;
- const weekdays = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
- const weekday = weekdays[now.getDay()];
- this.whatDay = weekday;
- }
- },
- watch: {
- // 监听数据变化
- allData: {
- handler() {
- this.$nextTick(() => {
- this.validateCurrentPage();
- if (this.autoScroll) {
- this.startAutoScroll();
- }
- });
- },
- immediate: true
- },
- // 监听页面大小变化
- pageSize() {
- this.validateCurrentPage();
- },
- // 监听特殊状态数据变化
- specialStatusData() {
- this.$nextTick(() => {
- this.calculatePageSize();
- });
- },
- reconnectionNum: {
- handler(newVal, oldVal) {
- if (newVal >= 3) {
- plus.runtime.restart();
- setTimeout(() => {
- plus.navigator.closeSplashscreen();
- }, 3e3);
- this.reconnectionNum = 0;
- }
- formatAppLog("log", "at pages/index/home.vue:988", "对象属性变化", newVal, oldVal);
- },
- deep: true,
- immediate: true
- }
- }
- };
- function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
- return vue.openBlock(), vue.createElementBlock("view", { class: "notice-board" }, [
- vue.createElementVNode("view", { class: "board-header" }, [
- vue.createElementVNode("view", {
- class: "card_logo",
- onClick: _cache[0] || (_cache[0] = (...args) => $options.linkSet && $options.linkSet(...args))
- }, [
- vue.createElementVNode("image", {
- class: "logo_image",
- src: _imports_0,
- mode: ""
- }),
- vue.createElementVNode("view", { class: "logo_title" }, "观山湖区疾控中心")
- ]),
- vue.createElementVNode("view", { class: "card_yellow" }, [
- vue.createElementVNode("view", { class: "card_board" }, [
- vue.createElementVNode("text", { class: "board-title" }, "接种留观等待")
- ])
- ]),
- vue.createElementVNode("view", { class: "card_time" }, [
- vue.createElementVNode(
- "view",
- { class: "time_title" },
- vue.toDisplayString($data.hhmmss),
- 1
- /* TEXT */
- ),
- vue.createElementVNode(
- "view",
- { class: "current-time" },
- vue.toDisplayString($data.currentTime) + " " + vue.toDisplayString($data.whatDay),
- 1
- /* TEXT */
- )
- ])
- ]),
- vue.createCommentVNode(" 表格容器 "),
- vue.createElementVNode("view", { class: "table-container" }, [
- vue.createCommentVNode(" 主要表头 "),
- vue.createElementVNode("view", { class: "table-header" }, [
- vue.createElementVNode("view", { class: "table-row header-row" }, [
- vue.createElementVNode("view", { class: "cell name title_color" }, "姓名"),
- vue.createElementVNode("view", { class: "cell time title_color" }, "留观时间"),
- vue.createElementVNode("view", { class: "cell time title_color" }, "离开时间"),
- vue.createElementVNode("view", { class: "cell status title_color" }, "状态")
- ])
- ]),
- vue.createCommentVNode(" 特殊状态数据展示区域(固定) "),
- $options.specialStatusData.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", {
- key: 0,
- class: "special-status-container"
- }, [
- (vue.openBlock(true), vue.createElementBlock(
- vue.Fragment,
- null,
- vue.renderList($options.specialStatusData, (item, index) => {
- return vue.openBlock(), vue.createElementBlock(
- "view",
- {
- class: vue.normalizeClass(["table-row", `item-${$options.getClass(item.status)}`]),
- key: item.id
- },
- [
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["table-cell name", `title-${$options.getClass(item.status)}`])
- },
- vue.toDisplayString(item.patientName),
- 3
- /* TEXT, CLASS */
- ),
- vue.createElementVNode(
- "view",
- { class: "table-cell time" },
- vue.toDisplayString($options.formatTime(item.createTime)),
- 1
- /* TEXT */
- ),
- vue.createElementVNode(
- "view",
- { class: "table-cell time" },
- vue.toDisplayString($options.formatTime(item.outTime)),
- 1
- /* TEXT */
- ),
- vue.createElementVNode("view", { class: "table-cell status" }, [
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["status-tag", `status-${$options.getClass(item.status)}`])
- },
- vue.toDisplayString($options.getStatusText(item)),
- 3
- /* TEXT, CLASS */
- )
- ])
- ],
- 2
- /* CLASS */
- );
- }),
- 128
- /* KEYED_FRAGMENT */
- )),
- vue.createCommentVNode(" 分隔线 "),
- vue.createElementVNode("view", { class: "divider" })
- ])) : vue.createCommentVNode("v-if", true),
- vue.createCommentVNode(" 普通数据内容区域 "),
- vue.createElementVNode(
- "view",
- {
- class: "table-body",
- onTouchstart: _cache[1] || (_cache[1] = (...args) => $options.handleTouchStart && $options.handleTouchStart(...args)),
- onTouchmove: _cache[2] || (_cache[2] = (...args) => $options.handleTouchMove && $options.handleTouchMove(...args)),
- onTouchend: _cache[3] || (_cache[3] = (...args) => $options.handleTouchEnd && $options.handleTouchEnd(...args))
- },
- [
- (vue.openBlock(true), vue.createElementBlock(
- vue.Fragment,
- null,
- vue.renderList($options.displayNormalData, (item, index) => {
- return vue.openBlock(), vue.createElementBlock(
- "view",
- {
- class: vue.normalizeClass(["table-row", `item-${$options.getClass(item.status)}`]),
- key: item.id
- },
- [
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["table-cell name", `title-${$options.getClass(item.status)}`])
- },
- vue.toDisplayString(item.patientName),
- 3
- /* TEXT, CLASS */
- ),
- vue.createElementVNode(
- "view",
- { class: "table-cell time" },
- vue.toDisplayString($options.formatTime(item.createTime)),
- 1
- /* TEXT */
- ),
- vue.createElementVNode(
- "view",
- { class: "table-cell time" },
- vue.toDisplayString($options.formatTime(item.outTime)),
- 1
- /* TEXT */
- ),
- vue.createElementVNode("view", { class: "table-cell status" }, [
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["status-tag", `status-${$options.getClass(item.status)}`])
- },
- vue.toDisplayString($options.getStatusText(item)),
- 3
- /* TEXT, CLASS */
- )
- ])
- ],
- 2
- /* CLASS */
- );
- }),
- 128
- /* KEYED_FRAGMENT */
- )),
- vue.createCommentVNode(" 空数据提示 "),
- $options.displayNormalData.length === 0 && $options.specialStatusData.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", {
- key: 0,
- class: "empty-tip"
- }, " 暂无留观人员信息 ")) : vue.createCommentVNode("v-if", true)
- ],
- 32
- /* NEED_HYDRATION */
- )
- ]),
- vue.createElementVNode("view", { class: "card_foot" }, [
- vue.createElementVNode("view", { class: "card_tips_box" }, [
- vue.createElementVNode("image", {
- class: "tips_imageil",
- src: _imports_1,
- mode: ""
- }),
- vue.createElementVNode("view", { class: "title_tips" }, "温馨提示:")
- ]),
- vue.createElementVNode("view", { class: "title_tips_foot" }, "请注意留观30分钟后无不良反应后再离开,谢谢。")
- ]),
- vue.createCommentVNode(" 连接状态与IP编辑栏 "),
- $data.linkShow ? (vue.openBlock(), vue.createElementBlock("view", {
- key: 0,
- class: "box_link_set"
- }, [
- vue.createElementVNode(
- "view",
- {
- class: "box_popup",
- style: vue.normalizeStyle({ bottom: $data.keyboardHeight + "px" })
- },
- [
- vue.createElementVNode("view", { class: "head_popup_title" }, [
- vue.createElementVNode("view", { class: "title_head_popup" }, "连接设置"),
- vue.createElementVNode("view", {
- class: "close_title",
- onClick: _cache[4] || (_cache[4] = (...args) => $options.getClose && $options.getClose(...args))
- }, "×")
- ]),
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["status-bar-bottom", `status-${$data.connectionStatus}`])
- },
- [
- vue.createCommentVNode(" IP 编辑区域 "),
- vue.createElementVNode("view", { class: "ip-input-group" }, [
- vue.createElementVNode("text", { class: "ip-label" }, "IP:"),
- vue.createElementVNode("input", {
- type: "text",
- value: $data.serverIp,
- onInput: _cache[5] || (_cache[5] = (...args) => $options.onIpInput && $options.onIpInput(...args)),
- placeholder: "192.168.0.41",
- class: "ip-input",
- onKeyboardheightchange: _cache[6] || (_cache[6] = (...args) => $options.keyboardheightchange && $options.keyboardheightchange(...args))
- }, null, 40, ["value"]),
- vue.createElementVNode("text", { class: "colon" }, ":"),
- vue.createElementVNode("input", {
- type: "number",
- value: $data.serverPort,
- onInput: _cache[7] || (_cache[7] = (...args) => $options.onPortInput && $options.onPortInput(...args)),
- placeholder: "8811",
- class: "port-input",
- onKeyboardheightchange: _cache[8] || (_cache[8] = (...args) => $options.keyboardheightchange && $options.keyboardheightchange(...args))
- }, null, 40, ["value"]),
- vue.createElementVNode("button", {
- class: "btn-reconnect",
- size: "mini",
- onClick: _cache[9] || (_cache[9] = (...args) => $options.handleReconnect && $options.handleReconnect(...args))
- }, " 更新并重连 ")
- ]),
- vue.createElementVNode("view", { class: "status-text-box" }, [
- vue.createElementVNode(
- "text",
- {
- class: vue.normalizeClass(["dot", `dot-${$data.connectionStatus}`])
- },
- "●",
- 2
- /* CLASS */
- ),
- vue.createElementVNode(
- "text",
- { class: "status-text" },
- vue.toDisplayString($options.connectionText),
- 1
- /* TEXT */
- )
- ])
- ],
- 2
- /* CLASS */
- )
- ],
- 4
- /* STYLE */
- )
- ])) : vue.createCommentVNode("v-if", true)
- ]);
- }
- const PagesIndexHome = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__scopeId", "data-v-760d994e"], ["__file", "D:/code/baozhida-observation-system/pages/index/home.vue"]]);
- const _sfc_main$2 = {
- data() {
- return {
- currentTime: "",
- // 当前时间
- timeTimer: null,
- // 时间更新定时器
- // WebSocket 实例
- ws: null,
- reconnectTimer: null,
- heartbeatTimer: null,
- // 心跳定时器
- heartbeatTimeout: null,
- // 心跳响应超时计时器
- heartbeatInterval: 3e4,
- // 30秒发一次心跳
- heartbeatTimeoutTime: 1e4,
- // 10秒内未响应视为超时
- isPongReceived: true,
- // 标记是否收到 pong
- // 连接状态
- connectionStatus: "connecting",
- // connecting, connected, disconnected
- // 留观数据列表
- list: [],
- statusText: {
- observing: "留观中",
- completed: "留观完成,可离开",
- warning: "提前离开",
- hasleft: "已离开"
- },
- // 可编辑的服务器地址
- serverIp: "192.168.11.132",
- serverPort: "8811"
- };
- },
- computed: {
- connectionText() {
- const {
- connectionStatus,
- serverIp,
- serverPort
- } = this;
- return {
- connecting: `正在连接 ${serverIp}:${serverPort}...`,
- connected: `已连接到 ${serverIp}:${serverPort}`,
- disconnected: `连接已断开`
- }[connectionStatus];
- },
- // 轮播列表数据
- carouselList() {
- if (this.list.length === 0)
- return [];
- if (this.list.length <= 5)
- return this.list;
- return [...this.list, ...this.list];
- },
- // 是否需要启动轮播动画
- shouldAnimate() {
- return this.list.length > 5;
- }
- },
- methods: {
- getClass(status) {
- var title = "";
- if (status == 0) {
- title = "observing";
- } else if (status == 1) {
- title = "completed";
- } else if (status == 3) {
- title = "warning";
- } else if (status == 4) {
- title = "completed";
- }
- return title;
- },
- getStatusText(status) {
- var title = "";
- if (status == 0) {
- title = this.statusText.observing;
- } else if (status == 1) {
- title = this.statusText.completed;
- } else if (status == 3) {
- title = this.statusText.warning;
- } else if (status == 4) {
- title = this.statusText.hasleft;
- }
- return title;
- },
- // 格式时分
- getTime(dateTimeStr) {
- const date = new Date(dateTimeStr);
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const time = `${hours}:${minutes}`;
- return time;
- },
- // 格式化时间范围:09:00 - 09:30
- formatTimeRange(start, end) {
- return start && end ? `${start} - ${end}` : "--";
- },
- // 输入框事件
- onIpInput(e) {
- this.serverIp = e.detail.value;
- },
- onPortInput(e) {
- this.serverPort = e.detail.value;
- },
- // 构建 WebSocket URL
- getWebSocketUrl() {
- return `ws://${this.serverIp}:${this.serverPort}`;
- },
- // 处理重连
- handleReconnect() {
- uni.showLoading({
- title: "正在重连..."
- });
- this.connectionStatus = "connecting";
- if (this.ws) {
- this.ws.close({
- success: () => {
- formatAppLog("log", "at pages/index/index.vue:180", "旧连接已关闭");
- this.connectWebSocket("link");
- },
- fail: () => {
- this.connectWebSocket("link");
- }
- });
- } else {
- this.connectWebSocket("link");
- }
- setTimeout(() => {
- uni.hideLoading();
- }, 2e3);
- },
- // 建立 WebSocket 连接
- connectWebSocket(type) {
- const url = this.getWebSocketUrl();
- this.ws = uni.connectSocket({
- url,
- success: (res) => {
- formatAppLog("log", "at pages/index/index.vue:201", "connectSocket success", res);
- },
- fail: (err) => {
- formatAppLog("error", "at pages/index/index.vue:204", "connectSocket 失败", err);
- this.connectionStatus = "disconnected";
- this.reconnect();
- }
- });
- this.ws.onOpen((res) => {
- this.connectionStatus = "connected";
- this.ws.send({
- data: type
- });
- this.startHeartbeat();
- uni.hideLoading();
- });
- this.ws.onMessage((res) => {
- if (res.data === "PONG" || res.data === '{"type":"PONG"}') {
- this.isPongReceived = true;
- if (this.heartbeatTimeout) {
- clearTimeout(this.heartbeatTimeout);
- this.heartbeatTimeout = null;
- }
- return;
- }
- try {
- const data = JSON.parse(res.data);
- this.handleMessage(data);
- } catch (e) {
- formatAppLog("warn", "at pages/index/index.vue:237", "非 JSON 消息,已忽略", res.data);
- }
- });
- this.ws.onClose((res) => {
- formatAppLog("log", "at pages/index/index.vue:241", "WebSocket 连接关闭", res);
- this.connectionStatus = "disconnected";
- this.stopHeartbeat();
- this.reconnect();
- });
- this.ws.onError((err) => {
- formatAppLog("error", "at pages/index/index.vue:247", "WebSocket 错误", err);
- this.connectionStatus = "disconnected";
- });
- },
- // 处理收到的消息
- handleMessage(data) {
- if (data.action == "link") {
- this.updateListWithArray(data.data);
- return;
- }
- if (typeof data === "object" && data !== null) {
- const action = data.action;
- if (!action) {
- formatAppLog("warn", "at pages/index/index.vue:263", "消息缺少 action 字段", data);
- return;
- }
- switch (action) {
- case "add":
- case "create":
- this.batchAdd(data.data);
- break;
- case "update":
- this.batchUpdate(data.data);
- break;
- case "remove":
- case "delete":
- this.batchRemove(data.data);
- break;
- default:
- formatAppLog("warn", "at pages/index/index.vue:279", "未知操作类型:", action);
- }
- } else {
- formatAppLog("warn", "at pages/index/index.vue:282", "收到未知格式消息:", data);
- }
- },
- // 批量新增
- batchAdd(data) {
- if (!data)
- return;
- const items = Array.isArray(data) ? data : [data];
- const validItems = items.filter((item) => item && item.id !== void 0);
- if (validItems.length === 0) {
- formatAppLog("warn", "at pages/index/index.vue:291", "没有有效数据用于新增", data);
- return;
- }
- const updated = [...this.list];
- validItems.forEach((item) => {
- const index = updated.findIndex((i) => i.id == item.id);
- if (index > -1) {
- updated[index] = {
- ...updated[index],
- ...item
- };
- } else {
- updated.unshift(item);
- }
- });
- this.list = updated;
- },
- // 批量修改
- batchUpdate(data) {
- if (!data)
- return;
- const items = Array.isArray(data) ? data : [data];
- const updated = [...this.list];
- items.forEach((item) => {
- if (!item || item.id === void 0)
- return;
- const index = updated.findIndex((i) => i.id == item.id);
- if (index > -1) {
- updated[index] = {
- ...updated[index],
- ...item
- };
- }
- });
- this.list = updated;
- },
- // 批量删除
- batchRemove(data) {
- let idsToRemove = [];
- if (Array.isArray(data.id)) {
- idsToRemove = data.id;
- } else if (data.id !== void 0) {
- idsToRemove = [data.id];
- } else if (Array.isArray(data.data)) {
- idsToRemove = data.data.map((item) => item.id).filter((id) => id !== void 0);
- } else {
- idsToRemove = [data.id];
- formatAppLog("warn", "at pages/index/index.vue:342", "无法解析删除指令", data);
- return;
- }
- if (idsToRemove.length === 0)
- return;
- const updated = this.list.filter((item) => !idsToRemove.includes(item.id));
- this.list = updated;
- },
- updateListWithArray(newList) {
- if (!Array.isArray(newList))
- return;
- const map = /* @__PURE__ */ new Map();
- newList.forEach((item) => {
- if (item.id !== void 0) {
- map.set(item.id, item);
- }
- });
- const updated = [...this.list];
- for (const [id, item] of map.entries()) {
- const index = updated.findIndex((i) => i.id == id);
- if (index > -1) {
- updated[index] = item;
- } else {
- updated.push(item);
- }
- }
- const final = updated.filter((item) => map.has(item.id));
- this.list = final;
- },
- // 断线重连(指数退避)
- reconnect() {
- if (this.reconnectTimer)
- return;
- this.reconnectTimer = setTimeout(() => {
- formatAppLog("log", "at pages/index/index.vue:377", "正在尝试重新连接...");
- this.connectWebSocket("link");
- this.reconnectTimer = null;
- }, 3e3);
- },
- // 启动心跳
- startHeartbeat() {
- formatAppLog("log", "at pages/index/index.vue:384", 2324);
- this.stopHeartbeat();
- this.heartbeatTimer = setInterval(() => {
- if (this.ws && this.connectionStatus === "connected") {
- if (!this.isPongReceived) {
- formatAppLog("warn", "at pages/index/index.vue:392", "上一次心跳未收到 pong,可能已断线");
- this.ws.close();
- return;
- }
- this.isPongReceived = false;
- this.heartbeatTimeout = setTimeout(() => {
- if (!this.isPongReceived) {
- formatAppLog("warn", "at pages/index/index.vue:401", "⚠️ 心跳超时:未在规定时间内收到 pong,即将重连");
- uni.showToast({
- title: "连接异常,正在重连...",
- icon: "none",
- duration: 2e3
- });
- this.ws.close();
- }
- }, this.heartbeatTimeoutTime);
- try {
- this.ws.send({
- data: "PING",
- success: () => {
- },
- fail: (err) => {
- formatAppLog("error", "at pages/index/index.vue:417", "ping 发送失败", err);
- this.ws.close();
- }
- });
- } catch (e) {
- formatAppLog("error", "at pages/index/index.vue:422", "发送 ping 异常", e);
- this.ws.close();
- }
- }
- }, this.heartbeatInterval);
- },
- // 停止心跳(断开连接时调用)
- stopHeartbeat() {
- if (this.heartbeatTimer) {
- clearInterval(this.heartbeatTimer);
- this.heartbeatTimer = null;
- }
- if (this.heartbeatTimeout) {
- clearTimeout(this.heartbeatTimeout);
- this.heartbeatTimeout = null;
- }
- },
- updateCurrentTime() {
- const now = /* @__PURE__ */ new Date();
- const year = now.getFullYear();
- const month = String(now.getMonth() + 1).padStart(2, "0");
- const day = String(now.getDate()).padStart(2, "0");
- const hours = String(now.getHours()).padStart(2, "0");
- const minutes = String(now.getMinutes()).padStart(2, "0");
- const seconds = String(now.getSeconds()).padStart(2, "0");
- this.currentTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
- },
- goback() {
- uni.navigateTo({
- url: "/pages/index/home"
- });
- }
- },
- mounted() {
- this.connectWebSocket("link");
- this.updateCurrentTime();
- this.timeTimer = setInterval(() => {
- this.updateCurrentTime();
- }, 1e3);
- },
- // 页面卸载时关闭连接
- beforeDestroy() {
- if (this.ws) {
- this.ws.close();
- }
- if (this.reconnectTimer) {
- clearTimeout(this.reconnectTimer);
- }
- this.stopHeartbeat();
- if (this.timeTimer) {
- clearInterval(this.timeTimer);
- }
- }
- };
- function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
- return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [
- vue.createElementVNode("view", { class: "header" }, [
- vue.createElementVNode("text", { class: "title" }, "接种留观人员信息表"),
- vue.createElementVNode(
- "text",
- { class: "current-time" },
- vue.toDisplayString($data.currentTime),
- 1
- /* TEXT */
- )
- ]),
- vue.createCommentVNode(" 表格 "),
- vue.createElementVNode("view", { class: "table-container" }, [
- vue.createCommentVNode(" 表头 "),
- vue.createElementVNode("view", { class: "table-header" }, [
- vue.createElementVNode("view", { class: "table-row header-row" }, [
- vue.createElementVNode("view", { class: "cell name title_color" }, "姓名"),
- vue.createElementVNode("view", { class: "cell time title_color" }, "留观时间"),
- vue.createElementVNode("view", { class: "cell time title_color" }, "离开时间"),
- vue.createElementVNode("view", { class: "cell status title_color" }, "状态")
- ])
- ]),
- vue.createCommentVNode(" 表格主体 - 支持纵向轮播滚动 "),
- vue.createElementVNode("view", { class: "table-body-container" }, [
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["table-body-wrapper", { "animate": $options.shouldAnimate }])
- },
- [
- (vue.openBlock(true), vue.createElementBlock(
- vue.Fragment,
- null,
- vue.renderList($options.carouselList, (item, index) => {
- return vue.openBlock(), vue.createElementBlock(
- "view",
- {
- key: index,
- class: vue.normalizeClass(["table-row body-row", `item-${$options.getClass(item.status)}`])
- },
- [
- vue.createElementVNode(
- "view",
- { class: "cell name" },
- vue.toDisplayString(item.patientName),
- 1
- /* TEXT */
- ),
- vue.createElementVNode(
- "view",
- { class: "cell time" },
- vue.toDisplayString($options.getTime(item.createTime)),
- 1
- /* TEXT */
- ),
- vue.createElementVNode(
- "view",
- { class: "cell time" },
- vue.toDisplayString($options.getTime(item.outTime)),
- 1
- /* TEXT */
- ),
- vue.createElementVNode("view", { class: "cell status" }, [
- vue.createElementVNode(
- "text",
- {
- class: vue.normalizeClass(["status-tag", `status-${$options.getClass(item.status)}`])
- },
- vue.toDisplayString($options.getStatusText(item.status)),
- 3
- /* TEXT, CLASS */
- )
- ])
- ],
- 2
- /* CLASS */
- );
- }),
- 128
- /* KEYED_FRAGMENT */
- ))
- ],
- 2
- /* CLASS */
- )
- ])
- ]),
- vue.createCommentVNode(" 连接状态与IP编辑栏 "),
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["status-bar-bottom", `status-${$data.connectionStatus}`])
- },
- [
- vue.createElementVNode("view", { class: "status-text-box" }, [
- vue.createElementVNode(
- "text",
- {
- class: vue.normalizeClass(["dot", `dot-${$data.connectionStatus}`])
- },
- "●",
- 2
- /* CLASS */
- ),
- vue.createElementVNode(
- "text",
- { class: "status-text" },
- vue.toDisplayString($options.connectionText),
- 1
- /* TEXT */
- )
- ]),
- vue.createCommentVNode(" IP 编辑区域 "),
- vue.createElementVNode("view", { class: "ip-input-group" }, [
- vue.createElementVNode("text", { class: "ip-label" }, "IP:"),
- vue.createElementVNode("input", {
- type: "text",
- value: $data.serverIp,
- onInput: _cache[0] || (_cache[0] = (...args) => $options.onIpInput && $options.onIpInput(...args)),
- placeholder: "192.168.0.41",
- class: "ip-input"
- }, null, 40, ["value"]),
- vue.createElementVNode("text", { class: "colon" }, ":"),
- vue.createElementVNode("input", {
- type: "number",
- value: $data.serverPort,
- onInput: _cache[1] || (_cache[1] = (...args) => $options.onPortInput && $options.onPortInput(...args)),
- placeholder: "8811",
- class: "port-input"
- }, null, 40, ["value"]),
- vue.createElementVNode("button", {
- class: "btn-reconnect",
- size: "mini",
- onClick: _cache[2] || (_cache[2] = (...args) => $options.handleReconnect && $options.handleReconnect(...args))
- }, " 更新并重连 "),
- vue.createElementVNode("button", {
- class: "btn-reconnect",
- size: "mini",
- onClick: _cache[3] || (_cache[3] = (...args) => $options.goback && $options.goback(...args))
- }, " 测试 ")
- ])
- ],
- 2
- /* CLASS */
- )
- ]);
- }
- const PagesIndexIndex = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__scopeId", "data-v-1cf27b2a"], ["__file", "D:/code/baozhida-observation-system/pages/index/index.vue"]]);
- const _sfc_main$1 = {
- data() {
- return {
- serverIp: uni.getStorageSync("serverIp") || "",
- scanning: false
- };
- },
- methods: {
- async scan() {
- if (this.scanning)
- return;
- this.scanning = true;
- const ip = await this.scanNetwork();
- if (ip) {
- this.serverIp = ip;
- uni.showToast({ title: "发现: " + ip });
- } else {
- uni.showToast({ icon: "none", title: "未发现" });
- }
- this.scanning = false;
- },
- async scanNetwork() {
- const lastIp = uni.getStorageSync("serverIp");
- if (lastIp && await this.testIp(lastIp)) {
- return lastIp;
- }
- const prefix = this.getNetworkPrefix();
- for (let i = 1; i <= 50; i++) {
- const ip = `${prefix}${i}`;
- if (await this.testIp(ip)) {
- return ip;
- }
- await this.delay(100);
- }
- return null;
- },
- testIp(ip) {
- return new Promise((resolve) => {
- uni.request({
- url: `http://${ip}:8811/ping`,
- timeout: 3e3,
- success: (res) => {
- resolve(res.statusCode === 200 ? ip : null);
- },
- fail: () => resolve(null)
- });
- });
- },
- getNetworkPrefix() {
- let prefix = "192.168.1.";
- if (typeof plus !== "undefined" && plus.networkinfo) {
- const ip = plus.networkinfo.getIPAddress();
- if (ip)
- prefix = ip.replace(/\.\d+$/, ".") + ".";
- }
- return prefix;
- },
- delay(ms) {
- return new Promise((resolve) => setTimeout(resolve, ms));
- },
- connect() {
- if (!this.serverIp) {
- uni.showToast({ icon: "none", title: "请先设置IP" });
- return;
- }
- uni.setStorageSync("serverIp", this.serverIp);
- uni.connectSocket({ url: `ws://${this.serverIp}:8811` });
- uni.onSocketOpen(() => {
- "link";
- });
- }
- }
- };
- function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
- return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [
- vue.createElementVNode("text", null, "服务端IP:"),
- vue.withDirectives(vue.createElementVNode(
- "input",
- {
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.serverIp = $event),
- placeholder: "192.168.1.100"
- },
- null,
- 512
- /* NEED_PATCH */
- ), [
- [vue.vModelText, $data.serverIp]
- ]),
- vue.createElementVNode("button", {
- onClick: _cache[1] || (_cache[1] = (...args) => $options.scan && $options.scan(...args))
- }, "🔍 自动扫描"),
- vue.createElementVNode("button", {
- onClick: _cache[2] || (_cache[2] = (...args) => $options.connect && $options.connect(...args))
- }, "🚀 连接"),
- $data.scanning ? (vue.openBlock(), vue.createElementBlock("text", { key: 0 }, "扫描中...")) : vue.createCommentVNode("v-if", true)
- ]);
- }
- const PagesIndexMine = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__file", "D:/code/baozhida-observation-system/pages/index/mine.vue"]]);
- __definePage("pages/index/home", PagesIndexHome);
- __definePage("pages/index/index", PagesIndexIndex);
- __definePage("pages/index/mine", PagesIndexMine);
- const _sfc_main = {
- mounted() {
- plus.screen.lockOrientation("landscape-primary");
- },
- onLaunch: function() {
- formatAppLog("log", "at App.vue:11", "App Launch");
- plus.screen.lockOrientation("landscape-primary");
- },
- onShow: function() {
- formatAppLog("log", "at App.vue:18", "App Show");
- },
- onHide: function() {
- formatAppLog("log", "at App.vue:21", "App Hide");
- }
- };
- const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "D:/code/baozhida-observation-system/App.vue"]]);
- function createApp() {
- const app = vue.createVueApp(App);
- return {
- app
- };
- }
- const { app: __app__, Vuex: __Vuex__, Pinia: __Pinia__ } = createApp();
- uni.Vuex = __Vuex__;
- uni.Pinia = __Pinia__;
- __app__.provide("__globalStyles", __uniConfig.styles);
- __app__._component.mpType = "app";
- __app__._component.render = () => {
- };
- __app__.mount("#app");
- })(Vue);
|