Compare commits
15 Commits
Author | SHA1 | Date |
---|---|---|
|
5f002865f1 | |
|
f785745c79 | |
|
d3fd661ecf | |
|
5c70211154 | |
|
6ff82d7fe4 | |
|
d45dde9261 | |
|
794c02b94c | |
|
80bbaf8f54 | |
|
4e809cde3f | |
|
f72d117d90 | |
|
3fbb21aa1d | |
|
10bea9c95e | |
|
2f2982d4af | |
|
7b2c05bc57 | |
|
275f3ac859 |
|
@ -0,0 +1 @@
|
|||
*.sh eol=lf
|
|
@ -28,9 +28,9 @@ coverage
|
|||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
package-lock.json
|
||||
components.d.ts
|
||||
auto-imports.d.ts
|
||||
|
||||
# Personal
|
||||
**/_priv_*
|
||||
**/_priv_*
|
||||
Makefile
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 kerms
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
19
README.md
19
README.md
|
@ -1 +1,18 @@
|
|||
# 允斯调试器的内嵌网页版上位机
|
||||
# 允斯无线透传器的内嵌网页版上位机
|
||||
|
||||
此项目使用`NPM`包管理, 需要先安装`node`工具。
|
||||
|
||||
# 环境准备步骤
|
||||
|
||||
##### 本地测试:
|
||||
|
||||
1. `npm install`
|
||||
2. `npm run dev`,或用 `npm run devh` 则可以用其他设备访问,如手机调试移动界面。
|
||||
3. 根据显示的地址,使用浏览器打开,默认地址为`localhost:5173`, 或者其他设备访问`192.168.X.X:5173`
|
||||
|
||||
##### 发布至esp32:
|
||||
|
||||
1. `npm install`
|
||||
2. `npm run build` -> 会在`dist/`生成`index.html`和`ws.sharedworker.js`
|
||||
3. 在`dist/`里执行`gzip *` -> -> 会在`dist/`生成`index.html.gz`和`ws.sharedworker.js.gz`
|
||||
4. 至此,可以使用这两个文件覆盖ESP32目录中的`project_components/html`里相对应的文件了。
|
||||
|
|
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
|
@ -5,8 +5,10 @@
|
|||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": ". ./set_env.sh && vite",
|
||||
"devh": ". ./set_env.sh && vite --host",
|
||||
"build": "run-p type-check \"build-only {@}\" --",
|
||||
"preview": ". ./set_env.sh && vite preview",
|
||||
"previewh": ". ./set_env.sh && vite preview --host",
|
||||
"build-only": ". ./set_env.sh && vite build",
|
||||
"build:dev": ". ./set_env.sh && vite build --mode development",
|
||||
"type-check": "vue-tsc --build --force",
|
||||
|
@ -14,12 +16,16 @@
|
|||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"element-plus": "^2.6.1",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"ansi_up": "^6.0.2",
|
||||
"element-plus": "^2.7.3",
|
||||
"mitt": "^3.0.1",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "^3.4.21",
|
||||
"vue-draggable-plus": "^0.4.1",
|
||||
"vue-i18n": "^9.10.2",
|
||||
"vue-router": "^4.3.0"
|
||||
"vue-router": "^4.3.0",
|
||||
"vuetify": "^3.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.3.3",
|
||||
|
@ -40,10 +46,11 @@
|
|||
"typescript": "~5.4.0",
|
||||
"unplugin-auto-import": "^0.17.5",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"vite": "^5.1.6",
|
||||
"vite": "^5.3.3",
|
||||
"vite-plugin-css-injected-by-js": "^3.5.0",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vite-plugin-singlefile": "^2.0.1",
|
||||
"vite-plugin-singlefile": "^2.0.2",
|
||||
"vite-plugin-vuetify": "^2.0.3",
|
||||
"vite-svg-loader": "^5.1.0",
|
||||
"vue-tsc": "^2.0.6"
|
||||
}
|
||||
|
|
10
set_env.sh
10
set_env.sh
|
@ -1,3 +1,7 @@
|
|||
#!/bin/bash
|
||||
export VITE_APP_GIT_TAG=$(git describe --tags)
|
||||
export VITE_APP_LAST_COMMIT=$(git log -1 --format=%cd)
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VITE_APP_GIT_TAG=$(git describe --tags | cut -d'-' -f1,2)
|
||||
VITE_APP_LAST_COMMIT=$(git log -1 --format=%cd)
|
||||
|
||||
export VITE_APP_GIT_TAG
|
||||
export VITE_APP_LAST_COMMIT
|
12
src/App.vue
12
src/App.vue
|
@ -40,7 +40,7 @@ onMounted(() => {
|
|||
logHelloMessage();
|
||||
let host = "";
|
||||
if (isDevMode()) {
|
||||
host = import.meta.env.VITE_DEVICE_HOST_NAME;
|
||||
host = import.meta.env.VITE_DEVICE_HOST_NAME || "dap.local";
|
||||
} else {
|
||||
host = window.location.host
|
||||
}
|
||||
|
@ -55,8 +55,10 @@ onUnmounted(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<header>
|
||||
<nav-bar/>
|
||||
</header>
|
||||
<RouterView/>
|
||||
<div class="flex flex-col h-screen">
|
||||
<header>
|
||||
<nav-bar/>
|
||||
</header>
|
||||
<RouterView/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,47 +1,75 @@
|
|||
import {type ApiJsonMsg, sendJsonMsg} from '@/api'
|
||||
import {type ApiJsonMsg, sendJsonMsg, WtModuleID} from '@/api'
|
||||
|
||||
export const WifiModuleID = 1;
|
||||
export enum WifiCmd {
|
||||
UNKNOWN = 0,
|
||||
WIFI_API_JSON_STA_GET_AP_INFO,
|
||||
WIFI_API_JSON_CONNECT,
|
||||
WIFI_API_JSON_GET_SCAN,
|
||||
WIFI_API_JSON_DISCONNECT,
|
||||
WIFI_API_JSON_AP_GET_INFO,
|
||||
WIFI_API_JSON_STA_GET_AP_INFO = 1,
|
||||
WIFI_API_JSON_CONNECT = 2,
|
||||
WIFI_API_JSON_GET_SCAN = 3,
|
||||
WIFI_API_JSON_DISCONNECT = 4,
|
||||
WIFI_API_JSON_AP_GET_INFO = 5,
|
||||
WIFI_API_JSON_GET_MODE = 6,
|
||||
WIFI_API_JSON_SET_MODE = 7,
|
||||
WIFI_API_JSON_AP_SET_CRED = 8,
|
||||
WIFI_API_JSON_STA_GET_STATIC_INFO = 9,
|
||||
WIFI_API_JSON_STA_SET_STATIC_CONF = 10,
|
||||
}
|
||||
|
||||
interface WifiMsgOut extends ApiJsonMsg {
|
||||
export enum WifiMode {
|
||||
/* permanent */
|
||||
WIFI_AP_AUTO_STA_ON = 0,
|
||||
|
||||
WIFI_AP_STA_OFF = 4, /* 100 */
|
||||
WIFI_AP_OFF_STA_ON = 5, /* 101 */
|
||||
WIFI_AP_ON_STA_OFF = 6, /* 110 */
|
||||
WIFI_AP_STA_ON = 7, /* 111 */
|
||||
|
||||
/* temporary */
|
||||
WIFI_AP_STOP = 8,
|
||||
WIFI_AP_START = 9,
|
||||
WIFI_STA_STOP = 10,
|
||||
WIFI_STA_START = 11,
|
||||
}
|
||||
|
||||
export enum WifiStatus {
|
||||
WIFI_MODE_NULL = 0, /**< null mode */
|
||||
WIFI_MODE_STA, /**< WiFi station mode */
|
||||
WIFI_MODE_AP, /**< WiFi soft-AP mode */
|
||||
WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */
|
||||
}
|
||||
|
||||
export interface WiFiCredential extends ApiJsonMsg {
|
||||
ssid?: string;
|
||||
password?: string;
|
||||
err?: string;
|
||||
}
|
||||
|
||||
export function wifi_get_scan_list() {
|
||||
const msg : WifiMsgOut = {
|
||||
module: WifiModuleID,
|
||||
const msg : WiFiCredential = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_GET_SCAN,
|
||||
}
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
export function wifi_sta_get_ap_info() {
|
||||
const msg : WifiMsgOut = {
|
||||
module: WifiModuleID,
|
||||
const msg : WiFiCredential = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO,
|
||||
}
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
export function wifi_ap_get_info() {
|
||||
const msg : WifiMsgOut = {
|
||||
module: WifiModuleID,
|
||||
const msg : WiFiCredential = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_AP_GET_INFO,
|
||||
}
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
export function wifi_connect_to(ssid: string, password: string) {
|
||||
const msg: WifiMsgOut = {
|
||||
module: WifiModuleID,
|
||||
const msg: WiFiCredential = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_CONNECT,
|
||||
ssid: ssid,
|
||||
password: password,
|
||||
|
@ -50,6 +78,19 @@ export function wifi_connect_to(ssid: string, password: string) {
|
|||
}
|
||||
|
||||
export interface WifiInfo extends ApiJsonMsg {
|
||||
rssi: number;
|
||||
ssid: string;
|
||||
password: string;
|
||||
gateway: string;
|
||||
ip: string;
|
||||
mac: string;
|
||||
netmask: string;
|
||||
dns_main: string;
|
||||
dns_backup: string;
|
||||
wifiLogo?: string;
|
||||
}
|
||||
|
||||
export interface WifiScanInfo extends ApiJsonMsg {
|
||||
rssi: number;
|
||||
ssid: string;
|
||||
gateway: string;
|
||||
|
@ -59,6 +100,87 @@ export interface WifiInfo extends ApiJsonMsg {
|
|||
wifiLogo?: string;
|
||||
}
|
||||
|
||||
export interface WifiList {
|
||||
scan_list: Array<WifiInfo>;
|
||||
export interface WifiList extends ApiJsonMsg {
|
||||
scan_list: Array<WifiScanInfo>;
|
||||
}
|
||||
|
||||
export interface IWifiMode extends ApiJsonMsg {
|
||||
mode?: WifiMode;
|
||||
status?: WifiStatus;
|
||||
ap_on_delay?: number;
|
||||
ap_off_delay?: number;
|
||||
err?: string;
|
||||
}
|
||||
|
||||
export function wifi_set_mode(req_mode: WifiMode, ap_on_delay = -1, ap_off_delay = -1) {
|
||||
let msg: IWifiMode;
|
||||
if (req_mode === WifiMode.WIFI_AP_AUTO_STA_ON && ap_on_delay !== -1 && ap_off_delay !== -1) {
|
||||
msg = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_SET_MODE,
|
||||
mode: req_mode,
|
||||
ap_on_delay: ap_on_delay,
|
||||
ap_off_delay: ap_off_delay,
|
||||
};
|
||||
} else {
|
||||
msg = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_SET_MODE,
|
||||
mode: req_mode,
|
||||
};
|
||||
}
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
export function wifi_get_mode() {
|
||||
const msg: IWifiMode = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_GET_MODE,
|
||||
};
|
||||
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
export function wifi_ap_set_credential(ssid: string, password: string) {
|
||||
const msg : WiFiCredential = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_AP_SET_CRED,
|
||||
ssid: ssid,
|
||||
password: password,
|
||||
}
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
export interface IWifiStaStaticInfo {
|
||||
static_ip_en: number;
|
||||
static_dns_en: number;
|
||||
ip: string;
|
||||
gateway: string;
|
||||
netmask: string;
|
||||
dns_main: string;
|
||||
dns_backup: string;
|
||||
}
|
||||
export function wifi_sta_get_static_info() {
|
||||
const msg: ApiJsonMsg = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_STA_GET_STATIC_INFO,
|
||||
}
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
export function wifi_sta_set_static_conf(static_info: IWifiStaStaticInfo) {
|
||||
const msg: IWifiStaStaticInfo & ApiJsonMsg = {
|
||||
module: WtModuleID.WIFI,
|
||||
cmd: WifiCmd.WIFI_API_JSON_STA_SET_STATIC_CONF,
|
||||
static_dns_en: static_info.static_dns_en,
|
||||
static_ip_en: static_info.static_ip_en,
|
||||
ip: static_info.ip,
|
||||
gateway: static_info.gateway,
|
||||
netmask: static_info.netmask,
|
||||
dns_main: static_info.dns_main,
|
||||
dns_backup: static_info.dns_backup,
|
||||
}
|
||||
sendJsonMsg(msg);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import type {WtModuleID} from "@/api/index";
|
||||
|
||||
export enum WtDataType {
|
||||
RESERVED = 0x00,
|
||||
/* primitive type */
|
||||
EVENT = 0x02,
|
||||
ROUTE_HDR = 0x03,
|
||||
RAW_BROADCAST = 0x04,
|
||||
|
||||
/* broadcast data */
|
||||
CMD_BROADCAST = 0x11,
|
||||
|
||||
/* targeted data */
|
||||
RAW = 0x20,
|
||||
CMD = 0x21,
|
||||
RESPONSE = 0x22,
|
||||
|
||||
/* standard protocols */
|
||||
PROTOBUF = 0x40,
|
||||
JSON = 0x41,
|
||||
MQTT = 0x42,
|
||||
}
|
||||
|
||||
|
||||
export interface ApiBinaryMsg {
|
||||
data_type: WtDataType,
|
||||
module: WtModuleID,
|
||||
sub_mod: number,
|
||||
payload: Uint8Array;
|
||||
}
|
||||
|
||||
export function decodeHeader(arrayBuffer: ArrayBuffer) : ApiBinaryMsg {
|
||||
// Create a DataView to access the data in the ArrayBuffer
|
||||
const dataView = new DataView(arrayBuffer);
|
||||
|
||||
// Extract the data_type from the first byte
|
||||
const data_type = dataView.getUint8(0) as WtDataType;
|
||||
|
||||
// Extract the module_id and sub_id from the next bytes
|
||||
const module = dataView.getUint8(1);
|
||||
const sub_mod = dataView.getUint8(2);
|
||||
|
||||
const payload = new Uint8Array(arrayBuffer.slice(4));
|
||||
|
||||
// Constructing the header object
|
||||
return {
|
||||
data_type,
|
||||
module,
|
||||
sub_mod,
|
||||
payload,
|
||||
};
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import {getWebsocketService} from "@/composables/websocket/websocketService";
|
||||
import type {ApiBinaryMsg} from "@/api/binDataDef";
|
||||
|
||||
export interface ApiJsonMsg {
|
||||
module: number;
|
||||
|
@ -26,18 +27,34 @@ export interface ControlMsg {
|
|||
|
||||
export interface ServerMsg {
|
||||
type: "json" | "binary"
|
||||
data: ApiJsonMsg | object;
|
||||
data: string | ArrayBuffer;
|
||||
}
|
||||
|
||||
export enum WtModuleID {
|
||||
WIFI = 1,
|
||||
DATA_FLOW = 2,
|
||||
UART = 4,
|
||||
}
|
||||
|
||||
export function sendJsonMsg(apiJsonMsg: ApiJsonMsg) {
|
||||
const msg: ServerMsg = {
|
||||
type: "json",
|
||||
data: apiJsonMsg,
|
||||
data: JSON.stringify(apiJsonMsg),
|
||||
};
|
||||
getWebsocketService().send(msg);
|
||||
// toServer.postMessage(msg);
|
||||
}
|
||||
|
||||
export function sendBinMsg(msg: ApiJsonMsg) {
|
||||
// toServer.postMessage(JSON.stringify(msg));
|
||||
export function sendBinMsg(binMsg: ApiBinaryMsg) {
|
||||
const buffer = new Uint8Array(4 + binMsg.payload.length);
|
||||
buffer[0] = binMsg.data_type;
|
||||
buffer[1] = binMsg.module;
|
||||
buffer[2] = binMsg.sub_mod;
|
||||
buffer[3] = 0; // Reserved byte
|
||||
buffer.set(binMsg.payload, 4); // Append payload after header
|
||||
|
||||
const msg: ServerMsg = {
|
||||
type: "binary",
|
||||
data: buffer,
|
||||
};
|
||||
getWebsocketService().send(msg);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#5f6368"><path d="m136-80-56-56 264-264H160v-80h320v320h-80v-184L136-80Zm344-400v-320h80v184l264-264 56 56-264 264h184v80H480Z"/></svg>
|
After Width: | Height: | Size: 206 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#5f6368"><path d="M478-240q21 0 35.5-14.5T528-290q0-21-14.5-35.5T478-340q-21 0-35.5 14.5T428-290q0 21 14.5 35.5T478-240Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342-618l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506-526q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
After Width: | Height: | Size: 668 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#5f6368"><path d="M120-120v-320h80v184l504-504H520v-80h320v320h-80v-184L256-200h184v80H120Z"/></svg>
|
After Width: | Height: | Size: 171 B |
|
@ -1,5 +1,5 @@
|
|||
.text-layout {
|
||||
@apply m-auto max-w-2xl min-w-min px-2
|
||||
@apply mx-auto max-w-2xl w-full sm:min-w-[640px] px-2
|
||||
}
|
||||
|
||||
.page-title {
|
||||
|
@ -14,3 +14,8 @@
|
|||
@apply text-blue-600 font-bold;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.el-checkbox:hover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border-color: var(--el-color-primary-light-8);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ class OneTimeWebsocket implements IWebsocket {
|
|||
/* did not receive packet "heartBeatTimeout" times,
|
||||
* connection may be lost: close the socket */
|
||||
if (this.socket.readyState === this.socket.OPEN) {
|
||||
console.log("No heart beat, break connection");
|
||||
this.close();
|
||||
this.clear();
|
||||
}
|
||||
|
@ -80,31 +81,21 @@ class OneTimeWebsocket implements IWebsocket {
|
|||
return
|
||||
|
||||
const msg: ServerMsg = {
|
||||
data: {},
|
||||
data: ev.data,
|
||||
type: "json",
|
||||
}
|
||||
if (typeof ev.data === "string") {
|
||||
try {
|
||||
msg.data = JSON.parse(ev.data) as ApiJsonMsg;
|
||||
if ((msg.data as ApiJsonMsg).cmd === undefined ||
|
||||
(msg.data as ApiJsonMsg).module === undefined
|
||||
){
|
||||
console.log("Server msg has no cmd or module");
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return;
|
||||
}
|
||||
msg.type = "json"
|
||||
} else {
|
||||
msg.type = "binary";
|
||||
msg.data = ev.data;
|
||||
console.log(typeof ev.data);
|
||||
}
|
||||
this.msgCallback(msg);
|
||||
}
|
||||
|
||||
this.socket.onclose = () => {
|
||||
this.socket.onclose = (ev) => {
|
||||
if (isDevMode()) {
|
||||
console.log("ws closed", ev.reason, ev.code);
|
||||
}
|
||||
this.socket.onclose = null
|
||||
this.socket.onopen = null
|
||||
this.socket.onerror = null
|
||||
|
@ -150,11 +141,8 @@ class OneTimeWebsocket implements IWebsocket {
|
|||
if (isDevMode()) {
|
||||
console.log('WebSocket proxies data ', msg);
|
||||
}
|
||||
if (msg.type === "binary") {
|
||||
// this.socket.send(msg.data);
|
||||
} else if (msg.type === "json") {
|
||||
this.socket.send(JSON.stringify(msg.data));
|
||||
}
|
||||
|
||||
this.socket.send(msg.data);
|
||||
}
|
||||
|
||||
clear() {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import type {ApiJsonMsg, ControlMsg, ServerMsg} from "@/api";
|
||||
import {isDevMode} from "@/composables/buildMode";
|
||||
import {type ApiBinaryMsg, decodeHeader} from "@/api/binDataDef";
|
||||
|
||||
export interface IModuleCallback {
|
||||
ctrlCallback: (msg: ControlMsg) => void;
|
||||
serverMsgCallback: (msg: ServerMsg) => void;
|
||||
serverJsonMsgCallback: (msg: ApiJsonMsg) => void;
|
||||
serverBinMsgCallback: (msg: ApiBinaryMsg) => void;
|
||||
}
|
||||
|
||||
const moduleMap = new Map<number, IModuleCallback>();
|
||||
|
@ -22,19 +24,47 @@ export function unregisterModule(moduleId: number) {
|
|||
}
|
||||
|
||||
export function routeModuleServerMsg(msg: ServerMsg) {
|
||||
if (msg.type == "json") {
|
||||
const module = (msg.data as ApiJsonMsg).module;
|
||||
if (msg.type === "json") {
|
||||
let jsonMsg: ApiJsonMsg;
|
||||
try {
|
||||
jsonMsg = JSON.parse(msg.data as string) as ApiJsonMsg;
|
||||
if (jsonMsg.cmd === undefined ||
|
||||
jsonMsg.module === undefined
|
||||
){
|
||||
console.log("Server msg has no cmd or module", msg.data);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return;
|
||||
}
|
||||
|
||||
const module = jsonMsg.module;
|
||||
const moduleHandler = moduleMap.get(module);
|
||||
if (moduleHandler) {
|
||||
moduleHandler.serverMsgCallback(msg);
|
||||
moduleHandler.serverJsonMsgCallback(jsonMsg);
|
||||
} else {
|
||||
if (isDevMode()) {
|
||||
console.log("routeModuleServerMsg module not loaded", module);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isDevMode()) {
|
||||
console.log("routeModuleServerMsg ignored:", msg);
|
||||
const arr = msg.data as ArrayBuffer;
|
||||
if (arr.byteLength < 4) {
|
||||
if (isDevMode()) {
|
||||
console.log("binary message too short");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const binaryMsg = decodeHeader(msg.data as ArrayBuffer);
|
||||
const moduleHandler = moduleMap.get(binaryMsg.module);
|
||||
if (moduleHandler) {
|
||||
moduleHandler.serverBinMsgCallback(binaryMsg);
|
||||
} else {
|
||||
if (isDevMode()) {
|
||||
console.log("routeModuleServerMsg ignored:", msg, binaryMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
const version = import.meta.env.VITE_APP_GIT_TAG;
|
||||
const compileTime = import.meta.env.VITE_APP_LAST_COMMIT;
|
||||
const version = import.meta.env.VITE_APP_GIT_TAG || "v0.0.0";
|
||||
const compileTime = import.meta.env.VITE_APP_LAST_COMMIT || "1970-00-00";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -17,23 +17,23 @@ const compileTime = import.meta.env.VITE_APP_LAST_COMMIT;
|
|||
</el-descriptions>
|
||||
|
||||
<el-descriptions title="鸣谢" border :column="1" class="mt-5 description-style">
|
||||
<el-descriptions-item label="vuejs"><a href="https://github.com/vuejs/vue/blob/main/LICENSE">MIT</a>
|
||||
<el-descriptions-item label="vuejs"><a target="_blank" href="https://github.com/vuejs/vue/blob/main/LICENSE">MIT</a>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="typescript"><a
|
||||
href="https://github.com/microsoft/TypeScript/blob/main/LICENSE.txt">Apache 2.0</a></el-descriptions-item>
|
||||
<el-descriptions-item label="vite"><a href="https://github.com/vitejs/vite/blob/main/LICENSE">MIT</a>
|
||||
<el-descriptions-item label="vite"><a target="_blank" href="https://github.com/vitejs/vite/blob/main/LICENSE">MIT</a>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="tailwindcss"><a
|
||||
href="https://github.com/tailwindlabs/tailwindcss/blob/master/LICENSE">MIT</a></el-descriptions-item>
|
||||
<el-descriptions-item label="element-plus"><a
|
||||
href="https://github.com/element-plus/element-plus/blob/dev/LICENSE">MIT</a></el-descriptions-item>
|
||||
<el-descriptions-item label="pinia"><a href="https://github.com/vuejs/pinia/blob/v2/LICENSE">MIT</a>
|
||||
<el-descriptions-item label="pinia"><a target="_blank" href="https://github.com/vuejs/pinia/blob/v2/LICENSE">MIT</a>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="mitt"><a href="https://github.com/developit/mitt/blob/main/LICENSE">MIT</a>
|
||||
<el-descriptions-item label="mitt"><a target="_blank" href="https://github.com/developit/mitt/blob/main/LICENSE">MIT</a>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="vue-router"><a
|
||||
href="https://github.com/vuejs/vue-router/blob/dev/LICENSE">MIT</a></el-descriptions-item>
|
||||
<el-descriptions-item label="vue-i18n"><a href="https://github.com/kazupon/vue-i18n?tab=MIT-1-ov-file#readme">MIT</a>
|
||||
<el-descriptions-item label="vue-i18n"><a target="_blank" href="https://github.com/kazupon/vue-i18n?tab=MIT-1-ov-file#readme">MIT</a>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="lightningcss"><a
|
||||
href="https://github.com/parcel-bundler/lightningcss/blob/master/LICENSE">MPL-2.0 license</a>
|
||||
|
@ -42,12 +42,12 @@ const compileTime = import.meta.env.VITE_APP_LAST_COMMIT;
|
|||
</el-collapse-item>
|
||||
<el-collapse-item title="关于下位机">
|
||||
<el-descriptions border :column="1" class="mt-5 description-style">
|
||||
<el-descriptions-item label="官网"><a href="https://yunsi.studio/wireless-proxy">允斯工作室</a></el-descriptions-item>
|
||||
<el-descriptions-item label="官网"><a target="_blank" href="https://yunsi.studio/wireless-proxy">允斯工作室</a></el-descriptions-item>
|
||||
<el-descriptions-item label="版本">-</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-descriptions title="鸣谢" border :column="1" class="mt-5 description-style">
|
||||
<el-descriptions-item label="windowsair"><a href="https://github.com/windowsair/wireless-esp8266-dap">wireless-esp8266-dap</a>
|
||||
<el-descriptions-item label="windowsair"><a target="_blank" href="https://github.com/windowsair/wireless-esp8266-dap">wireless-esp8266-dap</a>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-collapse-item>
|
||||
|
@ -55,11 +55,11 @@ const compileTime = import.meta.env.VITE_APP_LAST_COMMIT;
|
|||
|
||||
|
||||
<el-descriptions title="作者:空空(kerms)" border :column="1" class="mt-5 description-style">
|
||||
<el-descriptions-item label="官网"><a href="https://yunsi.studio/">允斯工作室(https://yunsi.studio/)</a></el-descriptions-item>
|
||||
<el-descriptions-item label="github"><a href="https://github.com/kerms">https://github.com/kerms</a>
|
||||
<el-descriptions-item label="官网"><a target="_blank" href="https://yunsi.studio/">允斯工作室(https://yunsi.studio/)</a></el-descriptions-item>
|
||||
<el-descriptions-item label="github"><a target="_blank" href="https://github.com/kerms">https://github.com/kerms</a>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="邮箱">kerms@niazo.org</el-descriptions-item>
|
||||
<el-descriptions-item label="BiliBili"><a href="https://space.bilibili.com/38669852">UID38669852</a>
|
||||
<el-descriptions-item label="BiliBili"><a target="_blank" href="https://space.bilibili.com/3461571571353885">3461571571353885</a>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="QQ群">642246000</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">欢迎大家来打扰啊~</el-descriptions-item>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
</h1>
|
||||
<el-divider></el-divider>
|
||||
|
||||
|
||||
<h2 class="mb-4 text-xl font-bold tracking-tight md:text-2xl lg:text-3xl">连接Wi-Fi</h2>
|
||||
<el-form label-width="auto" ref="formRef" :model="ssidValidateForm" class="m-auto">
|
||||
<el-form-item
|
||||
|
@ -45,38 +44,82 @@
|
|||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<div class="mb-2">
|
||||
<el-alert type="info" show-icon>
|
||||
如果不是通过透传器的热点连接,更换Wi-Fi将导致此界面与透传器断开连接。
|
||||
</el-alert>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<el-button @click="onConnectClick" type="primary">连接</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<el-divider></el-divider>
|
||||
<div class="flex items-center">
|
||||
<h5 class="text-md font-bold text-gray-800 w-32">Wi-Fi模式</h5>
|
||||
<div class="flex shrink-0">
|
||||
<el-tooltip effect="light">
|
||||
<template #content>
|
||||
<p>热点+终端模式并存会影响稳定性。且保持热点开启会增加功耗。</p>
|
||||
<p>
|
||||
<el-text size="small">智能模式:</el-text>
|
||||
成功连接Wi-Fi,30秒后自动关闭热点;断开连接,5秒后自动打开热点
|
||||
</p>
|
||||
<p>
|
||||
<el-text size="small">热点+终端共存模式:</el-text>
|
||||
方便使用,但是影响稳定性
|
||||
</p>
|
||||
<p>
|
||||
<el-text size="small">单热点模式缺点:</el-text>
|
||||
无网络
|
||||
</p>
|
||||
</template>
|
||||
<InlineSvg name="help" class="w-3.5 h-3.5 text-gray-500 cursor-help"></InlineSvg>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-select v-model="wifiMode" :disabled="wsStore.state != ControlEvent.CONNECTED">
|
||||
<el-option
|
||||
v-for="item in wifiModeOptions"
|
||||
:key="item.key"
|
||||
:value="item.key"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button type="primary" @click="wifiChangeMode" :loading="wifiMode_loading">保存</el-button>
|
||||
</div>
|
||||
|
||||
<el-divider></el-divider>
|
||||
|
||||
|
||||
<el-descriptions
|
||||
title="Wi-Fi终端信息"
|
||||
title="Wi-Fi终端(STA)信息"
|
||||
:column="1"
|
||||
border
|
||||
class="description-style"
|
||||
>
|
||||
<el-descriptions-item label="asd">
|
||||
<template #label >
|
||||
<template #extra>
|
||||
<el-switch v-model="wifiSta_On" :disabled="wsStore.state != ControlEvent.CONNECTED || !wifiAp_On"
|
||||
active-text="已开启" inactive-text="未开启" :loading="wifiMode_loading"
|
||||
:before-change="()=>beforeWifiModeChange('STA')"
|
||||
/>
|
||||
</template>
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
信号强度
|
||||
</div>
|
||||
</template>
|
||||
<template #default >
|
||||
{{ wifiStaApInfo.rssi }}
|
||||
<template #default>
|
||||
<p>{{ wifiStaApInfo.rssi }}</p>
|
||||
</template>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="1">
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
SSID
|
||||
Wi-Fi名(SSID)
|
||||
</div>
|
||||
</template>
|
||||
{{ wifiStaApInfo.ssid }}
|
||||
<p>{{ wifiStaApInfo.ssid }}</p>
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item span="6" >-->
|
||||
<!-- <template #label>-->
|
||||
|
@ -84,23 +127,21 @@
|
|||
<!-- 密码-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <password-viewer password="asdasdasd"></password-viewer>-->
|
||||
<!-- <password-viewer :password="wifiStaApInfo.password"></password-viewer>-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
IP
|
||||
</div>
|
||||
</template>
|
||||
{{ wifiStaApInfo.ip }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
MAC
|
||||
</div>
|
||||
</template>
|
||||
{{ wifiStaApInfo.mac }}
|
||||
<p>{{ wifiStaApInfo.mac }}</p>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>IP(内网地址)</div>
|
||||
</template>
|
||||
<p>{{ wifiStaApInfo.ip }}</p>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
|
@ -108,43 +149,139 @@
|
|||
网关
|
||||
</div>
|
||||
</template>
|
||||
{{ wifiStaApInfo.gateway }}
|
||||
<p>{{ wifiStaApInfo.gateway }}</p>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
掩码
|
||||
</div>
|
||||
</template>
|
||||
{{ wifiStaApInfo.netmask }}
|
||||
<p>{{ wifiStaApInfo.netmask }}</p>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
首选DNS
|
||||
</div>
|
||||
</template>
|
||||
<p>{{ wifiStaApInfo.dns_main }}</p>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
备用DNS
|
||||
</div>
|
||||
</template>
|
||||
<p>{{ wifiStaApInfo.dns_backup }}</p>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
IP分配模式
|
||||
</div>
|
||||
</template>
|
||||
<el-select v-model="wifiStaticInfo.static_ip_en" :disabled="wsStore.state != ControlEvent.CONNECTED">
|
||||
<el-option
|
||||
v-for="item in staIPModeOptions"
|
||||
:key="item.key"
|
||||
:value="item.key"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4" v-if="wifiStaticInfo.static_ip_en">
|
||||
<template #label>
|
||||
<div>IP(内网地址)</div>
|
||||
</template>
|
||||
<el-input v-model="wifiStaticInfo.ip"></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4" v-if="wifiStaticInfo.static_ip_en">
|
||||
<template #label>
|
||||
<div>
|
||||
网关
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model="wifiStaticInfo.gateway"></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4" v-if="wifiStaticInfo.static_ip_en">
|
||||
<template #label>
|
||||
<div>
|
||||
掩码
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model="wifiStaticInfo.netmask"></el-input>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
DNS模式
|
||||
</div>
|
||||
</template>
|
||||
<el-select v-model="wifiStaticInfo.static_dns_en" :disabled="wsStore.state != ControlEvent.CONNECTED">
|
||||
<el-option
|
||||
v-for="item in staDNSModeOptions"
|
||||
:key="item.key"
|
||||
:value="item.key"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4" v-if="wifiStaticInfo.static_dns_en">
|
||||
<template #label>
|
||||
<div>
|
||||
首选DNS
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model="wifiStaticInfo.dns_main"></el-input>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="4" v-if="wifiStaticInfo.static_dns_en">
|
||||
<template #label>
|
||||
<div>
|
||||
备用DNS
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model="wifiStaticInfo.dns_backup"></el-input>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div class="flex justify-center mt-4">
|
||||
<el-button type="primary" :loading="wifiMode_loading" @click="wifiStaSetStaticInfo">保存</el-button>
|
||||
</div>
|
||||
|
||||
<el-divider></el-divider>
|
||||
|
||||
<el-descriptions
|
||||
title="Wi-Fi热点信息"
|
||||
title="Wi-Fi自发热点(AP)信息"
|
||||
:column="1"
|
||||
border
|
||||
class="description-style"
|
||||
>
|
||||
<template #extra>
|
||||
<el-switch v-model="wifiAp_On" :disabled="wsStore.state != ControlEvent.CONNECTED || !wifiSta_On"
|
||||
:loading="wifiMode_loading" active-text="已开启" inactive-text="未开启"
|
||||
:before-change="()=>beforeWifiModeChange('AP')"
|
||||
/>
|
||||
</template>
|
||||
<el-descriptions-item span="6">
|
||||
<template #label>
|
||||
<div>
|
||||
SSID
|
||||
Wi-Fi名(SSID)
|
||||
</div>
|
||||
</template>
|
||||
{{ wifiApInfo.ssid }}
|
||||
<div class="flex">
|
||||
<el-input v-model="wifiApInfo.ssid"></el-input>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item span="6">
|
||||
<template #label>
|
||||
<div>
|
||||
密码
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model="wifiApInfo.password"></el-input>
|
||||
</el-descriptions-item>
|
||||
<!-- <el-descriptions-item span="6">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div>-->
|
||||
<!-- 密码-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <password-viewer password="asdasdasd"></password-viewer>-->
|
||||
<!-- </el-descriptions-item>-->
|
||||
<el-descriptions-item span="4">
|
||||
<template #label>
|
||||
<div>
|
||||
|
@ -181,7 +318,9 @@
|
|||
{{ wifiApInfo.netmask }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<div class="flex justify-center mt-4">
|
||||
<el-button type="primary" :loading="wifiMode_loading" @click="wifiApChangeCredential">保存</el-button>
|
||||
</div>
|
||||
<el-divider></el-divider>
|
||||
</div>
|
||||
|
||||
|
@ -190,22 +329,32 @@
|
|||
<script setup lang="ts">
|
||||
import {computed, onMounted, onUnmounted, reactive, ref} from "vue";
|
||||
import {
|
||||
wifi_sta_get_ap_info,
|
||||
type IWifiMode,
|
||||
wifi_ap_get_info,
|
||||
wifi_ap_set_credential,
|
||||
wifi_connect_to,
|
||||
wifi_get_mode,
|
||||
wifi_get_scan_list,
|
||||
wifi_set_mode,
|
||||
wifi_sta_get_ap_info,
|
||||
WifiCmd,
|
||||
type WifiInfo,
|
||||
type WifiList,
|
||||
WifiModuleID,
|
||||
wifi_ap_get_info, wifi_connect_to
|
||||
WifiMode,
|
||||
type WifiScanInfo,
|
||||
type WiFiCredential,
|
||||
WifiStatus, wifi_sta_get_static_info,
|
||||
type IWifiStaStaticInfo, wifi_sta_set_static_conf,
|
||||
} from "@/api/apiWifi";
|
||||
import type {FormInstance} from "element-plus";
|
||||
|
||||
import InlineSvg from "@/components/InlineSvg.vue";
|
||||
import type {ApiJsonMsg, ControlMsg, ServerMsg} from "@/api";
|
||||
import {ControlEvent, ControlMsgType} from "@/api";
|
||||
import type {ApiJsonMsg, ControlMsg} from "@/api";
|
||||
import {ControlEvent, ControlMsgType, WtModuleID} from "@/api";
|
||||
import {registerModule, unregisterModule} from "@/router/msgRouter";
|
||||
import {useWsStore} from "@/stores/websocket";
|
||||
import {globalNotify, globalNotifyRightSide} from "@/composables/notification";
|
||||
import {isDevMode} from "@/composables/buildMode";
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
let wifiListPlaceholder = ref("我的WIFI")
|
||||
|
@ -214,6 +363,29 @@ let ssidValidateForm = reactive({
|
|||
password: "",
|
||||
})
|
||||
|
||||
let wifiSta_On = ref(false);
|
||||
const wifiMode_loading = ref(false)
|
||||
|
||||
let wifiAp_On = ref(false);
|
||||
|
||||
let wifiMode = ref(-1);
|
||||
|
||||
let wifiModeOptions = [
|
||||
{
|
||||
label: "智能热点+常开终端 (AP+STA)",
|
||||
key: WifiMode.WIFI_AP_AUTO_STA_ON,
|
||||
}, {
|
||||
label: "仅开启热点 (AP)",
|
||||
key: WifiMode.WIFI_AP_ON_STA_OFF,
|
||||
}, {
|
||||
label: "[不推荐] 常开热点+常开终端 (AP+STA)",
|
||||
key: WifiMode.WIFI_AP_STA_ON,
|
||||
}, /* {
|
||||
value: "仅开启终端(STA)",
|
||||
key: 2,
|
||||
},*/
|
||||
|
||||
]
|
||||
|
||||
let wsStore = useWsStore();
|
||||
|
||||
|
@ -223,18 +395,49 @@ const defWifiInfo: WifiInfo = {
|
|||
gateway: "未连接",
|
||||
ip: "未连接",
|
||||
mac: "未连接",
|
||||
dns_main: "未连接",
|
||||
dns_backup: "未连接",
|
||||
rssi: 0,
|
||||
netmask: "未连接",
|
||||
ssid: "未连接",
|
||||
password: "",
|
||||
}
|
||||
const staIPModeOptions = [
|
||||
{
|
||||
label: "自动 (DHCP)",
|
||||
key: 0,
|
||||
}, {
|
||||
label: "静态IP",
|
||||
key: 1,
|
||||
},
|
||||
]
|
||||
|
||||
const staDNSModeOptions = [
|
||||
{
|
||||
label: "自动 (使用网关)",
|
||||
key: 0,
|
||||
}, {
|
||||
label: "静态DNS",
|
||||
key: 1,
|
||||
},
|
||||
]
|
||||
|
||||
let wifiStaApInfo = reactive<WifiInfo>({...defWifiInfo});
|
||||
let wifiApInfo = reactive<WifiInfo>({...defWifiInfo});
|
||||
let wifiStaticInfo = reactive<IWifiStaStaticInfo>({
|
||||
dns_backup: "0.0.0.0",
|
||||
dns_main: "0.0.0.0",
|
||||
gateway: "0.0.0.0",
|
||||
ip: "0.0.0.0",
|
||||
netmask: "0.0.0.0",
|
||||
static_dns_en: 0,
|
||||
static_ip_en: 0,
|
||||
});
|
||||
|
||||
let scanning = ref(false);
|
||||
let scan_cb: any;
|
||||
let connectBtnClicked = 0;
|
||||
let options: Array<WifiInfo> = [];
|
||||
let options: Array<WifiScanInfo> = [];
|
||||
const scanText = computed(() => {
|
||||
return scanning.value ? "扫描中" : "扫描";
|
||||
});
|
||||
|
@ -247,29 +450,28 @@ const querySearch = (queryString: string, cb: any) => {
|
|||
}
|
||||
}
|
||||
|
||||
const onClientMsg = (msg: ServerMsg) => {
|
||||
if (msg.type !== "json") {
|
||||
return;
|
||||
}
|
||||
|
||||
let json = msg.data as ApiJsonMsg;
|
||||
|
||||
switch (json.cmd as WifiCmd) {
|
||||
const onClientMsg = (msg: ApiJsonMsg) => {
|
||||
switch (msg.cmd as WifiCmd) {
|
||||
case WifiCmd.UNKNOWN:
|
||||
break;
|
||||
case WifiCmd.WIFI_API_JSON_STA_GET_AP_INFO: {
|
||||
const info = msg.data as WifiInfo;
|
||||
Object.assign(wifiStaApInfo, info);
|
||||
const info = msg as WifiInfo;
|
||||
if (info.rssi === 0) {
|
||||
Object.assign(wifiStaApInfo, defWifiInfo);
|
||||
} else {
|
||||
Object.assign(wifiStaApInfo, info);
|
||||
}
|
||||
if (connectBtnClicked) {
|
||||
connectBtnClicked = 0;
|
||||
globalNotifyRightSide(wifiStaApInfo.ssid + " 连接成功", "success");
|
||||
wifi_sta_get_static_info();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WifiCmd.WIFI_API_JSON_CONNECT:
|
||||
break;
|
||||
case WifiCmd.WIFI_API_JSON_GET_SCAN: {
|
||||
const list = msg.data as WifiList;
|
||||
const list = msg as WifiList;
|
||||
scanning.value = false;
|
||||
list.scan_list.forEach(value => {
|
||||
if (value.rssi > -50) {
|
||||
|
@ -291,10 +493,65 @@ const onClientMsg = (msg: ServerMsg) => {
|
|||
case WifiCmd.WIFI_API_JSON_DISCONNECT:
|
||||
break;
|
||||
case WifiCmd.WIFI_API_JSON_AP_GET_INFO: {
|
||||
const info = msg.data as WifiInfo;
|
||||
const info = msg as WifiInfo;
|
||||
Object.assign(wifiApInfo, info);
|
||||
break;
|
||||
}
|
||||
case WifiCmd.WIFI_API_JSON_SET_MODE:
|
||||
wifi_get_mode();
|
||||
/* falls through */
|
||||
case WifiCmd.WIFI_API_JSON_GET_MODE: {
|
||||
const modeInfo = msg as IWifiMode;
|
||||
wifiMode_loading.value = false;
|
||||
if (modeInfo.err !== undefined) {
|
||||
globalNotifyRightSide("设置失败", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (modeInfo.status !== undefined) {
|
||||
wifiAp_On.value = modeInfo.status === WifiStatus.WIFI_MODE_AP || modeInfo.status === WifiStatus.WIFI_MODE_APSTA;
|
||||
wifiSta_On.value = modeInfo.status === WifiStatus.WIFI_MODE_STA || modeInfo.status === WifiStatus.WIFI_MODE_APSTA;
|
||||
}
|
||||
if (modeInfo.mode !== undefined) {
|
||||
if (modeInfo.mode < WifiMode.WIFI_AP_STOP) {
|
||||
wifiMode.value = modeInfo.mode;
|
||||
} else if (modeInfo.mode === WifiMode.WIFI_AP_START) {
|
||||
wifiAp_On.value = true;
|
||||
} else if (modeInfo.mode === WifiMode.WIFI_AP_STOP) {
|
||||
wifiAp_On.value = false;
|
||||
} else if (modeInfo.mode === WifiMode.WIFI_STA_START) {
|
||||
wifiSta_On.value = true;
|
||||
} else if (modeInfo.mode === WifiMode.WIFI_STA_STOP) {
|
||||
wifiSta_On.value = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WifiCmd.WIFI_API_JSON_AP_SET_CRED: {
|
||||
const wifiCred = msg as WiFiCredential;
|
||||
if (wifiCred.err !== undefined) {
|
||||
globalNotifyRightSide(wifiCred.err, "error");
|
||||
} else {
|
||||
globalNotifyRightSide("已保存配置", "success");
|
||||
}
|
||||
wifiMode_loading.value = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case WifiCmd.WIFI_API_JSON_STA_GET_STATIC_INFO: {
|
||||
const staticInfo = msg as IWifiStaStaticInfo & ApiJsonMsg;
|
||||
console.log("@@@", staticInfo);
|
||||
Object.assign(wifiStaticInfo, staticInfo);
|
||||
break;
|
||||
}
|
||||
case WifiCmd.WIFI_API_JSON_STA_SET_STATIC_CONF:
|
||||
wifiMode_loading.value = false;
|
||||
break;
|
||||
default:
|
||||
if (isDevMode()) {
|
||||
console.log(msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -311,6 +568,8 @@ const onClientCtrl = (msg: ControlMsg) => {
|
|||
if (msg.data === ControlEvent.CONNECTED) {
|
||||
wifi_sta_get_ap_info();
|
||||
wifi_ap_get_info();
|
||||
wifi_get_mode();
|
||||
wifi_sta_get_static_info();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -334,20 +593,54 @@ function onConnectClick() {
|
|||
}
|
||||
}
|
||||
|
||||
function beforeWifiModeChange(ap_sta: "AP" | "STA" = "AP") {
|
||||
if (ap_sta === "AP") {
|
||||
wifiMode_loading.value = true;
|
||||
wifi_set_mode(wifiAp_On.value ? WifiMode.WIFI_AP_STOP : WifiMode.WIFI_AP_START);
|
||||
} else {
|
||||
wifiMode_loading.value = true;
|
||||
wifi_set_mode(wifiSta_On.value ? WifiMode.WIFI_STA_STOP : WifiMode.WIFI_STA_START);
|
||||
}
|
||||
wifi_sta_get_ap_info();
|
||||
return false;
|
||||
}
|
||||
|
||||
function wifiChangeMode() {
|
||||
wifiMode_loading.value = true;
|
||||
wifi_set_mode(wifiMode.value);
|
||||
}
|
||||
|
||||
function wifiApChangeCredential() {
|
||||
if (wifiApInfo.ssid === "") {
|
||||
globalNotifyRightSide("请输入AP名称", "error");
|
||||
return;
|
||||
}
|
||||
wifiMode_loading.value = true;
|
||||
wifi_ap_set_credential(wifiApInfo.ssid, wifiApInfo.password);
|
||||
}
|
||||
|
||||
function wifiStaSetStaticInfo() {
|
||||
wifiMode_loading.value = true;
|
||||
wifi_sta_set_static_conf(wifiStaticInfo);
|
||||
wifi_sta_get_ap_info();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
registerModule(WifiModuleID, {
|
||||
registerModule(WtModuleID.WIFI, {
|
||||
ctrlCallback: onClientCtrl,
|
||||
serverMsgCallback: onClientMsg
|
||||
serverJsonMsgCallback: onClientMsg,
|
||||
serverBinMsgCallback: () => {},
|
||||
});
|
||||
wifi_sta_get_ap_info();
|
||||
wifi_ap_get_info();
|
||||
wifi_get_mode();
|
||||
wifi_sta_get_static_info();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
unregisterModule(WifiModuleID);
|
||||
unregisterModule(WtModuleID.WIFI);
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
|
|
@ -1,25 +1,31 @@
|
|||
<template>
|
||||
<nav class="relative px-2 py-1 flex justify-between items-center border-b">
|
||||
<nav class="relative px-2 py-0.5 sm:py-1 flex justify-between items-center border-b h-full">
|
||||
<div class="flex">
|
||||
<button @click.prevent="sideMenuOpen=true" class="flex items-center hover:text-blue-600 p-3">
|
||||
<svg class="block h-4 w-4 fill-current" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<button @click.prevent="sideMenuOpen=true" class="flex items-center hover:text-blue-600 pl-1 mx-4">
|
||||
<svg class="block h-3 lg:h-4 lg:w-4 fill-current" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>导航侧栏</title>
|
||||
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<router-link to="/" class="text-3xl px-4 font-bold leading-none" title="走,去码头整点薯条">
|
||||
<InlineSvg name="favicon" class="h-10"></InlineSvg>
|
||||
<router-link to="/" class="text-3xl px-4 font-bold leading-none hidden items-center sm:flex" title="走,去码头整点薯条">
|
||||
<InlineSvg name="favicon" class="h-5 lg:h-8"></InlineSvg>
|
||||
</router-link>
|
||||
|
||||
|
||||
<!-- <a class="text-3xl px-4 font-bold leading-none" href="/">-->
|
||||
<!-- <InlineSvg name="home" class="h-10"></InlineSvg>-->
|
||||
<!-- </a>-->
|
||||
<!-- <router-link to="/" class="flex items-center text-sm text-blue-600 font-bold">主页</router-link>-->
|
||||
<!-- <a class="flex items-center text-sm text-blue-600 font-bold" href="/">主页6</a>-->
|
||||
|
||||
<div class="flex pt-0.5 sm:pt-1 ml-4 text-sm items-center sm:hidden">
|
||||
<router-link :to="route.fullPath">{{ route.meta.title }}</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<ul class="hidden absolute top-1/2 left-1/2 transform -translate-y-1/2 -translate-x-1/2 md:flex md:mx-auto md:items-center md:w-auto md:space-x-6">
|
||||
<ul class="hidden absolute top-1/2 left-1/2 transform -translate-y-1/2 -translate-x-1/2 sm:flex sm:mx-auto sm:items-center sm:w-auto sm:space-x-6">
|
||||
<li v-for="(item, index) in menuItems" :key="index" class="router-link">
|
||||
<router-link :to="item.href" :class="item?.class">{{item.name}}</router-link>
|
||||
</li>
|
||||
|
@ -27,12 +33,22 @@
|
|||
</div>
|
||||
|
||||
<!-- <a class="md:ml-auto md:mr-3"></a>-->
|
||||
<div class="flex">
|
||||
<el-button :type="wsColor" size="large" class="transition duration-1000">
|
||||
<InlineSvg v-show="wsColor!=='success'" name="link-off" class="mr-2" width="20"></InlineSvg>
|
||||
<InlineSvg v-show="wsColor==='success'" name="link" class="mr-2" width="20"></InlineSvg>
|
||||
{{ wsState }}
|
||||
</el-button>
|
||||
<div class="flex h-full">
|
||||
<div id="page-spec-slot" class="content-center h-full flex flex-row"></div>
|
||||
<div class="lg:hidden">
|
||||
<el-button :type="wsColor" size="small" class="transition duration-1000 min-h-full">
|
||||
<InlineSvg v-show="wsColor!=='success'" name="link-off" class="mr-2" width="20"></InlineSvg>
|
||||
<InlineSvg v-show="wsColor==='success'" name="link" class="mr-2" width="20"></InlineSvg>
|
||||
<div class="text-xs sm:text-sm lg:text-base">{{ wsState }}</div>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="hidden lg:flex">
|
||||
<el-button :type="wsColor" size="large" class="transition duration-1000 min-h-full">
|
||||
<InlineSvg v-show="wsColor!=='success'" name="link-off" class="mr-2" width="20"></InlineSvg>
|
||||
<InlineSvg v-show="wsColor==='success'" name="link" class="mr-2" width="20"></InlineSvg>
|
||||
<div class="text-base">{{ wsState }}</div>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div :class='["custom-drawer", {open: sideMenuOpen}]'>
|
||||
|
@ -42,7 +58,7 @@
|
|||
size=""
|
||||
:direction="'ltr'"
|
||||
>
|
||||
<div id="testborder" :class="[sideMenuItemClass]" class="pr-6 flex text-gray-500" @click="sideMenuOpen=false">
|
||||
<div :class="[sideMenuItemClass]" class="pr-6 flex text-gray-500" @click="sideMenuOpen=false">
|
||||
<InlineSvg name="cross" class="h-6"></InlineSvg>
|
||||
<div>
|
||||
<p class="h-6 flex items-center">{{ $t("page.close") }}</p>
|
||||
|
@ -59,9 +75,12 @@
|
|||
|
||||
<template #footer>
|
||||
<div>
|
||||
<p class="text-xs text-center text-gray-400">
|
||||
<span>Copyright <a href="http://github.com/kerms">kerms</a> 2024</span>
|
||||
</p>
|
||||
<el-button @click="toggle">
|
||||
<InlineSvg v-if="!isFullscreen" name="open-in-full" width="16px" fill="#000000"></InlineSvg>
|
||||
<p v-if="!isFullscreen">全屏</p>
|
||||
<InlineSvg v-if="isFullscreen" name="close-fullscreen" width="16px" fill="#000000"></InlineSvg>
|
||||
<p v-if="isFullscreen">缩小</p>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
@ -90,8 +109,12 @@ import {computed, ref} from "vue";
|
|||
import {useWsStore} from "@/stores/websocket";
|
||||
import {translate} from "@/locales";
|
||||
import {ControlEvent} from "@/api";
|
||||
import {useRoute} from "vue-router";
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
|
||||
const wsStore = useWsStore();
|
||||
const {isFullscreen, toggle} = useFullscreen();
|
||||
const route = useRoute();
|
||||
|
||||
const sideMenuItemClass = "block p-4 text-sm font-semibold hover:bg-blue-50 hover:text-blue-600 rounded"
|
||||
const sideMenuOpen = ref(false);
|
||||
|
@ -136,11 +159,7 @@ const menuItems: Item[] = ([
|
|||
}, {
|
||||
name: translate("page.feedback"),
|
||||
href: "/feedback",
|
||||
},/* {
|
||||
name: translate("page.uart"),
|
||||
href: "/uart",
|
||||
class: "todo-menu-item",
|
||||
},*/
|
||||
},
|
||||
]);
|
||||
|
||||
</script>
|
||||
|
|
205
vite.config.ts
205
vite.config.ts
|
@ -2,115 +2,118 @@ import { fileURLToPath, URL } from 'node:url'
|
|||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { defineConfig } from 'vite'
|
||||
import {ConfigEnv, defineConfig, loadEnv} from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import svgLoader from "vite-svg-loader";
|
||||
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
|
||||
import { viteSingleFile } from 'vite-plugin-singlefile'
|
||||
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
svgLoader(),
|
||||
cssInjectedByJsPlugin(),
|
||||
viteSingleFile(),
|
||||
],
|
||||
define: {
|
||||
export default ({mode}: ConfigEnv) => {
|
||||
process.env = {...process.env, ...loadEnv(mode, process.cwd())};
|
||||
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
|
||||
cacheDir: "/tmp/zhuang/cache",
|
||||
worker: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
inlineDynamicImports: true,
|
||||
minifyInternalExports: true,
|
||||
// entryFileNames: (chunkInfo) => {
|
||||
// // console.log(chunkInfo)
|
||||
// if (chunkInfo.name.includes("shared")) {
|
||||
// console.log(chunkInfo.name);
|
||||
// }
|
||||
// return "worker.js";
|
||||
// },
|
||||
entryFileNames: "[name].js",
|
||||
return defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
svgLoader(),
|
||||
cssInjectedByJsPlugin(),
|
||||
viteSingleFile(),
|
||||
],
|
||||
define: {},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
// target: 'es2015',
|
||||
outDir: '/tmp/zhuang/dap-web-dist/',
|
||||
emptyOutDir: true,
|
||||
cssMinify: 'lightningcss',
|
||||
},
|
||||
|
||||
rollupOptions: {
|
||||
output: {
|
||||
inlineDynamicImports: true,
|
||||
minifyInternalExports: true,
|
||||
assetFileNames: (assetInfo) => {
|
||||
if (!assetInfo || !assetInfo.name) {
|
||||
return 'default-filename.ext';
|
||||
}
|
||||
const info = assetInfo.name.split(".");
|
||||
let extType = info[info.length - 1];
|
||||
if (/png|jpe?g|svg|gif|tiff|bmp|ico/i.test(extType)) {
|
||||
extType = "img";
|
||||
} else if (/woff|woff2/.test(extType)) {
|
||||
extType = "css";
|
||||
} else if (/css/.test(extType)) {
|
||||
extType = "css";
|
||||
return "style.css"
|
||||
}
|
||||
console.log(assetInfo)
|
||||
return `[name]-[hash][extname]`;
|
||||
},
|
||||
// chunkFileNames: "[name]-[hash].js",
|
||||
// chunkFileNames: "[name][hash].js",
|
||||
chunkFileNames(chunkInfo) {
|
||||
// Check if this chunk is your SharedWorker
|
||||
// console.log(chunkInfo)
|
||||
cacheDir: process.env.VITE_CACHE_DIR || undefined,
|
||||
worker: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
inlineDynamicImports: true,
|
||||
minifyInternalExports: true,
|
||||
// entryFileNames: (chunkInfo) => {
|
||||
// // console.log(chunkInfo)
|
||||
// if (chunkInfo.name.includes("shared")) {
|
||||
// console.log(chunkInfo.name);
|
||||
// }
|
||||
// return "worker.js";
|
||||
// },
|
||||
entryFileNames: "[name].js",
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
// target: 'es2015',
|
||||
outDir: process.env.VITE_OUTPUT_DIR || undefined,
|
||||
emptyOutDir: true,
|
||||
cssMinify: 'lightningcss',
|
||||
|
||||
// For other chunks, use the default naming scheme
|
||||
return 'assets/[name]-[hash].js';
|
||||
},
|
||||
// entryFileNames: "[name]-[hash].js",
|
||||
entryFileNames: (chunkInfo) => {
|
||||
// console.log(chunkInfo)
|
||||
if (chunkInfo.name.includes("shared")) {
|
||||
console.log(chunkInfo.name);
|
||||
}
|
||||
return "script.js";
|
||||
},
|
||||
rollupOptions: {
|
||||
output: {
|
||||
inlineDynamicImports: true,
|
||||
minifyInternalExports: true,
|
||||
assetFileNames: (assetInfo) => {
|
||||
if (!assetInfo || !assetInfo.name) {
|
||||
return 'default-filename.ext';
|
||||
}
|
||||
const info = assetInfo.name.split(".");
|
||||
let extType = info[info.length - 1];
|
||||
if (/png|jpe?g|svg|gif|tiff|bmp|ico/i.test(extType)) {
|
||||
extType = "img";
|
||||
} else if (/woff|woff2/.test(extType)) {
|
||||
extType = "css";
|
||||
} else if (/css/.test(extType)) {
|
||||
extType = "css";
|
||||
return "style.css"
|
||||
}
|
||||
console.log(assetInfo)
|
||||
return `[name]-[hash][extname]`;
|
||||
},
|
||||
// chunkFileNames: "[name]-[hash].js",
|
||||
// chunkFileNames: "[name][hash].js",
|
||||
chunkFileNames(chunkInfo) {
|
||||
// Check if this chunk is your SharedWorker
|
||||
// console.log(chunkInfo)
|
||||
|
||||
sourcemapFileNames: "map-[name].js",
|
||||
// sanitizeFileName: "anit-[name].js",
|
||||
// entryFileNames: (chunkInfo) => {
|
||||
// console.log(chunkInfo)
|
||||
// return `${chunkInfo.name}.js`
|
||||
// },
|
||||
// manualChunks(id) {
|
||||
// /* if (id.match('.*!/src/.*shared[a-zA-Z0-9-_]*[.](ts|js).*')) {
|
||||
// // Prevent bundling node_modules into common chunks
|
||||
// return 'bundle-shared';
|
||||
// }
|
||||
// else */{
|
||||
// // Prevent bundling node_modules into common chunks
|
||||
// return 'script'
|
||||
// }
|
||||
// },
|
||||
manualChunks: undefined,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
// For other chunks, use the default naming scheme
|
||||
return 'assets/[name]-[hash].js';
|
||||
},
|
||||
// entryFileNames: "[name]-[hash].js",
|
||||
entryFileNames: (chunkInfo) => {
|
||||
// console.log(chunkInfo)
|
||||
if (chunkInfo.name.includes("shared")) {
|
||||
console.log(chunkInfo.name);
|
||||
}
|
||||
return "script.js";
|
||||
},
|
||||
|
||||
sourcemapFileNames: "map-[name].js",
|
||||
// sanitizeFileName: "anit-[name].js",
|
||||
// entryFileNames: (chunkInfo) => {
|
||||
// console.log(chunkInfo)
|
||||
// return `${chunkInfo.name}.js`
|
||||
// },
|
||||
// manualChunks(id) {
|
||||
// /* if (id.match('.*!/src/.*shared[a-zA-Z0-9-_]*[.](ts|js).*')) {
|
||||
// // Prevent bundling node_modules into common chunks
|
||||
// return 'bundle-shared';
|
||||
// }
|
||||
// else */{
|
||||
// // Prevent bundling node_modules into common chunks
|
||||
// return 'script'
|
||||
// }
|
||||
// },
|
||||
manualChunks: undefined,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue