├── .env ├── .env.development ├── .env.production ├── .env.server ├── .gitignore ├── .gitmodules ├── .npmrc ├── CHANGELOG.md ├── Dockerfile ├── README.md ├── build.sh ├── configs ├── getModulesAlias.ts ├── plugin │ ├── copyImagesPlugin.ts │ ├── index.ts │ ├── modules.ts │ └── optimize.ts └── theme │ └── index.ts ├── docker-entrypoint.sh ├── gitmodules.sh ├── index.html ├── nginx.conf ├── package.json ├── playwright.config.ts ├── pnpm-workspace.yaml ├── public ├── favicon.ico ├── fonts │ └── AlibabaPuHuiTi-2-55-Regular.ttf ├── icons │ ├── icon-128x128.png │ ├── icon-192x192.png │ ├── icon-512x512.png │ └── iconfont.js ├── images │ ├── DataCollect │ │ ├── channel-modbus.png │ │ ├── channel-opcua.png │ │ ├── dashboard │ │ │ ├── channel.png │ │ │ ├── collector.png │ │ │ └── point.png │ │ ├── device-modbus.png │ │ ├── device-opcua.png │ │ ├── gateway.png │ │ ├── s7.png │ │ ├── tree-channel.png │ │ └── tree-device.png │ ├── home │ │ └── home-view │ │ │ ├── comprehensive-active.png │ │ │ ├── comprehensive.png │ │ │ ├── device-active.png │ │ │ ├── device.png │ │ │ ├── ops-active.png │ │ │ └── ops.png │ ├── init-home │ │ ├── background.png │ │ ├── data-disabled.png │ │ ├── data-enabled.png │ │ ├── mark.png │ │ ├── menu.png │ │ ├── role1.png │ │ ├── role2.png │ │ └── role3.png │ ├── login.png │ ├── login │ │ ├── login.png │ │ ├── logo.png │ │ └── view-logo.png │ ├── notice-rule │ │ ├── dingtalk.png │ │ ├── email.png │ │ ├── inside-mail.png │ │ ├── sms.png │ │ ├── voice.png │ │ └── wechat.png │ ├── notice │ │ ├── dingTalk-rebot.png │ │ ├── dingtalk.png │ │ ├── email.png │ │ ├── sms.png │ │ ├── voice.png │ │ ├── webhook.png │ │ └── weixin-corp.png │ ├── rectangle.png │ └── relogin.png ├── logo.png └── protocol │ ├── BACNetIp │ ├── ScanPointSelect.vue │ ├── channel.vue │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ ├── pointActions.vue │ ├── scan.vue │ └── scanTree.vue │ ├── CJ188 │ ├── channel.vue │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ ├── DL645 │ ├── channel.vue │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ ├── EtherNetIp │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ ├── MELSEC_TCP │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ ├── MODBUS_RTU │ ├── channel.vue │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ ├── MODBUS_TCP │ ├── channel.vue │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ ├── OMRON_FINS │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ ├── OPC_DA │ ├── channel.vue │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ └── pointActions.vue │ ├── OPC_UA │ ├── channel.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ ├── pointActions.vue │ ├── scan.vue │ └── scanTree.vue │ ├── iec104 │ ├── collector.vue │ ├── lang │ │ ├── en.json │ │ └── zh.json │ ├── point.vue │ └── pointActions.vue │ └── snap7 │ ├── channel.vue │ ├── collector.vue │ ├── lang │ ├── en.json │ └── zh.json │ ├── point.vue │ └── pointActions.vue ├── src ├── App.vue ├── api │ ├── account │ │ ├── center.ts │ │ ├── notificationRecord.ts │ │ └── notificationSubscription.ts │ ├── application.ts │ ├── auth.ts │ ├── comm.ts │ ├── initHome.ts │ ├── login.ts │ └── system │ │ ├── apply.ts │ │ ├── basis.ts │ │ ├── bind.ts │ │ ├── calendar.ts │ │ ├── department.ts │ │ ├── menu.ts │ │ ├── positions.ts │ │ └── user.ts ├── assets │ ├── apply │ │ ├── internal-standalone.png │ │ ├── third-party.png │ │ └── wechat-miniapp.png │ ├── bindPage │ │ ├── Vector.png │ │ ├── bindPage.png │ │ ├── dingtalk.png │ │ ├── jetlinksLogo.png │ │ └── wechat-webapp.png │ ├── token-error-icon.png │ └── token-error.jpg ├── auto-imports.d.ts ├── components │ ├── AMapComponent │ │ ├── AMap.vue │ │ ├── DistrictSearch.vue │ │ ├── GeoJson.vue │ │ ├── PathSimplifier.vue │ │ ├── index.ts │ │ ├── types.d.ts │ │ ├── useMap.ts │ │ └── utils.ts │ ├── BatchDropdown │ │ ├── index.vue │ │ └── types.d.ts │ ├── CardBox │ │ ├── images.vue │ │ └── index.vue │ ├── CardSelect │ │ ├── CardSelect.vue │ │ ├── RadioButton.vue │ │ └── index.ts │ ├── CheckButton │ │ ├── CheckButton.vue │ │ └── index.ts │ ├── ConfirmModal │ │ └── index.vue │ ├── Dashboard │ │ ├── CardItem.vue │ │ ├── GaugeCard.vue │ │ ├── NetWork.vue │ │ ├── TimeLineEchart.vue │ │ ├── TrendChart.vue │ │ ├── components │ │ │ ├── Charts.vue │ │ │ ├── EchartsTime.vue │ │ │ ├── Guide.vue │ │ │ ├── ServerList.vue │ │ │ ├── TimeSelect.vue │ │ │ ├── index.ts │ │ │ └── tools.ts │ │ └── index.ts │ ├── FormItem │ │ ├── OrgList.vue │ │ ├── Position.vue │ │ ├── RoleList.vue │ │ └── index.ts │ ├── FullCalendar │ │ └── index.vue │ ├── HomeView │ │ └── index.vue │ ├── Image │ │ └── index.vue │ ├── MCarousel │ │ └── index.vue │ ├── MonacoEditor │ │ └── monacoEditor.vue │ ├── Player │ │ ├── ScreenPlayer.vue │ │ ├── index.less │ │ ├── index.vue │ │ ├── mediaTool.less │ │ ├── mediaTool.vue │ │ └── utils.ts │ ├── Search │ │ ├── Search.vue │ │ ├── index.ts │ │ ├── search.md │ │ ├── types.d.ts │ │ └── util.ts │ ├── SelectAMap │ │ └── index.vue │ ├── TitleComponent │ │ └── index.vue │ ├── Upload │ │ ├── Cropper.vue │ │ ├── Image │ │ │ ├── CropperModal.tsx │ │ │ ├── ImageUpload.vue │ │ │ └── cropper.md │ │ └── index.vue │ ├── antd-install.ts │ └── index.ts ├── directive │ ├── formatTime.ts │ └── index.ts ├── hooks │ ├── index.ts │ └── useWebSocket.ts ├── layout │ ├── BasicLayoutPage.vue │ ├── BlankLayoutPage.vue │ ├── FullPage.vue │ ├── Iframe.vue │ ├── components │ │ ├── Language.vue │ │ ├── Notice.vue │ │ ├── NoticeInfo.vue │ │ ├── NoticeItem.vue │ │ ├── NoticeTab.vue │ │ ├── Resource.vue │ │ ├── User.vue │ │ ├── index.ts │ │ └── nodata.svg │ └── index.ts ├── locales │ ├── index.ts │ ├── lang │ │ ├── en.json │ │ └── zh.json │ └── loader.ts ├── main.ts ├── package.ts ├── router │ ├── basic.ts │ ├── extraMenu.ts │ ├── globModules.ts │ ├── index.ts │ └── menu.ts ├── store │ ├── application.ts │ ├── auth.ts │ ├── department.ts │ ├── index.ts │ ├── menu.ts │ ├── system.ts │ └── user.ts ├── style.css ├── style │ ├── comm.less │ ├── font.less │ ├── global.less │ ├── layout.less │ ├── scrollbar.less │ └── variable.less ├── utils │ ├── comm.ts │ ├── consts.ts │ ├── context.ts │ ├── document.ts │ ├── encodeQuery.ts │ ├── index.ts │ ├── menu.ts │ ├── modules-loader.ts │ ├── modules.ts │ ├── regular.ts │ ├── utils.ts │ └── validate.ts ├── views │ ├── Error │ │ └── 404.vue │ ├── TokenJump │ │ └── index.vue │ ├── account │ │ └── center │ │ │ ├── bind │ │ │ └── index.vue │ │ │ ├── components │ │ │ ├── BindThirdAccount │ │ │ │ └── index.vue │ │ │ ├── Detail │ │ │ │ └── index.vue │ │ │ ├── EditInfo │ │ │ │ └── index.vue │ │ │ ├── EditPassword │ │ │ │ └── index.vue │ │ │ ├── HomeView │ │ │ │ └── index.vue │ │ │ ├── RoleShow │ │ │ │ └── index.vue │ │ │ ├── StationMessage │ │ │ │ ├── components │ │ │ │ │ └── NotificationRecord │ │ │ │ │ │ ├── components │ │ │ │ │ │ └── ViewDialog.vue │ │ │ │ │ │ └── index.vue │ │ │ │ └── index.vue │ │ │ ├── Subscribe │ │ │ │ ├── components │ │ │ │ │ ├── Bind.vue │ │ │ │ │ ├── Card.vue │ │ │ │ │ ├── Detail.vue │ │ │ │ │ ├── Item.vue │ │ │ │ │ ├── Unsubscribe.vue │ │ │ │ │ └── Wechat.vue │ │ │ │ └── index.vue │ │ │ ├── UploadAvatar │ │ │ │ └── index.vue │ │ │ └── data.ts │ │ │ ├── data.ts │ │ │ └── index.vue │ ├── demo │ │ └── index.vue │ ├── init-home │ │ ├── Basic │ │ │ ├── Form.vue │ │ │ ├── components │ │ │ │ └── upload │ │ │ │ │ ├── typing.ts │ │ │ │ │ └── upload.vue │ │ │ └── index.vue │ │ ├── Menu │ │ │ └── index.vue │ │ ├── Role │ │ │ └── index.vue │ │ ├── data │ │ │ ├── RoleData.ts │ │ │ ├── baseMenu.ts │ │ │ ├── index.ts │ │ │ └── interface.ts │ │ ├── index.vue │ │ └── initData │ │ │ └── index.vue │ ├── login │ │ ├── index.vue │ │ ├── remember.vue │ │ ├── right.vue │ │ └── util.ts │ ├── mirco │ │ ├── SubAppRedirect │ │ │ ├── base.vue │ │ │ └── index.vue │ │ └── iframe │ │ │ └── index.vue │ ├── oauth │ │ ├── WeChat.vue │ │ └── index.vue │ ├── relogin │ │ └── index.vue │ └── share │ │ └── authorize │ │ └── index.vue └── vite-env.d.ts ├── tests └── e2e │ └── example.spec.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.env: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/.env -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # public path 2 | VITE_PUBLIC_PATH=/ 3 | 4 | VITE_APP_BASE_API=/api 5 | 6 | VITE_PORT=9100 7 | 8 | VITE_TOKEN_KEY=X-Access-Token 9 | 10 | VITE_TOKEN_KEY_URL=:X_Access_Token 11 | 12 | VITE_GLOB_APP_SHORT_NAME=JetLinks_admin 13 | 14 | # 是否在开发环境开启 https 和 http2(开启后将大幅优化首次启动时加载速度) 15 | VITE_USE_HTTPS=false 16 | 17 | VITE_MICRO_APP=false 18 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | # public path 2 | VITE_PUBLIC_PATH=./ 3 | 4 | VITE_APP_BASE_API=/api 5 | 6 | VITE_TOKEN_KEY=X-Access-Token 7 | 8 | VITE_TOKEN_KEY_URL=:X_Access_Token 9 | 10 | VITE_MICRO_APP=false 11 | -------------------------------------------------------------------------------- /.env.server: -------------------------------------------------------------------------------- 1 | # public path 2 | VITE_PUBLIC_PATH=./ 3 | 4 | VITE_APP_BASE_API= 5 | 6 | VITE_TOKEN_KEY=X-Access-Token 7 | 8 | VITE_TOKEN_KEY_URL=:X_Access_Token 9 | 10 | VITE_OUT_DIR=dist 11 | 12 | VITE_MICRO_APP=false 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | components.d.ts 15 | apps 16 | 17 | # Editor directories and files 18 | .vscode 19 | .vscode/* 20 | !.vscode/extensions.json 21 | .idea 22 | .DS_Store 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | .history 29 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/modules/rule-engine-manager-ui"] 2 | path = src/modules/rule-engine-manager-ui 3 | url = git@github.com:jetlinks-v2/rule-engine-manager-ui.git 4 | [submodule "src/modules/notify-manager-ui"] 5 | path = src/modules/notify-manager-ui 6 | url = git@github.com:jetlinks-v2/notify-manager-ui.git 7 | [submodule "src/modules/device-manager-ui"] 8 | path = src/modules/device-manager-ui 9 | url = git@github.com:jetlinks-v2/device-manager-ui.git 10 | [submodule "src/modules/authentication-manager-ui"] 11 | path = src/modules/authentication-manager-ui 12 | url = git@github.com:jetlinks-v2/authentication-manager-ui.git 13 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers=true 2 | ignore-workspace-root-check=true 3 | registry=http://registry.npmjs.org 4 | #registry=https://registry.npmmirror.com/ 5 | 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | 4 | ## 2.10.0 5 | * 拆分 [系统管理](https://github.com/jetlinks-v2/authentication-manager-ui) 6 | * 添加 [组件ui](https://github.com/jetlinks-v2/jetlinks-components-ui) 7 | 8 | 9 | ## 2.3.0 10 | 11 | * 对业务功能进行模块化拆分,拆分为以下几个子模块 12 | * [设备管理](https://github.com/jetlinks-v2/device-manager-ui) 13 | * [数据采集](https://github.com/jetlinks-v2/data-collector-ui) 14 | * [规则引擎](https://github.com/jetlinks-v2/rule-engine-manager-ui) 15 | * [通知管理](https://github.com/jetlinks-v2/notify-manager-ui) 16 | * [视频中心](https://github.com/jetlinks-v2/jetlinks-media-ui) 17 | * [阿里云物联网平台接入](https://github.com/jetlinks-v2/jetlinks-aliyun-bridge-gateway-ui) 18 | * [数据源](https://github.com/jetlinks-v2/datasource-manager-ui) 19 | * [物联卡管理](https://github.com/jetlinks-v2/network-card-manager-ui) 20 | * [百度物联网平台接入](https://github.com/jetlinks-v2/jetlinks-dueros-ui) 21 | * 图片存放位置修改为assets下,并对之前public下的图片进行兼容 22 | * 修复若干bug 23 | * 优化部分代码逻辑 24 | * 添加国际化 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:1.20.2 2 | ADD nginx.conf /etc/nginx/conf.d/default.conf 3 | ADD docker-entrypoint.sh /docker-entrypoint.sh 4 | COPY dist /usr/share/nginx/html 5 | CMD ["sh","/docker-entrypoint.sh"] 6 | #ADD oauth2 /usr/share/nginx/html/oauth2 7 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.10.0 . 3 | docker push registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.10.0 4 | -------------------------------------------------------------------------------- /configs/getModulesAlias.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path' 2 | import * as fs from 'fs' 3 | 4 | export const getAliasNameMap = () => { 5 | const modulesPaths = path.join(__dirname, '../src', 'modules') 6 | 7 | const aliasMap: Record = {} 8 | 9 | const files = fs.readdirSync(modulesPaths) 10 | 11 | if (files && files.length) { 12 | files.forEach(file => { 13 | const projectDir = path.join(modulesPaths, file) 14 | 15 | const projectDirStats = fs.statSync(projectDir) 16 | 17 | if (projectDirStats?.isDirectory()) { 18 | try { 19 | const configPath = path.join(projectDir, 'config.json') 20 | 21 | if (configPath) { 22 | const content = fs.readFileSync(configPath, 'utf-8') 23 | const object = JSON.parse(content) 24 | 25 | if (object.aliasName) { 26 | aliasMap[`${object.aliasName}`] = path.resolve(projectDir) 27 | } 28 | console.log(JSON.parse(content)) 29 | } 30 | } catch (e) { 31 | console.warn(e) 32 | } 33 | } 34 | }) 35 | } 36 | 37 | return aliasMap 38 | } 39 | -------------------------------------------------------------------------------- /configs/plugin/index.ts: -------------------------------------------------------------------------------- 1 | export * from './optimize' 2 | export * from './modules' 3 | export * from './copyImagesPlugin' 4 | -------------------------------------------------------------------------------- /configs/plugin/modules.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import * as path from 'path' 3 | 4 | const rootPath = path.resolve(__dirname, '../../') 5 | const modulesBasePath = 'src/modules' 6 | 7 | function registerModulesAlias() { 8 | const modulesAlias = {} 9 | const pattern = path.resolve(rootPath, modulesBasePath) 10 | const folders = fs.readdirSync(pattern) 11 | folders?.map((name) => { 12 | const result = fs.readFileSync(path.resolve(rootPath, modulesBasePath, `${name}/config.json`), 'utf-8') 13 | const content = JSON.parse(result) 14 | if (content.aliasName) { 15 | modulesAlias[content.aliasName] = path.resolve(modulesBasePath, name) 16 | } 17 | }) 18 | return modulesAlias 19 | } 20 | 21 | export { registerModulesAlias } 22 | -------------------------------------------------------------------------------- /configs/plugin/optimize.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | const rootPath = path.resolve(__dirname, '../../'); 5 | 6 | function optimizeComponents(moduleName: string): string[] { 7 | const moduleESPath = `${moduleName}/es`; 8 | const nodeModulePath = `./node_modules/${moduleESPath}`; 9 | const includes: string[] = [moduleESPath]; 10 | 11 | const folders = fs.readdirSync(path.resolve(rootPath, nodeModulePath)); 12 | 13 | folders.map((name) => { 14 | 15 | const folderName = path.resolve(rootPath, nodeModulePath, name); 16 | let stat = fs.lstatSync(folderName); 17 | if (stat.isDirectory()) { 18 | let styleFolder = path.resolve(folderName, "style"); 19 | if (fs.existsSync(styleFolder)) { 20 | let _stat = fs.lstatSync(styleFolder); 21 | if (_stat.isDirectory()) { 22 | includes.push(`${moduleESPath}/${name}/style`); 23 | } 24 | } 25 | } 26 | }); 27 | 28 | return includes; 29 | } 30 | 31 | export function optimizeDeps() { 32 | return { 33 | name: "optimizeDeps", 34 | configResolved: async (config) => { 35 | const components = [ 36 | // ...optimizeComponents("ant-design-vue"), 37 | ...optimizeComponents("@jetlinks-web/components"), 38 | ]; 39 | let concat = config.optimizeDeps.include.concat(components); 40 | config.optimizeDeps.include = Array.from(new Set(concat)); 41 | }, 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /configs/theme/index.ts: -------------------------------------------------------------------------------- 1 | // 主题色变量参考 https://3x.antdv.com/docs/vue/customize-theme-cn 2 | export default { 3 | primaryColor: "#1677FF", 4 | linkColor: "#1677FF" 5 | } 6 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | API_BASE_PATH=$API_BASE_PATH; 4 | SERVER_NAME=$SERVER_NAME; 5 | 6 | #NAMESERVERS=$(cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' ') 7 | NAMESERVERS=$(grep "^nameserver" /etc/resolv.conf | awk '{print $2}' | tr '\n' ' ') 8 | if [ -z "$API_BASE_PATH" ]; then 9 | API_BASE_PATH="http://jetlinks:8844/"; 10 | fi 11 | 12 | apiUrl="proxy_pass $API_BASE_PATH\$1;" 13 | resolver="resolver $NAMESERVERS ipv6=off;" 14 | 15 | sed -i '11c '"$resolver"'' /etc/nginx/conf.d/default.conf 16 | sed -i "s%{API_BASE_PATH}%$API_BASE_PATH%g" /etc/nginx/conf.d/default.conf 17 | 18 | if [ -z "$SERVER_NAME" ]; then 19 | serverName="server_name localhost;" 20 | sed -i '4c '"$serverName"'' /etc/nginx/conf.d/default.conf 21 | sed -i "s%{SERVER_NAME}%\"0\"%g" /etc/nginx/conf.d/default.conf 22 | else 23 | serverName="server_name $SERVER_NAME;" 24 | sed -i '4c '"$serverName"'' /etc/nginx/conf.d/default.conf 25 | sed -i "s%{SERVER_NAME}%$SERVER_NAME%g" /etc/nginx/conf.d/default.conf 26 | fi 27 | 28 | #cat /etc/nginx/conf.d/default.conf 29 | 30 | nginx -g "daemon off;" 31 | 32 | -------------------------------------------------------------------------------- /gitmodules.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 初始化子模块 4 | git submodule init 5 | git submodule update 6 | 7 | # 获取主仓库当前分支 8 | main_branch=$(git symbolic-ref --short HEAD) 9 | 10 | # 如果是dev,就使用master,否则用当前分支 11 | if [[ "$main_branch" = "dev" || "$main_branch" = "master" ]]; then 12 | submodule_branch="master" 13 | else 14 | submodule_branch="$main_branch" 15 | fi 16 | 17 | # 切换子模块到目标分支 18 | git submodule foreach "git checkout $submodule_branch || git checkout -b $submodule_branch origin/$submodule_branch" 19 | 20 | # 拉取子模块最新代码 21 | git submodule foreach "git pull origin $submodule_branch" 22 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig} from '@playwright/test'; 2 | 3 | export default defineConfig({ 4 | testDir: './tests/e2e', 5 | use: { 6 | baseURL: 'http://localhost:9000', 7 | headless: true, 8 | screenshot: 'only-on-failure', 9 | trace: 'on-first-retry', 10 | browserName: 'chromium', 11 | }, 12 | 13 | }) 14 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "src/modules/*" 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/favicon.ico -------------------------------------------------------------------------------- /public/fonts/AlibabaPuHuiTi-2-55-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/fonts/AlibabaPuHuiTi-2-55-Regular.ttf -------------------------------------------------------------------------------- /public/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/icons/icon-128x128.png -------------------------------------------------------------------------------- /public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /public/images/DataCollect/channel-modbus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/channel-modbus.png -------------------------------------------------------------------------------- /public/images/DataCollect/channel-opcua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/channel-opcua.png -------------------------------------------------------------------------------- /public/images/DataCollect/dashboard/channel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/dashboard/channel.png -------------------------------------------------------------------------------- /public/images/DataCollect/dashboard/collector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/dashboard/collector.png -------------------------------------------------------------------------------- /public/images/DataCollect/dashboard/point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/dashboard/point.png -------------------------------------------------------------------------------- /public/images/DataCollect/device-modbus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/device-modbus.png -------------------------------------------------------------------------------- /public/images/DataCollect/device-opcua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/device-opcua.png -------------------------------------------------------------------------------- /public/images/DataCollect/gateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/gateway.png -------------------------------------------------------------------------------- /public/images/DataCollect/s7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/s7.png -------------------------------------------------------------------------------- /public/images/DataCollect/tree-channel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/tree-channel.png -------------------------------------------------------------------------------- /public/images/DataCollect/tree-device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/DataCollect/tree-device.png -------------------------------------------------------------------------------- /public/images/home/home-view/comprehensive-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/home/home-view/comprehensive-active.png -------------------------------------------------------------------------------- /public/images/home/home-view/comprehensive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/home/home-view/comprehensive.png -------------------------------------------------------------------------------- /public/images/home/home-view/device-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/home/home-view/device-active.png -------------------------------------------------------------------------------- /public/images/home/home-view/device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/home/home-view/device.png -------------------------------------------------------------------------------- /public/images/home/home-view/ops-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/home/home-view/ops-active.png -------------------------------------------------------------------------------- /public/images/home/home-view/ops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/home/home-view/ops.png -------------------------------------------------------------------------------- /public/images/init-home/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/background.png -------------------------------------------------------------------------------- /public/images/init-home/data-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/data-disabled.png -------------------------------------------------------------------------------- /public/images/init-home/data-enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/data-enabled.png -------------------------------------------------------------------------------- /public/images/init-home/mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/mark.png -------------------------------------------------------------------------------- /public/images/init-home/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/menu.png -------------------------------------------------------------------------------- /public/images/init-home/role1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/role1.png -------------------------------------------------------------------------------- /public/images/init-home/role2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/role2.png -------------------------------------------------------------------------------- /public/images/init-home/role3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/init-home/role3.png -------------------------------------------------------------------------------- /public/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/login.png -------------------------------------------------------------------------------- /public/images/login/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/login/login.png -------------------------------------------------------------------------------- /public/images/login/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/login/logo.png -------------------------------------------------------------------------------- /public/images/login/view-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/login/view-logo.png -------------------------------------------------------------------------------- /public/images/notice-rule/dingtalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice-rule/dingtalk.png -------------------------------------------------------------------------------- /public/images/notice-rule/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice-rule/email.png -------------------------------------------------------------------------------- /public/images/notice-rule/inside-mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice-rule/inside-mail.png -------------------------------------------------------------------------------- /public/images/notice-rule/sms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice-rule/sms.png -------------------------------------------------------------------------------- /public/images/notice-rule/voice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice-rule/voice.png -------------------------------------------------------------------------------- /public/images/notice-rule/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice-rule/wechat.png -------------------------------------------------------------------------------- /public/images/notice/dingTalk-rebot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice/dingTalk-rebot.png -------------------------------------------------------------------------------- /public/images/notice/dingtalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice/dingtalk.png -------------------------------------------------------------------------------- /public/images/notice/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice/email.png -------------------------------------------------------------------------------- /public/images/notice/sms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice/sms.png -------------------------------------------------------------------------------- /public/images/notice/voice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice/voice.png -------------------------------------------------------------------------------- /public/images/notice/webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice/webhook.png -------------------------------------------------------------------------------- /public/images/notice/weixin-corp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/notice/weixin-corp.png -------------------------------------------------------------------------------- /public/images/rectangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/rectangle.png -------------------------------------------------------------------------------- /public/images/relogin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/images/relogin.png -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/public/logo.png -------------------------------------------------------------------------------- /public/protocol/BACNetIp/ScanPointSelect.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 28 | 29 | 32 | -------------------------------------------------------------------------------- /public/protocol/BACNetIp/collector.vue: -------------------------------------------------------------------------------- 1 | 34 | 51 | 52 | -------------------------------------------------------------------------------- /public/protocol/BACNetIp/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "BACNetIp.channel.20250207-1": "BACnet Instance Number", 3 | "BACNetIp.channel.20250207-2": "Please enter the BACnet instance number", 4 | "BACNetIp.channel.20250207-3": "Network Interface Card", 5 | "BACNetIp.channel.20250207-4": "Please enter the network interface card", 6 | "BACNetIp.channel.20250207-5": "Broadcast Port", 7 | "BACNetIp.channel.20250207-6": "Please enter the broadcast port", 8 | "BACNetIp.channel.20250207-7": "Subnet Address", 9 | "BACNetIp.channel.20250207-8": "Please enter the subnet address", 10 | "BACNetIp.channel.20250207-9": "Network Prefix Length", 11 | "BACNetIp.channel.20250207-10": "Please enter the network prefix length", 12 | "BACNetIp.channel.20250207-11": "Please enter the correct subnet address", 13 | "BACNetIp.collector.20250207-1": "Device Instance Number", 14 | "BACNetIp.collector.20250207-2": "Please enter the device instance number", 15 | "BACNetIp.collector.20250207-3": "Address", 16 | "BACNetIp.collector.20250207-4": "Please enter the address", 17 | "BACNetIp.point.20250207-1": "Object ID", 18 | "BACNetIp.point.20250207-2": "Object Type", 19 | "BACNetIp.point.20250207-3": "Object Instance Number", 20 | "BACNetIp.point.20250207-4": "Property ID", 21 | "BACNetIp.point.20250207-5": "Value Type", 22 | "BACNetIp.point.20250207-6": "Access Type", 23 | "BACNetIp.point.20250207-7": "Please select the data type", 24 | "BACNetIp.point.20250207-8": "Please select the access type", 25 | "BACNetIp.point.20250207-9": "Read", 26 | "BACNetIp.point.20250207-10": "Write", 27 | "BACNetIp.point.20250207-11": "Subscribe", 28 | "BACNetIp.scan.20250414-1": "Name" 29 | } 30 | -------------------------------------------------------------------------------- /public/protocol/BACNetIp/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "BACNetIp.channel.20250207-1": "BACnet实例号", 3 | "BACNetIp.channel.20250207-2": "请输入BACnet实例号", 4 | "BACNetIp.channel.20250207-3": "网卡", 5 | "BACNetIp.channel.20250207-4": "请输入网卡", 6 | "BACNetIp.channel.20250207-5": "广播端口", 7 | "BACNetIp.channel.20250207-6": "请输入广播端口", 8 | "BACNetIp.channel.20250207-7": "子网地址", 9 | "BACNetIp.channel.20250207-8": "请输入子网地址", 10 | "BACNetIp.channel.20250207-9": "网络前缀长度", 11 | "BACNetIp.channel.20250207-10": "请输入网络前缀长度", 12 | "BACNetIp.channel.20250207-11": "请输入正确的子网地址", 13 | "BACNetIp.collector.20250207-1": "设备实例号", 14 | "BACNetIp.collector.20250207-2": "请输入设备实例号", 15 | "BACNetIp.collector.20250207-3": "地址", 16 | "BACNetIp.collector.20250207-4": "请输入地址", 17 | "BACNetIp.point.20250207-1": "对象ID", 18 | "BACNetIp.point.20250207-2": "对象类型", 19 | "BACNetIp.point.20250207-3": "对象实例号", 20 | "BACNetIp.point.20250207-4": "属性ID", 21 | "BACNetIp.point.20250207-5": "值类型", 22 | "BACNetIp.point.20250207-6": "访问类型", 23 | "BACNetIp.point.20250207-7": "请选择数据类型", 24 | "BACNetIp.point.20250207-8": "请选择访问类型", 25 | "BACNetIp.point.20250207-9": "读", 26 | "BACNetIp.point.20250207-10": "写", 27 | "BACNetIp.point.20250207-11": "订阅", 28 | "BACNetIp.scan.20250414-1": "对象类型", 29 | "BACNetIp.scan.20250414-2": "对象实例号", 30 | "BACNetIp.scan.20250414-3": "名称", 31 | "BACNetIp.scan.20250414-4": "属性ID", 32 | "BACNetIp.scan.20250414-5": "值类型" 33 | } 34 | -------------------------------------------------------------------------------- /public/protocol/BACNetIp/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/BACNetIp/scanTree.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 49 | 50 | 53 | -------------------------------------------------------------------------------- /public/protocol/CJ188/channel.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /public/protocol/CJ188/collector.vue: -------------------------------------------------------------------------------- 1 | 37 | 58 | 59 | -------------------------------------------------------------------------------- /public/protocol/CJ188/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "CJ188.channel.20250207-1": "Serial Port", 3 | "CJ188.channel.20250207-2": "Please select the serial port", 4 | "CJ188.channel.20250207-3": "Preamble Byte Length", 5 | "CJ188.channel.20250207-4": "Please select the preamble byte length", 6 | "CJ188.collector.20250207-1": "Meter Number", 7 | "CJ188.collector.20250207-2": "Please enter or select the meter number", 8 | "CJ188.collector.20250207-3": "Meter Type", 9 | "CJ188.collector.20250207-4": "Please select the meter type", 10 | "CJ188.point.20250207-1": "Function Identifier", 11 | "CJ188.point.20250207-2": "Please select the function identifier", 12 | "CJ188.point.20250207-3": "Data Type" 13 | } 14 | -------------------------------------------------------------------------------- /public/protocol/CJ188/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "CJ188.channel.20250207-1": "串口", 3 | "CJ188.channel.20250207-2": "请选择串口", 4 | "CJ188.channel.20250207-3": "前导字节长度", 5 | "CJ188.channel.20250207-4": "请选择前导字节长度", 6 | "CJ188.collector.20250207-1": "表号", 7 | "CJ188.collector.20250207-2": "请输入或选择表号", 8 | "CJ188.collector.20250207-3": "表类型", 9 | "CJ188.collector.20250207-4": "请选择表类型", 10 | "CJ188.point.20250207-1": "功能标识", 11 | "CJ188.point.20250207-2": "请选择功能标识", 12 | "CJ188.point.20250207-3": "数据类型" 13 | } 14 | -------------------------------------------------------------------------------- /public/protocol/CJ188/point.vue: -------------------------------------------------------------------------------- 1 | 38 | 72 | 73 | -------------------------------------------------------------------------------- /public/protocol/CJ188/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/DL645/channel.vue: -------------------------------------------------------------------------------- 1 | 35 | 97 | 98 | -------------------------------------------------------------------------------- /public/protocol/DL645/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/EtherNetIp/collector.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /public/protocol/EtherNetIp/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "EtherNetIp.collector.20250207-1": "Host Address", 3 | "EtherNetIp.collector.20250207-2": "Please enter the host address", 4 | "EtherNetIp.collector.20250207-3": "Please enter a valid host address", 5 | "EtherNetIp.collector.20250207-4": "Port", 6 | "EtherNetIp.collector.20250207-5": "Please enter the port", 7 | "EtherNetIp.collector.20250207-6": "Connection Pool Size", 8 | "EtherNetIp.collector.20250207-7": "Please enter the connection pool size", 9 | "EtherNetIp.point.20250207-1": "Address", 10 | "EtherNetIp.point.20250207-2": "Please enter a valid address", 11 | "EtherNetIp.point.20250207-3": "Please enter the address", 12 | "EtherNetIp.point.20250207-4": "Please select the access type", 13 | "EtherNetIp.point.20250207-5": "Read", 14 | "EtherNetIp.point.20250207-6": "Write", 15 | "EtherNetIp.point.20250207-7": "Data Type", 16 | "EtherNetIp.point.20250207-8": "Please select the data type", 17 | "EtherNetIp.point.20250207-9": "Access Type" 18 | } 19 | -------------------------------------------------------------------------------- /public/protocol/EtherNetIp/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "EtherNetIp.collector.20250207-1": "主机地址", 3 | "EtherNetIp.collector.20250207-2": "请输入主机地址", 4 | "EtherNetIp.collector.20250207-3": "请输入正确的主机地址", 5 | "EtherNetIp.collector.20250207-4": "端口", 6 | "EtherNetIp.collector.20250207-5": "请输入端口", 7 | "EtherNetIp.collector.20250207-6": "连接池大小", 8 | "EtherNetIp.collector.20250207-7": "请输入连接池大小", 9 | "EtherNetIp.point.20250207-1": "地址", 10 | "EtherNetIp.point.20250207-2": "请输入正确的地址", 11 | "EtherNetIp.point.20250207-3": "请输入地址", 12 | "EtherNetIp.point.20250207-4": "请选择访问类型", 13 | "EtherNetIp.point.20250207-5": "读", 14 | "EtherNetIp.point.20250207-6": "写", 15 | "EtherNetIp.point.20250207-7": "数据类型", 16 | "EtherNetIp.point.20250207-8": "请选择数据类型", 17 | "EtherNetIp.point.20250207-9": "访问类型" 18 | } 19 | -------------------------------------------------------------------------------- /public/protocol/EtherNetIp/point.vue: -------------------------------------------------------------------------------- 1 | 54 | 74 | 75 | -------------------------------------------------------------------------------- /public/protocol/EtherNetIp/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/MELSEC_TCP/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "MELSEC_TCP.collector.20250207-1": "Host IP", 3 | "MELSEC_TCP.collector.20250207-2": "Please enter the endpoint URL", 4 | "MELSEC_TCP.collector.20250207-3": "Port", 5 | "MELSEC_TCP.collector.20250207-4": "Please enter the port", 6 | "MELSEC_TCP.collector.20250207-5": "Frame (Data Communication Message) Type", 7 | "MELSEC_TCP.collector.20250207-6": "Please enter the host IP", 8 | "MELSEC_TCP.collector.20250207-7": "Please enter a valid IP address", 9 | "MELSEC_TCP.collector.20250207-8": "Please select the frame type", 10 | "MELSEC_TCP.point.20250207-1": "Register Type", 11 | "MELSEC_TCP.point.20250207-2": "Please select the register type", 12 | "MELSEC_TCP.point.20250207-3": "Data Type", 13 | "MELSEC_TCP.point.20250207-4": "Please select the data type", 14 | "MELSEC_TCP.point.20250207-5": "Register Quantity (word)", 15 | "MELSEC_TCP.point.20250207-6": "Please enter the register quantity", 16 | "MELSEC_TCP.point.20250207-7": "Register Address", 17 | "MELSEC_TCP.point.20250207-8": "Please enter the register address", 18 | "MELSEC_TCP.point.20250207-9": "Bit Number", 19 | "MELSEC_TCP.point.20250207-10": "Please enter the bit number", 20 | "MELSEC_TCP.point.20250207-11": "Access Type", 21 | "MELSEC_TCP.point.20250207-12": "Read", 22 | "MELSEC_TCP.point.20250207-13": "Write", 23 | "MELSEC_TCP.point.20250207-14": "Please enter the quantity", 24 | "MELSEC_TCP.point.20250207-15": "Please enter the address", 25 | "MELSEC_TCP.point.20250207-16": "Please select the access type" 26 | } 27 | -------------------------------------------------------------------------------- /public/protocol/MELSEC_TCP/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "MELSEC_TCP.collector.20250207-1": "主机IP", 3 | "MELSEC_TCP.collector.20250207-2": "请输入端点url", 4 | "MELSEC_TCP.collector.20250207-3": "端口", 5 | "MELSEC_TCP.collector.20250207-4": "请输入端口", 6 | "MELSEC_TCP.collector.20250207-5": "帧(数据通信报文)类型", 7 | "MELSEC_TCP.collector.20250207-6": "请输入主机IP", 8 | "MELSEC_TCP.collector.20250207-7": "请输入正确的IP地址", 9 | "MELSEC_TCP.collector.20250207-8": "请选择帧类型", 10 | "MELSEC_TCP.point.20250207-1": "寄存器类型", 11 | "MELSEC_TCP.point.20250207-2": "请选择寄存器类型", 12 | "MELSEC_TCP.point.20250207-3": "数据类型", 13 | "MELSEC_TCP.point.20250207-4": "请选择数据类型", 14 | "MELSEC_TCP.point.20250207-5": "寄存器数量(word)", 15 | "MELSEC_TCP.point.20250207-6": "请输入寄存器数量", 16 | "MELSEC_TCP.point.20250207-7": "寄存器地址", 17 | "MELSEC_TCP.point.20250207-8": "请输入寄存器地址", 18 | "MELSEC_TCP.point.20250207-9": "位号", 19 | "MELSEC_TCP.point.20250207-10": "请输入位号", 20 | "MELSEC_TCP.point.20250207-11": "访问类型", 21 | "MELSEC_TCP.point.20250207-12": "读", 22 | "MELSEC_TCP.point.20250207-13": "写", 23 | "MELSEC_TCP.point.20250207-14": "请输入数量", 24 | "MELSEC_TCP.point.20250207-15": "请输入地址", 25 | "MELSEC_TCP.point.20250207-16": "请选择访问类型" 26 | } 27 | -------------------------------------------------------------------------------- /public/protocol/MELSEC_TCP/pointActions.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/protocol/MODBUS_RTU/channel.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 83 | 84 | 87 | -------------------------------------------------------------------------------- /public/protocol/MODBUS_RTU/collector.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 85 | 86 | 88 | -------------------------------------------------------------------------------- /public/protocol/MODBUS_RTU/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "MODBUS_RTU.channel.20250207-1": "串口", 3 | "MODBUS_RTU.channel.20250207-2": "请选择串口", 4 | "MODBUS_RTU.channel.20250207-3": "请求超时", 5 | "MODBUS_RTU.channel.20250207-4": "请输入请求超时时间", 6 | "MODBUS_RTU.channel.20250207-5": "通讯间隔", 7 | "MODBUS_RTU.channel.20250207-6": "请输入通讯间隔", 8 | "MODBUS_RTU.collector.20250207-1": "从机地址", 9 | "MODBUS_RTU.collector.20250207-2": "请输入从机地址", 10 | "MODBUS_RTU.collector.20250207-3": "双字高低位切换", 11 | "MODBUS_RTU.collector.20250207-4": "单字高低位切换", 12 | "MODBUS_RTU.collector.20250207-5": "当前内存布局", 13 | "MODBUS_RTU.collector.20250207-6": "只有4字节数据类型(int32、ieee754 float)", 14 | "MODBUS_RTU.collector.20250207-7": "具有4种内存布局,其它只有ABCD、DCBA两种内存布局(以双字配置为准)", 15 | "MODBUS_RTU.collector.20250207-9": "请输入0-255之间的正整数", 16 | "MODBUS_RTU.collector.20250207-10": "请选择双字高低位切换", 17 | "MODBUS_RTU.collector.20250207-11": "请选择单字高低位切换", 18 | "MODBUS_RTU.point.20250207-1": "功能码", 19 | "MODBUS_RTU.point.20250207-2": "请选择所功能码", 20 | "MODBUS_RTU.point.20250207-3": "地址", 21 | "MODBUS_RTU.point.20250207-4": "请输入地址", 22 | "MODBUS_RTU.point.20250207-5": "请选择访问类型", 23 | "MODBUS_RTU.point.20250207-6": "寄存器数量(word)", 24 | "MODBUS_RTU.point.20250207-7": "请输入寄存器数量", 25 | "MODBUS_RTU.point.20250207-8": "缩放因子", 26 | "MODBUS_RTU.point.20250207-9": "请输入缩放因子", 27 | "MODBUS_RTU.point.20250207-10": "小数保留位数", 28 | "MODBUS_RTU.point.20250207-11": "请输入小数保留位数", 29 | "MODBUS_RTU.point.20250207-12": "非标准协议写入配置", 30 | "MODBUS_RTU.point.20250207-13": "是否写入数据区长度", 31 | "MODBUS_RTU.point.20250207-14": "是", 32 | "MODBUS_RTU.point.20250207-15": "否", 33 | "MODBUS_RTU.point.20250207-16-1": "自定义数据区长度(byte)", 34 | "MODBUS_RTU.point.20250207-16": "请输入自定义数据区长度(byte)", 35 | "MODBUS_RTU.point.20250207-17": "访问类型", 36 | "MODBUS_RTU.point.20250207-20": "请选择功能码", 37 | "MODBUS_RTU.point.20250207-22": "请输入1-255之间的正整数", 38 | "MODBUS_RTU.point.20250207-23": "请选择数据类型", 39 | "MODBUS_RTU.point.20250207-24": "请选择是否写入数据区长度", 40 | "MODBUS_RTU.point.20250207-27": "01线圈寄存器", 41 | "MODBUS_RTU.point.20250207-28": "02离散输入寄存器", 42 | "MODBUS_RTU.point.20250207-29": "03保存寄存器", 43 | "MODBUS_RTU.point.20250207-30": "04输入寄存器", 44 | "MODBUS_RTU.point.20250207-31": "数据类型长度需 <= 寄存器数量 * 2", 45 | "MODBUS_RTU.point.20250207-32": "请输入0-999999之间的正整数", 46 | "MODBUS_RTU.point.20250207-33": "读", 47 | "MODBUS_RTU.point.20250207-34": "写", 48 | "MODBUS_RTU.point.20250207-35": "数据类型" 49 | } 50 | -------------------------------------------------------------------------------- /public/protocol/MODBUS_RTU/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/MODBUS_TCP/collector.vue: -------------------------------------------------------------------------------- 1 | 38 | 77 | 78 | -------------------------------------------------------------------------------- /public/protocol/MODBUS_TCP/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "MODBUS_TCP.channel.20250207-1": "Modbus主机IP", 3 | "MODBUS_TCP.channel.20250207-2": "支持ipv4、ipv6、域名", 4 | "MODBUS_TCP.channel.20250207-3": "请输入Modbus主机IP", 5 | "MODBUS_TCP.channel.20250207-4": "端口", 6 | "MODBUS_TCP.channel.20250207-5": "请输入端口", 7 | "MODBUS_TCP.channel.20250207-6": "请输入正确格式的Modbus主机IP地址", 8 | "MODBUS_TCP.channel.20250207-7": "请输入0-65535之间的正整数", 9 | "MODBUS_TCP.collector.20250207-1": "从机地址", 10 | "MODBUS_TCP.collector.20250207-2": "请输入从机地址", 11 | "MODBUS_TCP.collector.20250207-3": "请输入0-255之间的正整数", 12 | "MODBUS_TCP.collector.20250207-4": "双字高低位切换", 13 | "MODBUS_TCP.collector.20250207-5": "请选择双字高低位切换", 14 | "MODBUS_TCP.collector.20250207-6": "单字高低位切换", 15 | "MODBUS_TCP.collector.20250207-7": "请选择单字高低位切换", 16 | "MODBUS_TCP.collector.20250207-8": "当前内存布局", 17 | "MODBUS_TCP.collector.20250207-9": "只有4字节数据类型(int32、ieee754 float)", 18 | "MODBUS_TCP.collector.20250207-10": "具有4种内存布局,其它只有ABCD、DCBA两种内存布局(以双字配置为准)", 19 | "MODBUS_TCP.point.20250207-1": "功能码", 20 | "MODBUS_TCP.point.20250207-2": "请选择功能码", 21 | "MODBUS_TCP.point.20250207-3": "地址", 22 | "MODBUS_TCP.point.20250207-4": "请输入地址", 23 | "MODBUS_TCP.point.20250207-5": "PLC地址", 24 | "MODBUS_TCP.point.20250207-6": "数据类型", 25 | "MODBUS_TCP.point.20250207-7": "请选择数据类型", 26 | "MODBUS_TCP.point.20250207-8": "寄存器数量(word)", 27 | "MODBUS_TCP.point.20250207-9": "请输入寄存器数量", 28 | "MODBUS_TCP.point.20250207-10": "请输入1-255之间的正整数", 29 | "MODBUS_TCP.point.20250207-11": "缩放因子", 30 | "MODBUS_TCP.point.20250207-12": "请输入缩放因子", 31 | "MODBUS_TCP.point.20250207-13": "小数保留位数", 32 | "MODBUS_TCP.point.20250207-14": "请输入小数保留位数", 33 | "MODBUS_TCP.point.20250207-15": "非标准协议写入配置", 34 | "MODBUS_TCP.point.20250207-16": "请选择是否写入数据区长度", 35 | "MODBUS_TCP.point.20250207-17": "是否写入数据区长度", 36 | "MODBUS_TCP.point.20250207-18": "是", 37 | "MODBUS_TCP.point.20250207-19": "否", 38 | "MODBUS_TCP.point.20250207-20": "请输入自定义数据区长度(byte)", 39 | "MODBUS_TCP.point.20250207-21": "自定义数据区长度(byte)", 40 | "MODBUS_TCP.point.20250207-22": "访问类型", 41 | "MODBUS_TCP.point.20250207-23": "请选择访问类型", 42 | "MODBUS_TCP.point.20250207-24": "01线圈寄存器", 43 | "MODBUS_TCP.point.20250207-25": "02离散输入寄存器", 44 | "MODBUS_TCP.point.20250207-26": "03保存寄存器", 45 | "MODBUS_TCP.point.20250207-27": "04输入寄存器", 46 | "MODBUS_TCP.point.20250207-28": "数据类型长度需 <= 寄存器数量 * 2", 47 | "MODBUS_TCP.point.20250207-29": "请输入0-999999之间的正整数", 48 | "MODBUS_TCP.point.20250207-30": "读", 49 | "MODBUS_TCP.point.20250207-31": "写", 50 | "MODBUS_TCP.point.20250207-32": "基本参数", 51 | "MODBUS_TCP.point.20250207-33": "数据解析", 52 | "MODBUS_TCP.point.20250207-34": "采集传输" 53 | } 54 | -------------------------------------------------------------------------------- /public/protocol/MODBUS_TCP/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/OMRON_FINS/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "OMRON_FINS.collector.20250207-1": "Please enter the IP address", 3 | "OMRON_FINS.collector.20250207-2": "Please select the protocol type", 4 | "OMRON_FINS.collector.20250207-3": "Port", 5 | "OMRON_FINS.collector.20250207-4": "Please enter the port", 6 | "OMRON_FINS.collector.20250207-5": "Node number", 7 | "OMRON_FINS.collector.20250207-6": "Please enter the node number", 8 | "OMRON_FINS.collector.20250207-7": "Device model", 9 | "OMRON_FINS.collector.20250207-8": "Please select the device model", 10 | "OMRON_FINS.collector.20250207-9": "Please enter a valid IP address", 11 | "OMRON_FINS.collector.20250207-10": "Protocol type", 12 | "OMRON_FINS.point.20250207-1": "Register", 13 | "OMRON_FINS.point.20250207-2": "Please select the register", 14 | "OMRON_FINS.point.20250207-3": "Address", 15 | "OMRON_FINS.point.20250207-4": "Please enter the address", 16 | "OMRON_FINS.point.20250207-5": "Number of items", 17 | "OMRON_FINS.point.20250207-6": "Please enter the number of items", 18 | "OMRON_FINS.point.20250207-7": "Data type", 19 | "OMRON_FINS.point.20250207-8": "Please select the data type", 20 | "OMRON_FINS.point.20250207-9": "Offset", 21 | "OMRON_FINS.point.20250207-10": "Please enter the offset", 22 | "OMRON_FINS.point.20250207-11": "Access type", 23 | "OMRON_FINS.point.20250207-12": "Please select the access type", 24 | "OMRON_FINS.point.20250207-13": "Read", 25 | "OMRON_FINS.point.20250207-14": "Write" 26 | } 27 | -------------------------------------------------------------------------------- /public/protocol/OMRON_FINS/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "OMRON_FINS.collector.20250207-1": "请输入IP地址", 3 | "OMRON_FINS.collector.20250207-2": "请选择协议类型", 4 | "OMRON_FINS.collector.20250207-3": "端口", 5 | "OMRON_FINS.collector.20250207-4": "请输入端口", 6 | "OMRON_FINS.collector.20250207-5": "节点号", 7 | "OMRON_FINS.collector.20250207-6": "请输入节点号", 8 | "OMRON_FINS.collector.20250207-7": "设备型号", 9 | "OMRON_FINS.collector.20250207-8": "请选择设备型号", 10 | "OMRON_FINS.collector.20250207-9": "请输入正确的IP地址", 11 | "OMRON_FINS.collector.20250207-10": "协议类型", 12 | "OMRON_FINS.point.20250207-1": "寄存器", 13 | "OMRON_FINS.point.20250207-2": "请选择寄存器", 14 | "OMRON_FINS.point.20250207-3": "地址", 15 | "OMRON_FINS.point.20250207-4": "请输入地址", 16 | "OMRON_FINS.point.20250207-5": "项目数", 17 | "OMRON_FINS.point.20250207-6": "请输入项目数", 18 | "OMRON_FINS.point.20250207-7": "数据类型", 19 | "OMRON_FINS.point.20250207-8": "请选择数据类型", 20 | "OMRON_FINS.point.20250207-9": "偏移量", 21 | "OMRON_FINS.point.20250207-10": "请输入偏移量", 22 | "OMRON_FINS.point.20250207-11": "访问类型", 23 | "OMRON_FINS.point.20250207-12": "请选择访问类型", 24 | "OMRON_FINS.point.20250207-13": "读", 25 | "OMRON_FINS.point.20250207-14": "写" 26 | } 27 | -------------------------------------------------------------------------------- /public/protocol/OMRON_FINS/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/OPC_DA/channel.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /public/protocol/OPC_DA/collector.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /public/protocol/OPC_DA/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "OPC_DA.channel.20250207-1": "Host address", 3 | "OPC_DA.channel.20250207-2": "Please enter the host address", 4 | "OPC_DA.channel.20250207-3": "Please enter a valid host address", 5 | "OPC_DA.channel.20250207-4": "Username", 6 | "OPC_DA.channel.20250207-5": "Please enter the username", 7 | "OPC_DA.channel.20250207-6": "Password", 8 | "OPC_DA.channel.20250207-7": "Please enter the password", 9 | "OPC_DA.collector.20250207-1": "Please enter the clsId", 10 | "OPC_DA.collector.20250207-2": "Program ID used in Windows applications" 11 | } 12 | -------------------------------------------------------------------------------- /public/protocol/OPC_DA/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "OPC_DA.channel.20250207-1": "主机地址", 3 | "OPC_DA.channel.20250207-2": "请输入主机地址", 4 | "OPC_DA.channel.20250207-3": "请输入正确的主机地址", 5 | "OPC_DA.channel.20250207-4": "用户名", 6 | "OPC_DA.channel.20250207-5": "请输入用户名", 7 | "OPC_DA.channel.20250207-6": "密码", 8 | "OPC_DA.channel.20250207-7": "请输入密码", 9 | "OPC_DA.collector.20250207-1": "请输入clsId", 10 | "OPC_DA.collector.20250207-2": "应用在windows上的程序id" 11 | } 12 | -------------------------------------------------------------------------------- /public/protocol/OPC_DA/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/OPC_UA/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "OPC_UA.channel.20250207-1": "Endpoint URL", 3 | "OPC_UA.channel.20250207-2": "Please enter the endpoint URL", 4 | "OPC_UA.channel.20250207-3": "Security Policy", 5 | "OPC_UA.channel.20250207-4": "Please select the security policy", 6 | "OPC_UA.channel.20250207-5": "Security Mode", 7 | "OPC_UA.channel.20250207-6": "Please select the security mode", 8 | "OPC_UA.channel.20250207-7": "Authentication", 9 | "OPC_UA.channel.20250207-8": "Please enter the Modbus host IP", 10 | "OPC_UA.channel.20250207-9": "Anonymous User", 11 | "OPC_UA.channel.20250207-10": "Username", 12 | "OPC_UA.channel.20250207-11": "Please enter the username", 13 | "OPC_UA.channel.20250207-12": "Password", 14 | "OPC_UA.channel.20250207-13": "Please enter the password", 15 | "OPC_UA.channel.20250207-14": "Please select the authentication method", 16 | "OPC_UA.channel.20250207-15": "Up to 64 characters can be entered", 17 | "OPC_UA.point.20250207-1": "Data Type", 18 | "OPC_UA.point.20250207-2": "Please select the data type", 19 | "OPC_UA.point.20250207-3": "Access Type", 20 | "OPC_UA.point.20250207-4": "Please select the access type", 21 | "OPC_UA.point.20250207-5": "Read", 22 | "OPC_UA.point.20250207-6": "Write", 23 | "OPC_UA.point.20250207-7": "Subscribe", 24 | "OPC_UA.scan.20250414-1": "Name" 25 | } 26 | -------------------------------------------------------------------------------- /public/protocol/OPC_UA/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "OPC_UA.channel.20250207-1": "端点url", 3 | "OPC_UA.channel.20250207-2": "请输入端点url", 4 | "OPC_UA.channel.20250207-3": "安全策略", 5 | "OPC_UA.channel.20250207-4": "请选择安全策略", 6 | "OPC_UA.channel.20250207-5": "安全模式", 7 | "OPC_UA.channel.20250207-6": "请选择安全模式", 8 | "OPC_UA.channel.20250207-7": "权限认证", 9 | "OPC_UA.channel.20250207-8": "请输入Modbus主机IP", 10 | "OPC_UA.channel.20250207-9": "匿名用户", 11 | "OPC_UA.channel.20250207-10": "用户名", 12 | "OPC_UA.channel.20250207-11": "请输入用户名", 13 | "OPC_UA.channel.20250207-12": "密码", 14 | "OPC_UA.channel.20250207-13": "请输入密码", 15 | "OPC_UA.channel.20250207-14": "请选择权限认证", 16 | "OPC_UA.channel.20250207-15": "最多可输入64个字符", 17 | "OPC_UA.channel.20250207-16": "证书", 18 | "OPC_UA.channel.20250207-17": "请选择证书", 19 | "OPC_UA.point.20250207-1": "数据类型", 20 | "OPC_UA.point.20250207-2": "请选择数据类型", 21 | "OPC_UA.point.20250207-3": "访问类型", 22 | "OPC_UA.point.20250207-4": "请选择访问类型", 23 | "OPC_UA.point.20250207-5": "读", 24 | "OPC_UA.point.20250207-6": "写", 25 | "OPC_UA.point.20250207-7": "订阅", 26 | "OPC_UA.scan.20250414-1": "名称" 27 | } 28 | -------------------------------------------------------------------------------- /public/protocol/OPC_UA/point.vue: -------------------------------------------------------------------------------- 1 | 36 | 61 | 62 | -------------------------------------------------------------------------------- /public/protocol/OPC_UA/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /public/protocol/OPC_UA/scan.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 54 | 55 | 58 | -------------------------------------------------------------------------------- /public/protocol/OPC_UA/scanTree.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 36 | 37 | 40 | -------------------------------------------------------------------------------- /public/protocol/iec104/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "iec104.collector.20250207-1": "Slave Address", 3 | "iec104.collector.20250207-2": "Please enter the slave address", 4 | "iec104.collector.20250207-3": "Slave Port", 5 | "iec104.collector.20250207-4": "Please enter the slave port", 6 | "iec104.collector.20250207-5": "Group Address", 7 | "iec104.collector.20250207-6": "Please enter the group address", 8 | "iec104.collector.20250207-7": "Please enter the channel port", 9 | "iec104.collector.20250207-8": "Please enter an integer between 1 and 65535", 10 | "iec104.collector.20250207-9": "Please enter the channel IP", 11 | "iec104.collector.20250207-10": "Please enter a valid domain name or IP address", 12 | "iec104.collector.20250207-11": "Please enter the group address", 13 | "iec104.collector.20250207-12": "Number of acknowledgement frames", 14 | "iec104.collector.20250207-13": "Please enter the number of confirmation frames", 15 | "iec104.point.20250207-1": "Type Identifier", 16 | "iec104.point.20250207-2": "Please select the type identifier", 17 | "iec104.point.20250207-3": "Address", 18 | "iec104.point.20250207-4": "Please enter the address", 19 | "iec104.point.20250207-5": "Read", 20 | "iec104.point.20250207-6": "Write", 21 | "iec104.point.20250207-7": "Subscribe", 22 | "iec104.point.20250207-8": "Access Type", 23 | "iec104.point.20250207-9": "Please select the access type" 24 | } 25 | -------------------------------------------------------------------------------- /public/protocol/iec104/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "iec104.collector.20250207-1": "从机地址", 3 | "iec104.collector.20250207-2": "请输入从机地址", 4 | "iec104.collector.20250207-3": "从机端口", 5 | "iec104.collector.20250207-4": "请输入从机端口", 6 | "iec104.collector.20250207-5": "分组地址", 7 | "iec104.collector.20250207-6": "请输入分组地址", 8 | "iec104.collector.20250207-7": "请输入通道端口", 9 | "iec104.collector.20250207-8": "请输入1~65535的整数", 10 | "iec104.collector.20250207-9": "请输入通道Ip", 11 | "iec104.collector.20250207-10": "请输入正确的域名或ip地址", 12 | "iec104.collector.20250207-11": "请输入分组地址", 13 | "iec104.collector.20250207-12": "确认帧数量", 14 | "iec104.collector.20250207-13": "请输入确认帧数量", 15 | "iec104.point.20250207-1": "类型标识", 16 | "iec104.point.20250207-2": "请选择类型标识", 17 | "iec104.point.20250207-3": "地址", 18 | "iec104.point.20250207-4": "请输入地址", 19 | "iec104.point.20250207-5": "读", 20 | "iec104.point.20250207-6": "写", 21 | "iec104.point.20250207-7": "订阅", 22 | "iec104.point.20250207-8": "访问类型", 23 | "iec104.point.20250207-9": "请选择访问类型" 24 | } 25 | -------------------------------------------------------------------------------- /public/protocol/iec104/point.vue: -------------------------------------------------------------------------------- 1 | 58 | 59 | 93 | 94 | -------------------------------------------------------------------------------- /public/protocol/iec104/pointActions.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/protocol/snap7/channel.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | -------------------------------------------------------------------------------- /public/protocol/snap7/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "snap7.collector.20250207-1": "请输入通道IP", 3 | "snap7.collector.20250207-2": "端口", 4 | "snap7.collector.20250207-3": "请输入通道端口", 5 | "snap7.collector.20250207-4": "机架号", 6 | "snap7.collector.20250207-5": "请输入机架号", 7 | "snap7.collector.20250207-6": "型号", 8 | "snap7.collector.20250207-7": "请选择型号", 9 | "snap7.collector.20250207-8": "槽位", 10 | "snap7.collector.20250207-9": "请输入槽位", 11 | "snap7.collector.20250207-10": "超时时间(毫秒)", 12 | "snap7.collector.20250207-11": "请输入超时时间", 13 | "snap7.collector.20250207-12": "数据读取方式", 14 | "snap7.collector.20250207-13": "并行", 15 | "snap7.collector.20250207-14": "串行", 16 | "snap7.collector.20250207-15": "请输入正确的域名或ip地址", 17 | "snap7.collector.20250207-16": "请输入1~65535的整数", 18 | "snap7.collector.20250207-17": "请输入0~65535的整数", 19 | "snap7.point.20250207-1": "地址区域", 20 | "snap7.point.20250207-2": "请选择地址区域", 21 | "snap7.point.20250207-3": "地址编号", 22 | "snap7.point.20250207-4": "请输入地址编号", 23 | "snap7.point.20250207-5": "数据类型", 24 | "snap7.point.20250207-6": "请选择数据类型", 25 | "snap7.point.20250207-7": "字符串长度(byte)", 26 | "snap7.point.20250207-8": "请输入0~65535之间的正整数", 27 | "snap7.point.20250207-9": "请输入字符串长度", 28 | "snap7.point.20250207-10": "位偏移量(bit)", 29 | "snap7.point.20250207-11": "请输入0~7之间的正整数", 30 | "snap7.point.20250207-12": "请输入位偏移量", 31 | "snap7.point.20250207-13": "偏移量", 32 | "snap7.point.20250207-14": "请输入0~65535之间的正整数", 33 | "snap7.point.20250207-15": "请输入偏移量", 34 | "snap7.point.20250207-16": "缩放因子", 35 | "snap7.point.20250207-17": "请输入缩放因子", 36 | "snap7.point.20250207-18": "小数保留位数", 37 | "snap7.point.20250207-19": "请输入小数保留位数", 38 | "snap7.point.20250207-20": "访问类型", 39 | "snap7.point.20250207-21": "请选择访问类型", 40 | "snap7.point.20250207-22": "轮询任务", 41 | "snap7.point.20250207-23": "采集频率", 42 | "snap7.point.20250207-24": "采集频率为0时不执行轮询任务", 43 | "snap7.point.20250207-25": "请输入采集频率", 44 | "snap7.point.20250207-26": "只推送变化的数据", 45 | "snap7.point.20250207-27": "请配置点位死区", 46 | "snap7.point.20250207-28": "变量存储区(V)", 47 | "snap7.point.20250207-29": "位", 48 | "snap7.point.20250207-30": "读", 49 | "snap7.point.20250207-31": "写", 50 | "snap7.point.20250207-32": "字节", 51 | "snap7.point.20250207-33": "基本参数", 52 | "snap7.point.20250207-34": "数据解析", 53 | "snap7.point.20250207-35": "采集传输" 54 | } 55 | -------------------------------------------------------------------------------- /public/protocol/snap7/pointActions.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 12 | 59 | 60 | -------------------------------------------------------------------------------- /src/api/account/center.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | export const getSsoBinds_api = (): any =>request.get(`/application/sso/me/bindings`) 4 | 5 | 6 | // 修改登录用户信息 7 | export const updateMeInfo_api = (data:object) => request.put(`/user/detail`,data); 8 | // 修改登录用户密码 9 | export const updateMepsd_api = (data:object) => request.put(`/user/passwd`,data); 10 | // 第三方账号解绑 11 | export const unBind_api = (appId: string) => request.post(`/application/sso/${appId}/unbind/me`,[]); 12 | /** 13 | * 校验字段合法性 14 | * @param type 类型 15 | * @param name 值 16 | */ 17 | export const validateField_api = (type: 'username' | 'password', name: string) => request.post(`/user/${type}/_validate`,name,{ 18 | headers: { 19 | 'Content-Type': 'text/plain' 20 | } 21 | }); 22 | /** 23 | * 校验旧密码是否正确 24 | * @param password 旧密码 25 | */ 26 | export const checkOldPassword_api = (password:string) => request.post(`/user/me/password/_validate`,password,{ 27 | headers: { 28 | 'Content-Type': 'text/plain' 29 | } 30 | }); 31 | 32 | // 我的订阅 33 | // 查询当前用户可访问的通道配置 34 | export const getAllNotice = () => request.get(`/notify/channel/all`); 35 | 36 | 37 | // 当前登录用户权限信息 38 | export const getMe_api = () => request.get<{ user: any, [key : string]: any }>(`/authorize/me`); 39 | // 设置登录用户选择的页面 40 | export const setView_api = (data:object) => request.patch(`/user/settings/view/user`, data); 41 | // 当前登录用户选择的页面 42 | export const getView_api = () => request.get(`/user/settings/view/user`); 43 | 44 | -------------------------------------------------------------------------------- /src/api/account/notificationRecord.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // 获取记录列表 4 | export const getList_api = (data: any): any => request.post(`/notifications/_query`, data) 5 | // 获取未读记录列表 6 | // export const getListByUnRead_api = (data: any): any => request.post(`/notifications/_query`, data) 7 | // 修改记录状态 8 | export const changeStatus_api = (type: '_read' | '_unread', data: string[]): any => request.post(`/notifications/${type}`, data) 9 | 10 | //查看工作流通知详情 11 | export const getWorkflowNotice = (data:any) => request.post('/process/runtime/processes/_query/no-paging',data) 12 | 13 | // 查询告警记录详情 14 | export const getDetail = (id: string): any => request.get(`/alarm/record/${id}`) 15 | 16 | /** 17 | * 查询等级 18 | */ 19 | export const queryLevel = () => request.get('/alarm/config/default/level'); 20 | 21 | -------------------------------------------------------------------------------- /src/api/account/notificationSubscription.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // 获取通知订阅列表 4 | export const getNoticeList_api = () => request.post(`/notifications/subscriptions/_query/`,{}); 5 | // 保存通知订阅 6 | export const save_api = (data:any) => request.patch(`/notifications/subscribe`, data); 7 | 8 | // 获取订阅类型 9 | export const getTypeList_api = () => request.get(`/notifications/providers`); 10 | 11 | //获取订阅类型 新 12 | export const getTypeListNew = (type:string) => request.get(`/notifications/current/${type}/providers`) 13 | 14 | // 判断获取当前用户绑定信 15 | export const getIsBindThird = () => request.get(`/user/third-party/me`); 16 | 17 | // 生成OAuth2授权URL 18 | export const getWechatOAuth2 = (configId: string, templateId: string, url: string) => request.get(`/notifier/wechat/corp/${configId}/${templateId}/oauth2/binding-user-url?redirectUri=${url}`); 19 | 20 | export const getDingTalkOAuth2 = (configId: string, url: string) => request.get(`/notifier/dingtalk/corp/${configId}/oauth2/binding-user-url?authCode=${url}`); 21 | 22 | // 获取oauth2授权的用户绑定码 23 | 24 | export const getUserBind = (type: 'wechat' | 'dingtalk', params: any) => request.get(`/notifier/${type}/corp/oauth2/user-bind-code`, params); 25 | 26 | // 根据绑定码绑定当前用户 27 | export const bindThirdParty = (type: string, provider: string, bindCode: string) => request.post(`/user/third-party/me/${type}/${provider}/${bindCode}/_bind`); 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/api/application.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | export const uiList = () => request.get('/system/resources/ui') 4 | -------------------------------------------------------------------------------- /src/api/auth.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // 当前登录用户权限信息 4 | export const getMe_api = () => request.get(`/authorize/me`); 5 | -------------------------------------------------------------------------------- /src/api/comm.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | import {getToken} from "@jetlinks-web/utils"; 3 | import {BASE_API, TOKEN_KEY_URL} from '@jetlinks-web/constants'; 4 | 5 | export const FileStatic = '/file/upload' 6 | export const FileStaticPath = `${BASE_API}${FileStatic}` 7 | export const getFileUrlById = (id: string) => `${BASE_API}/file/${id}?${TOKEN_KEY_URL}=${getToken()}` 8 | export const fileUpload = (data: any) => request.post(FileStatic, data) 9 | 10 | /** 11 | * 保存查询记录 12 | * @param data 13 | * @param target 14 | */ 15 | export const saveSearchHistory = (data: any, target:string) => request.post(`/user/settings/${target}`, data) 16 | 17 | /** 18 | * 获取查询记录 19 | * @param target 20 | */ 21 | export const getSearchHistory = (target:string) => request.get(`/user/settings/${target}`) 22 | 23 | /** 24 | * 删除指定查询记录 25 | * @param id 26 | * @param target 27 | */ 28 | export const deleteSearchHistory = (target:string, id:string) => request.remove(`/user/settings/${target}/${id}`) 29 | 30 | /** 31 | * 聚合查询 32 | * @param data 33 | * @returns 34 | */ 35 | export const queryDashboard = (data: Record) => request.post(`/dashboard/_multi`, data) 36 | 37 | export const lowCodeUrl = () => request.get('/system/config/low-code') 38 | /** 39 | * 获取认证配置 40 | * @param tokenId 41 | */ 42 | export const getTokenConfig = (tokenId: string) => request.get(`/personal/token/${tokenId}/_config`) 43 | 44 | /** 45 | * 获取跳转链接 46 | * @param tokenId 47 | * @param data 48 | */ 49 | export const getTokenRedirect = (tokenId: string, data: any) => 50 | request.post(`/personal/token/${tokenId}/_redirect`, data) -------------------------------------------------------------------------------- /src/api/initHome.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // 更新全部菜单 4 | export const updateMenus = (data: any) => request.patch(`/menu/iot/_all`, data) 5 | 6 | 7 | // 记录初始化 8 | export const saveInit = () => request.post(`/user/settings/init`,{ init: true },) 9 | 10 | //获取初始化 11 | export const getInit = () => request.get(`/user/settings/init`) 12 | 13 | // 保存基础信息 14 | export const save = (data?: any) => request.post('/system/config/scope/_save',data) 15 | 16 | // 查询保存后的数据 17 | export const detail = (data?: any) => request.post(`/system/config/scopes`, data) 18 | 19 | // 获取当前系统权限信息 20 | 21 | export const getSystemPermission = () =>request.get(`/system/resources/permission`) 22 | 23 | //更新权限菜单 24 | export const updateRoleMenu = (id: string, data: any) => request.put(`/menu/role/${id}/_grant`, data) 25 | 26 | // 添加角色 27 | export const addRole = (data: any) => request.post(`/role`, data) 28 | 29 | //更新权限菜单 30 | export const getRoleMenu = (id: string) => request.get(`/menu/role/${id}/_grant/tree`) 31 | 32 | //添加角色分组 33 | export const addRoleGroup = (data:any) => request.patch('/role/group',data) 34 | 35 | /** 36 | * 查询系统版本信息 37 | * @returns 38 | */ 39 | export const systemVersion = () => request.get(`/system/version`) 40 | 41 | // export const getProviders = () => request.get(`/data-collect/channel/providers`); 42 | export const queryModule = () => request.get(`/command-supports/service/collectorService:collector/commands`); 43 | 44 | export const saveNetwork = (data: any) => request.post(`/network/config`, data) 45 | 46 | // 保存协议 47 | export const saveProtocol = () => request.post(`/protocol/default-protocol/_save`) 48 | 49 | // 新增设备接入网关 50 | export const saveAccessConfig = (data: any) => request.post(`/gateway/device`, data) 51 | 52 | // 新增产品 53 | export const saveProduct = (data: any) => request.post(`/device/product`,data) 54 | 55 | // 新增设备 56 | export const saveDevice = (data: any) => request.post(`/device/instance`,data) 57 | 58 | // 启用设备 59 | export const deployDevice = (deviceId: string, params?: any) => request.post(`/device-instance/${deviceId}/deploy`,params,) 60 | export const changeDeploy= (id: string) => request.post(`/device-product/${id}/deploy`) 61 | 62 | // 获取协议 63 | export const getProtocol = () => request.get(`/protocol/_query/no-paging?paging=false`) 64 | 65 | // 查询对应协议下的本地端口数据 66 | export const getResourcesCurrent = () => request.get('/network/resources/alive/_current') 67 | 68 | -------------------------------------------------------------------------------- /src/api/login.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | /** 4 | * 登录 5 | * @param data 6 | * @returns 7 | */ 8 | export const login = (data: any) => request.post('/authorize/login', data) 9 | 10 | /** 11 | * 退出登录 12 | */ 13 | export const logout = () => request.get('/user-token/reset') 14 | 15 | /** 16 | * 获取验证码 17 | */ 18 | export const codeUrl = () => request.get<{ base64: string, key: string }>(`/authorize/captcha/image?width=130&height=30`) 19 | 20 | /** 21 | * 登录加密信息 22 | * @returns 23 | */ 24 | export const encryptionConfig = () => request.get(`/authorize/login/configs`) 25 | 26 | /** 27 | * 登录加密信息 28 | * @returns 29 | */ 30 | export const captchaConfig = () => request.get(`/authorize/captcha/config`) 31 | 32 | 33 | /** 34 | * 登录 35 | * @returns 36 | */ 37 | export const authLogin = (data: any) => request.post(`/authorize/login`, data) 38 | 39 | /** 40 | * 获取当前登录用户信息 41 | */ 42 | export const userDetail = () => request.get('/user/detail') 43 | 44 | /** 45 | * 查询初始化配置信息 46 | * @returns 47 | */ 48 | export const getInitSet = () => request.get(`/user/settings/init`) 49 | 50 | /** 51 | * 查看后端配置模块 52 | */ 53 | export const queryModal = (serviceId:string) => request.get(`/command-supports/service/${serviceId}/exists`) 54 | 55 | /** 56 | * 获取支持的SSO的应用 57 | * @returns 58 | */ 59 | export const bindInfo = () => request.get(`/application/sso/_all`) 60 | 61 | export const getOAuth2 = (params: any) => request.get('/oauth2/authorize', params) 62 | 63 | export const initApplication = (clientId: string | number) => request.get<{name: string}>(`/application/${clientId}/info`) 64 | 65 | -------------------------------------------------------------------------------- /src/api/system/apply.ts: -------------------------------------------------------------------------------- 1 | import {request} from '@jetlinks-web/core'; 2 | // 3 | // 4 | // // 获取应用管理列表 5 | // export const getApplyList_api = (data: any) => request.post(`/application/_query/`, data) 6 | // // 修改应用状态 7 | // export const changeApplyStatus_api = (id: string, data: any) => request.put(`/application/${id}`, data) 8 | // // 删除应用 9 | // export const delApply_api = (id: string) => request.remove(`/application/${id}`) 10 | // 11 | // export const queryType = () => request.get(`/application/providers`) 12 | // 13 | // // 获取组织列表 14 | // export const getDepartmentList_api = (params: any) => request.get(`/organization/_all/tree`, params); 15 | // 获取应用详情 16 | export const getAppInfo_api = (id: string) => request.get(`/application/${id}`); 17 | // // 新增应用 18 | // export const addApp_api = (data: object) => request.post(`/application`, data); 19 | // // 更新应用 20 | // export const updateApp_api = (id: string, data: object) => request.put(`/application/${id}`, data); 21 | // 22 | // 23 | // // ---------集成菜单----------- 24 | // 25 | // // 获取所属系统 26 | // export const getOwner_api = (data: object) => request.post(`/menu/owner`, data); 27 | // export const getOwnerStandalone_api = (appId: string, data: object) => request.post(`/application/${appId}/_/api/menu/owner`, data); 28 | // 29 | // // 获取对应系统菜单树 30 | // export const getOwnerTree_api = (owner: string) => request.post(`/menu/owner/tree/${owner}`, {}); 31 | // export const getOwnerTreeStandalone_api = (appId: string, owner: string) => request.post(`/application/${appId}/_/api/menu/owner/tree/${owner}`, {}); 32 | // // 保存集成菜单 33 | // export const saveOwnerMenu_api = (owner: string, appId: string, data: object) => request.patch(`/menu/owner/${owner}/${appId}/_all`, data); 34 | -------------------------------------------------------------------------------- /src/api/system/basis.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // 保存 4 | export const save_api = (data: any) => request.post(`/system/config/scope/_save`, data) 5 | // 获取详情 6 | export const getDetails_api = (data: any) => request.post(`/system/config/scopes`, data) 7 | 8 | /** 9 | * 系统版本 10 | */ 11 | export const systemVersion = () => request.get('/system/version') 12 | 13 | /** 14 | * 系统配置信息 15 | * @param scopes 16 | */ 17 | export const settingDetail = (scopes: string) => request.get(`/system/config/${scopes}`) 18 | 19 | /** 20 | * 判断预处理数据是否开启 21 | */ 22 | export const preprocessorExists = () => request.get(`/command-supports/service/metadataPreprocessor/exists`) 23 | -------------------------------------------------------------------------------- /src/api/system/bind.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // 三方应用账户信息 4 | export const applicationInfo = (code: string): any => request.get(`/application/sso/bind-code/${code}`) 5 | // 立即绑定 6 | export const bindAccount = (code: string): any => request.post(`/application/sso/me/bind/${code}`) 7 | -------------------------------------------------------------------------------- /src/api/system/calendar.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core'; 2 | //编辑标签 3 | export const saveTag = (data:any) => request.patch('/calendar/tags',data) 4 | //查询标签列表 5 | export const queryTags = () => request.get('/calendar/tags') 6 | //删除标签 7 | export const deleteTags = (ids:any) => request.post('/calendar/tags/_delete',{},{ data:ids }) 8 | //保存标签颜色 9 | export const saveTagsColor = (data:any) => request.post('/system/config/calendar-tag-color',data) 10 | //查询标签颜色 11 | export const getTagsColor = () => request.get('/system/config/calendar-tag-color'); 12 | 13 | //查询指定日期内的日历 14 | export const queryEvents = (dateFrom:any,dateTo:any) => request.get(`/calendar/${dateFrom}/${dateTo}`) 15 | //批量保存指定日期的日历 16 | export const saveEvents = (data:any) => request.patch('/calendar',data) 17 | //清空日历 18 | export const clearAll = () => request.remove('/calendar/mine/_all') 19 | -------------------------------------------------------------------------------- /src/api/system/department.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // 获取部门数据 4 | export const getTreeData_api = (data: object) => request.post(`/organization/_all/tree`, data); 5 | 6 | -------------------------------------------------------------------------------- /src/api/system/menu.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // /** 4 | // * 获取当前用户可访问菜单 5 | // * @param data 6 | // * @returns 7 | // */ 8 | // export const getMenuTree = (data: any) => request.post(`/menu/_all/tree`, data); 9 | 10 | /** 11 | * 获取当前用户可访问菜单 包含权限 12 | * @param data 13 | * @returns 14 | */ 15 | export const getOwnMenuThree = (data: any) => request.post('/menu/user-own/tree', data) 16 | // /** 17 | // * 校验编码唯一性 18 | // * @param data 19 | // */ 20 | // export const validMenuCode = (data: any) => request.get(`/menu/code/_validate`,data); 21 | // 22 | // /** 23 | // * 获取资产类型 24 | // * @returns 25 | // */ 26 | // export const getAssetsType = () => request.get(`/asset/types`); 27 | // 28 | // /** 29 | // * 获取菜单详情 30 | // * @returns 31 | // */ 32 | // export const getMenuInfo = (id: string) => request.get(`/menu/${id}`); 33 | // 34 | // /** 35 | // * 编辑菜单信息 36 | // * @returns 37 | // */ 38 | // export const updateMenu = (data: any) => request.patch(`/menu`, data); 39 | // 40 | // /** 41 | // * 新增菜单信息 42 | // * @returns 43 | // */ 44 | // export const addMenu = (data: any) => request.post(`/menu`, data); 45 | // 46 | // /** 47 | // * 删除菜单信息 48 | // * @returns 49 | // */ 50 | // export const delMenu = (id: string) => request.remove(`/menu/${id}`); 51 | // 52 | // /** 53 | // * 获取支持的数采协议 54 | // */ 55 | // export const getProviders = () => request.get(`/data-collect/channel/providers`); 56 | // 57 | // // 获取当前用户可访问菜单 58 | // export const getMenuTree_api = (data: object) => request.post(`/menu/_all/tree`, data); 59 | // 60 | // /** 61 | // * 校验编码唯一性 62 | // * @param data 63 | // */ 64 | // export const validCode_api = (data:object) => request.get(`/menu/code/_validate`,data); 65 | // 66 | // // 获取菜单详情 67 | // export const getMenuInfo_api = (id:string) => request.get(`/menu/${id}`); 68 | // // 编辑菜单信息 69 | // export const saveMenuInfo_api = (data: object) => request.patch(`/menu`, data); 70 | // // 新增菜单信息 71 | // export const addMenuInfo_api = (data: object) => request.post(`/menu`, data); 72 | // // 删除菜单信息 73 | // export const delMenuInfo_api = (id: string) => request.remove(`/menu/${id}`); 74 | -------------------------------------------------------------------------------- /src/api/system/positions.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | // export const save = (orgId: string, data: any) => request.post(`/position/${orgId}/_create`, data) 4 | // 5 | // export const update = (id: string, data: any) => request.patch(`/position/${id}/_save`, data) 6 | // 7 | // export const detail = (id: string) => request.post('/position/_query/detail/no-paging', { terms: [{ 8 | // "column":"id", 9 | // "termType":"eq", 10 | // "value": id 11 | // }]}) 12 | // // 职位绑定用户 13 | // export const bindUser = (orgId: string, id: string, userIdList: Array) => request.post(`/organization/${orgId}/position/${id}/users/_bind`, userIdList) 14 | // // 职位解绑用户 15 | // export const unbindUser = (orgId: string, id: string, userIdList: Array) => request.post(`/organization/${orgId}/position/${id}/users/_unbind`, userIdList) 16 | // 17 | // export const del = (id: string) => request.remove(`/position/${id}`) 18 | // 19 | // export const getUser = (data: any) => request.post(`/user/detail/_query`, data) 20 | // 21 | // export const queryPage = (data: any) => request.post('/position/_query/detail', data) 22 | 23 | export const queryPageNoPage = (data?: any) => request.post('/position/_query/detail/no-paging', data) 24 | -------------------------------------------------------------------------------- /src/api/system/user.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@jetlinks-web/core' 2 | 3 | /** 4 | * 获取用户基本信息 5 | * @returns 6 | */ 7 | export const detail = () => request.get('/user/detail') 8 | 9 | // // 获取用户类型 10 | // export const getUserType_api = () => request.get(`/user/detail/types`); 11 | // 12 | // // 获取用户列表 13 | // export const getUserList_api = (data: any) => request.post(`/user/detail/_query`, data); 14 | // 15 | // // 校验字段合法性 16 | // export const validateField_api = (type: 'username' | 'password', name: string) => request.post(`/user/${type}/_validate`, name, { 17 | // headers: { 18 | // 'Content-Type': 'text/plain' 19 | // } 20 | // }) 21 | // 22 | // // 获取角色列表 23 | // export const getRoleList_api = () => request.get(`/role/_query/no-paging?paging=false`); 24 | // 25 | /** 26 | * 查询用户列表 27 | * @returns 28 | */ 29 | export const queryUserListNoPaging = () => request.post(`/user/_query/no-paging`, { 30 | paging: false, 31 | sorts: [{ name: 'name', order: "asc" }] 32 | }) 33 | // 34 | //获取角色列表 35 | export const getRoleList = (data:any) => request.post('/role/group/detail/_query/tree',data) 36 | // 获取组织列表 37 | export const getDepartmentList_api = (data:any) => request.post(`/organization/_all/tree`,data); 38 | // 39 | // // 获取用户信息 40 | // export const getUser_api = (id: string) => request.get(`/user/detail/${id}`); 41 | // // 添加用户 42 | // export const addUser_api = (data: any) => request.post(`/user/detail/_create`, data); 43 | // // 更新用户 44 | // export const updateUser_api = (data: any) => request.put(`/user/detail/${data.id}/_update`, data); 45 | // // 更新密码 46 | // export const updatePassword_api = (data: { id: string, password: string }) => request.post(`/user/${data.id}/password/_reset`, data.password, { 47 | // headers: { 48 | // 'Content-Type': 'text/plain' 49 | // } 50 | // }); 51 | // // 修改用户状态 52 | // export const changeUserStatus_api = (data: object) => request.patch(`/user`,data); 53 | // // 删除用户 54 | // export const deleteUser_api = (id: string) => request.remove(`/user/${id}`); 55 | // 56 | // // 查询角色不分页 57 | // export const queryRole_api = (data: any): Promise => request.post(`/role/_query/no-paging`, data) 58 | -------------------------------------------------------------------------------- /src/assets/apply/internal-standalone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/apply/internal-standalone.png -------------------------------------------------------------------------------- /src/assets/apply/third-party.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/apply/third-party.png -------------------------------------------------------------------------------- /src/assets/apply/wechat-miniapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/apply/wechat-miniapp.png -------------------------------------------------------------------------------- /src/assets/bindPage/Vector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/bindPage/Vector.png -------------------------------------------------------------------------------- /src/assets/bindPage/bindPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/bindPage/bindPage.png -------------------------------------------------------------------------------- /src/assets/bindPage/dingtalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/bindPage/dingtalk.png -------------------------------------------------------------------------------- /src/assets/bindPage/jetlinksLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/bindPage/jetlinksLogo.png -------------------------------------------------------------------------------- /src/assets/bindPage/wechat-webapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/bindPage/wechat-webapp.png -------------------------------------------------------------------------------- /src/assets/token-error-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/token-error-icon.png -------------------------------------------------------------------------------- /src/assets/token-error.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jetlinks/jetlinks-ui-vue/6279a075340e5538f74fa6cd5613d57e3431161f/src/assets/token-error.jpg -------------------------------------------------------------------------------- /src/components/AMapComponent/AMap.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/components/AMapComponent/GeoJson.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 88 | 89 | 92 | -------------------------------------------------------------------------------- /src/components/AMapComponent/index.ts: -------------------------------------------------------------------------------- 1 | import AMap from './AMap.vue' 2 | 3 | export * from './useMap' 4 | export { default as DistrictSearch } from './DistrictSearch.vue' 5 | export { default as GeoJson } from './GeoJson.vue' 6 | 7 | export default AMap 8 | -------------------------------------------------------------------------------- /src/components/AMapComponent/useMap.ts: -------------------------------------------------------------------------------- 1 | export const useMap = () => { 2 | return inject('parentInstance') 3 | } 4 | 5 | -------------------------------------------------------------------------------- /src/components/AMapComponent/utils.ts: -------------------------------------------------------------------------------- 1 | const protocol = window.location.protocol; 2 | 3 | const buildScriptTag = (src: string): HTMLScriptElement => { 4 | const script = document.createElement('script'); 5 | script.type = 'text/javascript'; 6 | script.async = true; 7 | script.defer = true; 8 | script.src = src; 9 | return script; 10 | }; 11 | 12 | export const getAMapUiPromise = (version: string = '1.0'): Promise => { 13 | if ((window as any).AMapUI) { 14 | return Promise.resolve(); 15 | } 16 | const script = buildScriptTag(`${protocol}//webapi.amap.com/ui/${version}/main-async.js`); 17 | const pro = new Promise((resolve) => { 18 | script.onload = () => { 19 | (window as any).initAMapUI(); 20 | resolve(true); 21 | }; 22 | }); 23 | 24 | document.body.append(script); 25 | return pro; 26 | }; 27 | -------------------------------------------------------------------------------- /src/components/BatchDropdown/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { ButtonProps } from "ant-design-vue/es/button"; 2 | import type { PopconfirmProps } from "ant-design-vue/es/popconfirm"; 3 | 4 | export interface BatchActionsType extends ButtonProps { 5 | key: string; 6 | text?: string; 7 | permission?: string; 8 | onClick?: (data: any) => void; 9 | style?: CSSProperties; 10 | popConfirm?: PopconfirmProps; 11 | icon?: string; 12 | selected?: {// 需要选择表格数据,后触发的事件 13 | popConfirm?: PopconfirmProps; 14 | onClick?: (data: any) => void 15 | } 16 | } -------------------------------------------------------------------------------- /src/components/CardBox/images.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /src/components/CardSelect/RadioButton.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 52 | 53 | 73 | -------------------------------------------------------------------------------- /src/components/CardSelect/index.ts: -------------------------------------------------------------------------------- 1 | import CardSelect from './CardSelect.vue'; 2 | import type { App } from 'vue'; 3 | 4 | CardSelect.name = 'JCardSelect'; 5 | 6 | CardSelect.install = function (app: App) { 7 | app.component('JCardSelect', CardSelect); 8 | return app; 9 | }; 10 | 11 | export default CardSelect; 12 | -------------------------------------------------------------------------------- /src/components/CheckButton/index.ts: -------------------------------------------------------------------------------- 1 | import CheckButton from "./CheckButton.vue"; 2 | 3 | export default CheckButton 4 | -------------------------------------------------------------------------------- /src/components/ConfirmModal/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 72 | 77 | -------------------------------------------------------------------------------- /src/components/Dashboard/components/Charts.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 57 | 58 | 64 | -------------------------------------------------------------------------------- /src/components/Dashboard/components/EchartsTime.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 50 | 51 | -------------------------------------------------------------------------------- /src/components/Dashboard/components/Guide.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 22 | 23 | 59 | -------------------------------------------------------------------------------- /src/components/Dashboard/components/ServerList.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 54 | 55 | 80 | -------------------------------------------------------------------------------- /src/components/Dashboard/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as TimeSelect} from './TimeSelect.vue' 2 | -------------------------------------------------------------------------------- /src/components/Dashboard/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CardItem } from './CardItem.vue' 2 | export { default as GaugeCard } from './GaugeCard.vue' 3 | export { default as TimeLineEchart } from './TimeLineEchart.vue' 4 | export { default as TrendChart } from './TrendChart.vue' 5 | export { default as NetWork } from './NetWork.vue' 6 | -------------------------------------------------------------------------------- /src/components/FormItem/index.ts: -------------------------------------------------------------------------------- 1 | import FormItemOrg from './OrgList.vue' 2 | import FormItemRole from './RoleList.vue' 3 | import FormItemPosition from './Position.vue' 4 | 5 | export default { 6 | FormItemOrg, 7 | FormItemRole, 8 | FormItemPosition 9 | } 10 | -------------------------------------------------------------------------------- /src/components/HomeView/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 57 | 58 | 83 | -------------------------------------------------------------------------------- /src/components/MCarousel/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 58 | 59 | -------------------------------------------------------------------------------- /src/components/Player/mediaTool.vue: -------------------------------------------------------------------------------- 1 | 2 | 63 | 64 | 71 | 72 | 75 | -------------------------------------------------------------------------------- /src/components/Player/utils.ts: -------------------------------------------------------------------------------- 1 | import FlvPlugin from 'xgplayer-flv' 2 | import HlsPlugin from "xgplayer-hls" 3 | export const settingEnum = { 4 | mp4: { 5 | isLive: false, 6 | }, 7 | flv: { 8 | plugins: [FlvPlugin], 9 | }, 10 | m3u8: { 11 | plugins: [HlsPlugin], 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/components/Search/Search.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 93 | 94 | 101 | -------------------------------------------------------------------------------- /src/components/Search/index.ts: -------------------------------------------------------------------------------- 1 | import Search from './Search.vue' 2 | 3 | export default Search -------------------------------------------------------------------------------- /src/components/Search/search.md: -------------------------------------------------------------------------------- 1 | # Search组件 2 | 3 | - 需要结合Table使用 4 | 5 | ## 属性 6 | 7 | | 名称 | 说明 | 类型 | 默认值 | 8 | | --- | --- | --- | --- | 9 | | columns | 查询下拉列表 | JColumnsProps[] | [] | 10 | | type | 查询模式 | 'advanced', 'simple' | 'advanced' | 11 | | target | 查询组件唯一key | String | | 12 | | search | 查询回调事件 | Function | | 13 | 14 | > JColumnsProps[*].search 15 | 16 | | 名称 | 说明 | 类型 | 默认值 | 17 | | --- | --- | --- | --- | 18 | | rename | 用来重命名查询字段值 | String | | 19 | | type | 查询值组件类型 | 'select', 'number', 'string', 'treeSelect', 'date', 'time' | | 20 | | options | Select和TreeSelect组件下拉值 | Array, Promise | | 21 | | first | 控制查询字段下拉默认值,默认为name即名称 | Boolean | | 22 | | defaultTermType | 查询条件 | String | | 23 | | handleValue | 处理单个查询value值 | Function | | 24 | 25 | ## 基础用法 26 | 27 | > columns中包含search属性才会出现在查询下拉中 28 | 29 | ```vue 30 | const columns = [ 31 | { 32 | title: '名称', 33 | dataIndex: 'name', 34 | key: 'name', 35 | search: { 36 | type: 'string', 37 | } 38 | } 39 | ] 40 | const search = (params) => { 41 | } 42 | 47 | ``` 48 | 49 | > rename的作用在于search抛出params会根据rename修改数据中column的值 50 | 51 | ```vue 52 | const columns = [ 53 | { 54 | title: '名称', 55 | dataIndex: 'name', 56 | key: 'name', 57 | search: { 58 | type: 'string', 59 | rename: 'TestName' 60 | } 61 | } 62 | ] 63 | const search = (params) => { 64 | terms: [ 65 | { 66 | column: 'TestName', 67 | value: '', 68 | termType: 'like' 69 | } 70 | ] 71 | } 72 | 77 | ``` 78 | 79 | > defaultTermType的作用在于设置查询条件,相关条件参考util中的termType 80 | 81 | ```vue 82 | const columns = [ 83 | { 84 | title: '名称', 85 | dataIndex: 'name', 86 | key: 'name', 87 | search: { 88 | type: 'string', 89 | defaultTermType: 'gt' 90 | } 91 | } 92 | ] 93 | const search = (params) => { 94 | terms: [ 95 | { 96 | column: 'TestName', 97 | value: '', 98 | termType: 'gt' 99 | } 100 | ] 101 | } 102 | 107 | ``` 108 | -------------------------------------------------------------------------------- /src/components/Search/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface SearchBaseProps { 2 | rename?: string 3 | type?: 'select' | 'number' | 'string' | 'treeSelect' | 'date' | 'time' 4 | format?: string 5 | options?: any[] | Function 6 | first?: boolean 7 | defaultTermType?: string // 默认 eq 8 | title?: ColumnType.title 9 | sortIndex?: number 10 | handleValue?: (value: SearchItemData) => any 11 | } 12 | 13 | export interface SearchItemProps { 14 | rename?: SearchBaseProps['rename'] 15 | title: string 16 | column: ColumnType.dataIndex 17 | } 18 | 19 | export interface SearchItemData { 20 | column: ColumnType.dataIndex 21 | value: any 22 | termType: string 23 | type?: string 24 | } 25 | 26 | export interface TermsItem { 27 | terms: SearchItemData[] 28 | } 29 | 30 | export interface Terms { 31 | terms: TermsItem[] 32 | } 33 | 34 | export interface SortItem { 35 | name: string 36 | order?: 'desc' | 'asc' 37 | value?: any 38 | } 39 | 40 | export interface SearchHistoryList { 41 | content?: string 42 | name: string 43 | id: string 44 | key: string 45 | } 46 | 47 | export interface SearchProps extends SearchBaseProps, SearchItemProps { 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/components/Search/util.ts: -------------------------------------------------------------------------------- 1 | import i18n from "@/locales"; 2 | export const typeOptions = [ 3 | { label: i18n.global.t('Search.util.184827-0'), value: 'or' }, 4 | { label: i18n.global.t('Search.util.184827-1'), value: 'and' }, 5 | ] 6 | 7 | export const termType = [ 8 | { label: '=', value: 'eq' }, 9 | { label: '!=', value: 'not' }, 10 | { label: i18n.global.t('Search.util.184827-2'), value: 'like' }, 11 | { label: i18n.global.t('Search.util.184827-3'), value: 'nlike' }, 12 | { label: '>', value: 'gt' }, 13 | { label: '>=', value: 'gte' }, 14 | { label: '<', value: 'lt' }, 15 | { label: '<=', value: 'lte' }, 16 | { label: i18n.global.t('Search.util.184827-4'), value: 'in' }, 17 | { label: i18n.global.t('Search.util.184827-5'), value: 'nin' }, 18 | ]; -------------------------------------------------------------------------------- /src/components/TitleComponent/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 22 | 23 | 50 | -------------------------------------------------------------------------------- /src/components/Upload/Cropper.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 69 | 70 | 73 | -------------------------------------------------------------------------------- /src/components/Upload/Image/cropper.md: -------------------------------------------------------------------------------- 1 | ## Cropper 2 | [地址](https://github.com/xyxiao001/vue-cropper) 3 | 4 | ## 二、文档 5 | 6 | ### 1. props 7 | 8 | > 目前还不知道什么原因项目里面开启 `mock` 会导致 file 报错,建议使用时关掉 `mock` 9 | 10 | 11 | 名称 | 功能 | 默认值 | 可选值 12 | --- | --- | --- | --- 13 | img | 裁剪图片的地址 | 空 | `url 地址`, `base64`, `blob` 14 | outputSize | 裁剪生成图片的质量 | `1` | 0.1 ~ 1 15 | outputType | 裁剪生成图片的格式 | jpg (jpg 需要传入jpeg) | `jpeg`, `png`, `webp` 16 | info | 裁剪框的大小信息 | `true` | `true`, `false` 17 | canScale | 图片是否允许滚轮缩放 | `true` | `true`, `false` 18 | autoCrop | 是否默认生成截图框 | `false` | `true`, `false` 19 | autoCropWidth | 默认生成截图框宽度 | 容器的 80% | 0 ~ max 20 | autoCropHeight | 默认生成截图框高度 | 容器的 80% | 0 ~ max 21 | fixed | 是否开启截图框宽高固定比例 | `false` | `true`, `false` 22 | fixedNumber | 截图框的宽高比例 | `[1, 1]` | `[ 宽度 , 高度 ]` 23 | full | 是否输出原图比例的截图 | `false` | `true`, `false` 24 | fixedBox | 固定截图框大小 | 不允许改变 | `false` | `true`, `false` 25 | canMove | 上传图片是否可以移动 | `true` | `true`, `false` 26 | canMoveBox | 截图框能否拖动 | `true` | `true`, `false` 27 | original | 上传图片按照原始比例渲染 | `false` | `true`, `false` 28 | centerBox | 截图框是否被限制在图片里面 | `false` | `true`, `false` 29 | high | 是否按照设备的dpr 输出等比例图片 | `true` | `true`, `false` 30 | infoTrue | true 为展示真实输出图片宽高 `false` 展示看到的截图框宽高 | false | `true`, `false` 31 | maxImgSize | 限制图片最大宽度和高度 | `2000` | 0 ~ max 32 | enlarge | 图片根据截图框输出比例倍数 | `1` | 0 ~ max(建议不要太大不然会卡死的呢) 33 | mode | 图片默认渲染方式 | `contain` | `contain` , `cover`, `100px`, `100%` auto 34 | limitMinSize | 裁剪框限制最小区域 | 10 | Number, Array, String 35 | fillColor | 导出时背景颜色填充 | 空 | `#ffffff`, `white` 36 | 37 | ### CropperModal props 38 | 39 | 名称 | 功能 | 默认值 | 可选值 40 | --- |-----------|-------------------|---------------------------- 41 | img | 裁剪图片的地址 | 空 | `url 地址`, `base64`, `blob` 42 | outputSize | 裁剪生成图片的质量 | `1` | 0.1 ~ 1 43 | outputType | 裁剪生成图片的格式 | jpg (jpg 需要传入jpeg) | `jpeg`, `png`, `webp` 44 | autoCrop | 是否默认生成截图框 | `true` | `true`, `false` 45 | autoCropWidth | 默认生成截图框宽度 | 200 | 0 ~ max 46 | autoCropHeight | 默认生成截图框高度 | 200 | 0 ~ max 47 | fixedBox | 固定截图框大小 | `true` | `true`, `false` 48 | openServer | 是否开启文件上传 | `true` | `true`, `false` 49 | -------------------------------------------------------------------------------- /src/components/antd-install.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import { 3 | Button, 4 | Divider, 5 | Row, 6 | Col, 7 | Space, 8 | Dropdown, 9 | Menu, 10 | Pagination, 11 | Steps, 12 | AutoComplete, 13 | Cascader, 14 | Checkbox, 15 | DatePicker, 16 | Form, 17 | Input, 18 | InputNumber, 19 | Radio, 20 | Select, 21 | Switch, 22 | TimePicker, 23 | TreeSelect, 24 | Upload, 25 | Avatar, 26 | Badge, 27 | Card, 28 | Collapse, 29 | Descriptions, 30 | Empty, 31 | Image, 32 | List, 33 | Popover, 34 | Statistic, 35 | Table, 36 | Tabs, 37 | Tag, 38 | Timeline, 39 | Tooltip, 40 | Tree, 41 | Alert, 42 | Drawer, 43 | Modal, 44 | Popconfirm, 45 | Progress, 46 | Result, 47 | Skeleton, 48 | Spin 49 | } from 'ant-design-vue' 50 | 51 | export default { 52 | install(app: App) { 53 | app.use(Button) 54 | .use(Divider) 55 | .use(Row) 56 | .use(Col) 57 | .use(Space) 58 | .use(Dropdown) 59 | .use(Menu) 60 | .use(Pagination) 61 | .use(Steps) 62 | .use(AutoComplete) 63 | .use(Cascader) 64 | .use(Checkbox) 65 | .use(DatePicker) 66 | .use(Form) 67 | .use(Input) 68 | .use(InputNumber) 69 | .use(Radio) 70 | .use(Select) 71 | .use(Switch) 72 | .use(TimePicker) 73 | .use(TreeSelect) 74 | .use(Upload) 75 | .use(Avatar) 76 | .use(Badge) 77 | .use(Card) 78 | .use(Collapse) 79 | .use(Descriptions) 80 | .use(Empty) 81 | .use(Image) 82 | .use(List) 83 | .use(Popover) 84 | .use(Statistic) 85 | .use(Table) 86 | .use(Tabs) 87 | .use(Tag) 88 | .use(Timeline) 89 | .use(Tooltip) 90 | .use(Tree) 91 | .use(Alert) 92 | .use(Drawer) 93 | .use(Modal) 94 | .use(Popconfirm) 95 | .use(Progress) 96 | .use(Result) 97 | .use(Skeleton) 98 | .use(Spin) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/components/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import TitleComponent from './TitleComponent/index.vue' 3 | import ImageUpload from "./Upload/Image/ImageUpload.vue"; 4 | import CardBox from './CardBox/index.vue'; 5 | import Search from './Search' 6 | import AMapComponent from './AMapComponent/AMap.vue' 7 | import PathSimplifier from './AMapComponent/PathSimplifier.vue' 8 | import { BasicLayoutPage, BlankLayoutPage, FullPage } from '@/layout' 9 | import ProUpload from './Upload/index.vue' 10 | import Player from './Player/index.vue' 11 | import BatchDropdown from './BatchDropdown/index.vue' 12 | import ConfirmModal from './ConfirmModal/index.vue' 13 | import CheckButton from './CheckButton/CheckButton.vue' 14 | import SelectAMap from './SelectAMap/index.vue' 15 | import MonacoEditor from './MonacoEditor/monacoEditor.vue' 16 | import FormItemValue from './FormItem' 17 | import { TimeSelect } from './Dashboard/components' 18 | import FullCalendar from './FullCalendar/index.vue' 19 | import Image from './Image/index.vue' 20 | 21 | export default { 22 | install(app: App) { 23 | 24 | app.component('TitleComponent', TitleComponent) 25 | .component('ImageUpload', ImageUpload) 26 | .component('CardBox', CardBox) 27 | .component('ProSearch', Search) 28 | .component('BasicLayoutPage', BasicLayoutPage) 29 | .component('BlankLayoutPage', BlankLayoutPage) 30 | .component('FullPage', FullPage) 31 | .component('AMapComponent', AMapComponent) 32 | .component('PathSimplifier', PathSimplifier) 33 | .component('ProUpload', ProUpload) 34 | .component('Player', Player) 35 | .component('BatchDropdown', BatchDropdown) 36 | .component('ConfirmModal',ConfirmModal) 37 | .component('CheckButton',CheckButton) 38 | .component('SelectAMap', SelectAMap) 39 | .component('monaco-editor', MonacoEditor) 40 | .component(TimeSelect.name, TimeSelect) 41 | .component('FullCalendar', FullCalendar) 42 | .component('Image', Image) 43 | 44 | Object.keys(FormItemValue).forEach(key => { 45 | app.component(key, FormItemValue[key]) 46 | }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/directive/formatTime.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import dayjs from 'dayjs' 3 | 4 | function formatTime(app: App) { 5 | app.directive("time-format", { 6 | mounted(el: HTMLElement, bindings) { 7 | const _timeStamps = Number(el.textContent) 8 | el.textContent = !isNaN(_timeStamps) ? dayjs(_timeStamps).format(bindings.value) : el.textContent; 9 | }, 10 | updated(el: HTMLElement, bindings) { 11 | const _timeStamps = Number(el.textContent) 12 | el.textContent = !isNaN(_timeStamps) ? dayjs(_timeStamps).format(bindings.value) : el.textContent; 13 | } 14 | }) 15 | } 16 | 17 | export default formatTime 18 | -------------------------------------------------------------------------------- /src/directive/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import formatTime from './formatTime' 3 | 4 | export default { 5 | install(app: App) { 6 | app.use(formatTime) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useWebSocket'; 2 | -------------------------------------------------------------------------------- /src/hooks/useWebSocket.ts: -------------------------------------------------------------------------------- 1 | import { onBeforeUnmount, ref } from 'vue' 2 | import type { Ref } from 'vue' 3 | import { wsClient } from '@jetlinks-web/core' 4 | import { debounce, isNumber, throttle } from 'lodash-es' 5 | 6 | interface WebSocketOptions { 7 | onMessage?: (data: T) => void 8 | 9 | debounce?: number | boolean 10 | 11 | throttle?: number | boolean 12 | } 13 | 14 | export const useWebSocket = ( 15 | options?: WebSocketOptions 16 | ): { 17 | data: Ref, 18 | send: (id: string, topic: string, parameter?: Record) => void 19 | unSubscribe: () => void 20 | } => { 21 | 22 | const data = ref() 23 | let ws: any = null 24 | 25 | const handleMsg = (msgData: T) => { 26 | data.value = msgData 27 | options?.onMessage?.(msgData) 28 | } 29 | 30 | const debounceMsg = debounce(handleMsg, isNumber(options?.debounce) ? options?.debounce : 300) 31 | 32 | const throttleMsg = throttle(handleMsg, isNumber(options?.throttle) ? options?.throttle : 300) 33 | /** 34 | * 消息发送 35 | * @param id {String} 36 | * @param topic {String} 37 | * @param parameter {Object} 38 | */ 39 | const send = (id: string, topic: string, parameter?: Record) => { 40 | ws = wsClient.getWebSocket(id, topic, parameter) 41 | 42 | if (options?.throttle) { 43 | ws.subscribe(throttleMsg) 44 | } else if (options?.debounce) { 45 | ws.subscribe(debounceMsg) 46 | } else { 47 | ws.subscribe((msgData: any) => handleMsg(msgData)) 48 | } 49 | } 50 | 51 | const unSubscribe = () => { 52 | ws?.unsubscribe?.() 53 | } 54 | 55 | onBeforeUnmount(() => { 56 | unSubscribe() 57 | }) 58 | 59 | return { 60 | data, 61 | send, 62 | unSubscribe 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/layout/BlankLayoutPage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | 24 | 27 | -------------------------------------------------------------------------------- /src/layout/FullPage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 63 | 64 | 74 | -------------------------------------------------------------------------------- /src/layout/components/Language.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 29 | 30 | 33 | -------------------------------------------------------------------------------- /src/layout/components/NoticeTab.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 69 | -------------------------------------------------------------------------------- /src/layout/components/Resource.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/layout/components/User.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 57 | 58 | 67 | -------------------------------------------------------------------------------- /src/layout/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as User } from './User.vue' 2 | export { default as Notice } from './Notice.vue' 3 | export { default as Language } from './Language.vue' 4 | export { default as Resource } from './Resource.vue' 5 | -------------------------------------------------------------------------------- /src/layout/index.ts: -------------------------------------------------------------------------------- 1 | export { default as BlankLayoutPage } from './BlankLayoutPage.vue' 2 | export { default as BasicLayoutPage } from './BasicLayoutPage.vue' 3 | export { default as Iframe } from './Iframe.vue' 4 | export { default as FullPage } from './FullPage.vue' 5 | -------------------------------------------------------------------------------- /src/locales/index.ts: -------------------------------------------------------------------------------- 1 | import { createI18n } from 'vue-i18n' 2 | import type { Locale } from 'vue-i18n'; 3 | import {langKey} from "@/utils/consts"; 4 | 5 | const mainModules = import.meta.glob('./lang/*.json', {eager: true}) 6 | const modules = import.meta.glob('../modules/*/locales/lang/*.json', {eager: true}); 7 | 8 | const allModules = Object.assign({}, mainModules, modules) 9 | 10 | function loadLocalesMapFromDir(regexp: RegExp, modules: Record) { 11 | const localesRaw: Record Promise>> = {}; 12 | for (const path in modules) { 13 | const match = path.match(regexp); 14 | if (match) { 15 | const [_, locale] = match; 16 | if (locale) { 17 | if (!localesRaw[locale]) { 18 | localesRaw[locale] = {}; 19 | } 20 | if (modules[path]) { 21 | localesRaw[locale] = Object.assign(localesRaw[locale], modules[path]?.default); 22 | } 23 | } 24 | } 25 | } 26 | // Convert raw locale data into async import functions 27 | 28 | return localesRaw; 29 | } 30 | const messages = loadLocalesMapFromDir(/([^/]*)\.json$/, allModules); 31 | 32 | const language = (navigator.language || 'en').toLocaleLowerCase() // 这是获取浏览器的语言 33 | 34 | const i18n = createI18n({ 35 | legacy: false, 36 | silentTranslationWarn: true, 37 | locale: localStorage.getItem(langKey) || language.split('-')[0] || 'en', 38 | fallbackLocale: language, 39 | messages, 40 | }) 41 | 42 | export default i18n 43 | -------------------------------------------------------------------------------- /src/locales/loader.ts: -------------------------------------------------------------------------------- 1 | import type {Locale} from "vue-i18n"; 2 | 3 | const mainModules = import.meta.glob('./lang/*.json', {eager: true}) 4 | const langModules = import.meta.glob('../modules/*/locales/lang/*.json', {eager: true}) 5 | 6 | export const getLang = async () => { 7 | const modulesMap = {} 8 | const modulesFiles = import.meta.glob('../modules/*/locales/lang/*.json', {eager: true}) 9 | 10 | return Object.assign(modulesMap, modulesFiles) 11 | } 12 | 13 | export async function loadLocalesMapFromDir() { 14 | 15 | const modules = Object.assign({}, mainModules, langModules) 16 | const localesRaw: Record> = {}; 17 | for (const path in modules) { 18 | const match = path.match(/([^/]*)\.json$/); 19 | if (match) { 20 | const [_, locale] = match; 21 | if (locale) { 22 | if (!localesRaw[locale]) { 23 | localesRaw[locale] = {}; 24 | } 25 | if (modules[path]) { 26 | localesRaw[locale] = Object.assign(localesRaw[locale], modules[path]?.default); 27 | } 28 | } 29 | } 30 | } 31 | return localesRaw 32 | } 33 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | import pinia from '@/store' 5 | import i18n from '@/locales' 6 | import JetLinksComponents from '@jetlinks-web/components' 7 | import components from './components' 8 | import directive from '@/directive' 9 | import dayjs from 'dayjs' 10 | import { loadMicroApp, initAxios } from '@/package' 11 | import andtv from 'ant-design-vue' 12 | 13 | import 'ant-design-vue/dist/antd.variable.min.css' 14 | import 'vue3-json-viewer/dist/index.css' 15 | import '@jetlinks-web/components/es/style/index.less' 16 | import 'xgplayer/dist/index.min.css' 17 | import '@/style/global.less' 18 | import 'dayjs/locale/zh-cn' 19 | import microApp from '@micro-zoe/micro-app' 20 | 21 | dayjs.locale('zh-cn') 22 | 23 | initAxios() 24 | loadMicroApp() 25 | 26 | if (import.meta.env.VITE_MICRO_APP) { 27 | microApp.start({ 28 | iframe: true 29 | }) 30 | } 31 | 32 | // 👇 用 async 包装启动逻辑 33 | async function bootstrap() { 34 | const router = await import('@/router').then(mod => mod.default) 35 | 36 | const app = createApp(App) 37 | 38 | app.provide('appInstance', app) 39 | .use(pinia) 40 | .use(router) // ✅ 异步引入后的 router 41 | .use(directive) 42 | .use(andtv) 43 | .use(i18n) 44 | .use(JetLinksComponents) 45 | .use(components) 46 | .mount('#app') 47 | } 48 | 49 | bootstrap() 50 | -------------------------------------------------------------------------------- /src/router/basic.ts: -------------------------------------------------------------------------------- 1 | import type { RouteRecordRaw } from 'vue-router' 2 | 3 | export const USER_CENTER_ROUTE: RouteRecordRaw = { 4 | path: "/account", 5 | name: "Account", 6 | redirect: "/account/center", 7 | component: () => import("@/layout/BasicLayoutPage.vue"), 8 | meta: { 9 | title: "个人中心", 10 | hideInMenu: true, 11 | }, 12 | children: [ 13 | { 14 | path: "/account/center", 15 | name: "account/center", 16 | meta: { 17 | title: "基本设置", 18 | icon: "", 19 | hideInMenu: false, 20 | }, 21 | component: () => import("@/views/account/center/index.vue"), 22 | }, 23 | // { 24 | // path: AccountCenterBindPath, 25 | // name: "account/center/bind", 26 | // component: () => import("@/views/account/center/bind/index.vue"), 27 | // }, 28 | ], 29 | }; 30 | 31 | export const LOGIN_ROUTE: RouteRecordRaw = { 32 | path: "/login", 33 | name: "Login", 34 | // @ts-ignore 35 | component: () => import("@/views/login/index.vue"), 36 | meta: { 37 | title: "登录页", 38 | }, 39 | }; 40 | 41 | export const NOT_FIND_ROUTE: RouteRecordRaw = { 42 | path: "/:pathMatch(.*)", 43 | name: "error", 44 | component: () => import("@/views/Error/404.vue"), 45 | meta: { 46 | title: "404", 47 | }, 48 | }; 49 | 50 | export const EDGE_TOKEN_ROUTE: RouteRecordRaw = { 51 | path: '/edge/token/:id', 52 | meta: { 53 | title: 'token失效' 54 | }, 55 | component: () => import('@/views/TokenJump/index.vue') 56 | }; 57 | 58 | export const AccountCenterBind: RouteRecordRaw = { 59 | path: '/account/center/bind', 60 | meta: { 61 | title: '第三方' 62 | }, 63 | component: () => import("@/views/account/center/bind/index.vue"), 64 | } 65 | 66 | export const OAuth2: RouteRecordRaw = { 67 | path: '/oauth', 68 | meta: { 69 | title: '授权页' 70 | }, 71 | component: () => import('@/views/oauth/index.vue') 72 | } 73 | 74 | export const INIT_HOME: RouteRecordRaw = { 75 | path: '/init-home', 76 | name: 'init-home', 77 | component: () => import("@/views/init-home/index.vue"), 78 | meta: { 79 | title: "初始化", 80 | }, 81 | } 82 | 83 | export const OAuthWechat: RouteRecordRaw = { 84 | path: '/oauth/wechat', 85 | meta: { 86 | title: '微信授权页' 87 | }, 88 | component: () => import('@/views/oauth/WeChat.vue') 89 | } 90 | 91 | export const AUTHORIZE_ROUTE: RouteRecordRaw = { 92 | path: '/share/authorize', 93 | name: 'Authorize', 94 | component: () => import('@/views/share/authorize/index.vue'), 95 | meta: { 96 | title: '授权认证' 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/router/extraMenu.ts: -------------------------------------------------------------------------------- 1 | import {modules} from '@/utils/modules' 2 | 3 | export const getExtraRouters = async () => { 4 | const extraMenu = { 5 | 6 | } 7 | 8 | const modulesFiles = modules() 9 | Object.values(modulesFiles).forEach(item => { 10 | const routes = item.default.getExtraRoutesMap?.() || [] 11 | Object.assign(extraMenu, routes) 12 | }) 13 | return extraMenu 14 | } 15 | -------------------------------------------------------------------------------- /src/router/globModules.ts: -------------------------------------------------------------------------------- 1 | import {modules} from '@/utils/modules' 2 | 3 | const routerModules = import.meta.glob('../views/**/index.vue') 4 | 5 | export const getAsyncRoutesMap = () => { 6 | const modulesMap: Record = {} 7 | Object.keys(routerModules).forEach(item => { 8 | const code = item.replace('../views/', '').replace('/index.vue', '') 9 | modulesMap[code] = routerModules[item] 10 | }) 11 | 12 | return modulesMap 13 | } 14 | 15 | 16 | export const getGlobModules = async () => { 17 | const asyncRoutesMap = getAsyncRoutesMap() 18 | 19 | const modulesFiles = modules() 20 | Object.values(modulesFiles).forEach(item => { 21 | const routes = item.default.getAsyncRoutesMap?.() || [] 22 | Object.assign(asyncRoutesMap, routes) 23 | }) 24 | 25 | return { 26 | ...asyncRoutesMap 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/router/menu.ts: -------------------------------------------------------------------------------- 1 | export const NotificationSubscriptionCode = 'message-subscribe' 2 | -------------------------------------------------------------------------------- /src/store/application.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | import {uiList} from "@/api/application"; 4 | import {OpenMicroApp} from "@/utils/consts"; 5 | 6 | type ApplicationItemType = { 7 | id: string 8 | path: string 9 | name: string 10 | } 11 | 12 | export const useApplication = defineStore('application', () => { 13 | const appList = ref>([]) 14 | let lock = false 15 | 16 | const queryApplication = async () => { 17 | if (lock || OpenMicroApp === 'false') return 18 | 19 | const resp = await uiList() 20 | if (resp.success) { 21 | appList.value = resp.result 22 | lock = true 23 | // appList.value = [{ 24 | // id: 'device-manager', 25 | // path: 'http://localhost:9100/' 26 | // }] 27 | } 28 | } 29 | 30 | 31 | const findAppById = (appId:string) => appList.value.find((item: any) => item.id === appId) 32 | 33 | return { 34 | appList, 35 | queryApplication, 36 | findAppById 37 | } 38 | }) 39 | -------------------------------------------------------------------------------- /src/store/auth.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | import { isArray } from 'lodash-es' 4 | import { handleAuthMenu } from '@/utils' 5 | 6 | export const useAuthStore = defineStore('auth', () => { 7 | const permissions = ref>({}) 8 | 9 | const setPermission = (code: string, buttons: string[]) => { 10 | permissions.value[code] = buttons 11 | } 12 | 13 | const cleanPermission = () => { 14 | permissions.value = {} 15 | } 16 | 17 | const getPermission = (code: string): string[] => { 18 | if (code) { 19 | return permissions.value[code] 20 | } 21 | 22 | return [] 23 | } 24 | 25 | const hasPermission = (code: string | string[]): boolean => { 26 | const codes = isArray(code) ? code : [code] 27 | return codes.some((key) => { 28 | const [menuCode, button] = key.split(':') 29 | return !!getPermission(menuCode)?.includes(button) 30 | }) 31 | } 32 | 33 | const handlePermission = (data: any) => { 34 | cleanPermission() 35 | handleAuthMenu(data, setPermission) 36 | } 37 | 38 | return { 39 | permissions, 40 | getPermission, 41 | setPermission, 42 | cleanPermission, 43 | handlePermission, 44 | hasPermission 45 | } 46 | }) 47 | -------------------------------------------------------------------------------- /src/store/department.ts: -------------------------------------------------------------------------------- 1 | 2 | import { defineStore } from "pinia"; 3 | 4 | type DepartmentStateType = { 5 | productId?: string[]; 6 | optType: string | undefined; 7 | crossPageKeys: string[]; 8 | changedApis: any; 9 | } 10 | 11 | export const useDepartmentStore = defineStore({ 12 | id: 'department', 13 | state: (): DepartmentStateType => ({ 14 | productId: undefined, 15 | // 设备资产分配弹窗操作类型: 16 | // 1. optType === 'handle': 手动点击资产分配按钮; 17 | // 2. optType === ': 产品资产分配后, 自动弹出设备资产分配 18 | optType: '', 19 | crossPageKeys: [], // 表格跨页多选的keys 20 | changedApis: {}, 21 | }), 22 | actions: { 23 | setProductId(value?: string[]) { 24 | this.productId = value; 25 | }, 26 | setType(value: string | undefined) { 27 | this.optType = value; 28 | }, 29 | setSelectedKeys(value: string[], type?: string) { 30 | // 分页保留选中项 31 | this.crossPageKeys = type === 'concat' ? [...new Set([...this.crossPageKeys, ...value])] : value; 32 | }, 33 | setChangedApis(value: any) { 34 | this.changedApis = { ...this.changedApis, ...value }; 35 | } 36 | } 37 | }) -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia'; 2 | 3 | export * from './auth' 4 | export * from './user' 5 | export * from './menu' 6 | export * from './system' 7 | export * from './application' 8 | 9 | const pinia = createPinia(); 10 | 11 | export default pinia; 12 | -------------------------------------------------------------------------------- /src/store/user.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { detail } from '@/api/system/user' 3 | import { tabList } from "@/views/account/center/data"; 4 | import {LocalStore} from "@jetlinks-web/utils/src/storage"; 5 | 6 | type UserInfo = { 7 | name: string 8 | icon: string 9 | } 10 | 11 | export const useUserStore = defineStore('user', () => { 12 | const userInfo = ref>({}) 13 | const isAdmin = ref(false) 14 | const isApplicationUser = ref(false) 15 | const tabKey = ref(tabList?.[0]?.key || 'HomeView') // 个人中心的tabKey, 16 | const other = { 17 | tabKey: '' // 站内信的tabkey 18 | } 19 | const alarmUpdateCount = ref(0) 20 | /** 21 | * 设置用户信息 22 | * @param data 23 | */ 24 | const setUserInfo = (data: Partial) => { 25 | userInfo.value = data 26 | } 27 | 28 | /** 29 | * 获取用户信息 30 | */ 31 | const getUserInfo = async () => { 32 | const resp = await detail() 33 | if (resp.success) { 34 | setUserInfo(resp.result) 35 | isAdmin.value = resp.result.username === 'admin' 36 | isApplicationUser.value = resp.result.type?.id === 'application' 37 | LocalStore.set('username', resp.result?.username) 38 | } 39 | } 40 | const updateAlarm = () => { 41 | alarmUpdateCount.value += 1 42 | } 43 | 44 | return { 45 | tabKey, 46 | other, 47 | userInfo, 48 | alarmUpdateCount, 49 | isAdmin, 50 | isApplicationUser, 51 | getUserInfo, 52 | setUserInfo, 53 | updateAlarm 54 | } 55 | }) 56 | 57 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: AliRegular; 3 | src: url("/fonts/AlibabaPuHuiTi-2-55-Regular.ttf"); 4 | } 5 | 6 | body { 7 | font-family: 'AliRegular' !important; 8 | } 9 | -------------------------------------------------------------------------------- /src/style/comm.less: -------------------------------------------------------------------------------- 1 | @set: { 2 | 0: #ffffff; 3 | 50: #F8F9FA; 4 | 200: #EFF0F1; 5 | 300: #E4E6E7; 6 | 400: #C3C7CB; 7 | 500: #8D9399; 8 | 600: #646C73; 9 | 900: #1F2429; 10 | } 11 | 12 | each(@set, { 13 | .text-color-@{key} { 14 | color: @value; 15 | } 16 | .bg-color-@{key} { 17 | background-color: @value; 18 | } 19 | .border-color-@{key} { 20 | border-color: @value; 21 | } 22 | }) 23 | 24 | -------------------------------------------------------------------------------- /src/style/font.less: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: AliRegular; 3 | src: url("/fonts/AlibabaPuHuiTi-2-55-Regular.ttf"); 4 | } 5 | 6 | body { 7 | font-family: 'AliRegular' !important; 8 | } 9 | 10 | .fc-900 { 11 | color: @font-gray-900; 12 | } 13 | .fc-600 { 14 | color: @font-gray-600; 15 | } 16 | .fc-500 { 17 | color: @font-gray-500; 18 | } 19 | .fc-400 { 20 | color: @font-gray-400; 21 | } 22 | .fc-300 { 23 | color: @font-gray-300; 24 | } 25 | .fc-200 { 26 | color: @font-gray-200; 27 | } 28 | .fc-50 { 29 | color: @font-gray-50; 30 | } 31 | .fc-0 { 32 | color: @font-gray-0; 33 | } 34 | 35 | .fw-700 { 36 | font-weight: 700; 37 | } 38 | 39 | .fw-b { 40 | font-weight: bold; 41 | } 42 | .ta-c { 43 | text-align: center; 44 | } 45 | -------------------------------------------------------------------------------- /src/style/global.less: -------------------------------------------------------------------------------- 1 | @import "./font.less"; 2 | @import "./scrollbar.less"; 3 | @import "./comm.less"; 4 | @import "./layout.less"; 5 | -------------------------------------------------------------------------------- /src/style/scrollbar.less: -------------------------------------------------------------------------------- 1 | /* 自定义滚动条整体样式 */ 2 | ::-webkit-scrollbar { 3 | width: 6px; /* 对于垂直滚动条,设置宽度 */ 4 | height: 10px; /* 对于水平滚动条,设置高度 */ 5 | 6 | } 7 | 8 | /* 自定义滚动条轨道样式 */ 9 | ::-webkit-scrollbar-track { 10 | background: transparent; /* 背景色 */ 11 | } 12 | 13 | /* 自定义滚动条滑块样式 */ 14 | ::-webkit-scrollbar-thumb { 15 | background: #E7E9EF; /* 滑块颜色 */ 16 | border-radius: 5px; 17 | } 18 | 19 | /* 当滑块悬停或活动时的样式 */ 20 | ::-webkit-scrollbar-thumb:hover { 21 | background: #E7E9EF; /* 滑块悬停颜色 */ 22 | } 23 | 24 | /* 针对Select下拉菜单的滚动条的样式 */ 25 | //.rc-virtual-list-scrollbar { 26 | // scrollbar-color: #d8d8d8 #fafafa; /* 滚动条的颜色 */ 27 | // width: 5px !important;/* 滚动条的宽度 */ 28 | //} 29 | -------------------------------------------------------------------------------- /src/style/variable.less: -------------------------------------------------------------------------------- 1 | @import "ant-design-vue/es/style/themes/index.less"; 2 | 3 | .ellipsisFn(@num: 1, @width: 100%) { 4 | display: -webkit-box; 5 | max-width: @width; 6 | overflow: hidden; 7 | /*! autoprefixer: off */ 8 | -webkit-box-orient: vertical; 9 | /*! autoprefixer: on */ 10 | -webkit-line-clamp: @num; 11 | } 12 | 13 | @font-gray-900: #1F2429; 14 | @font-gray-600: #646C73; 15 | @font-gray-500: #8D9399; 16 | @font-gray-400: #C3C7CB; 17 | @font-gray-300: #E4E6E7; 18 | @font-gray-200: #EFF0F1; 19 | @font-gray-50: #F8F9FA; 20 | @font-gray-0: #fffff; 21 | @border-base-color: #D9D9D9; 22 | -------------------------------------------------------------------------------- /src/utils/consts.ts: -------------------------------------------------------------------------------- 1 | export const USER_CENTER_MENU_CODE = 'account-center' 2 | export const USER_CENTER_MENU_BUTTON_CODE = 'user-center-passwd-update' 3 | export const messageSubscribe = 'message-subscribe' 4 | 5 | export const OWNER_KEY = 'iot' 6 | 7 | export const default_app_id = 'authentication-service' 8 | 9 | export const URL_TOKEN_KET = import.meta.env.VITE_TOKEN_KEY.replace(/-/g, '_') 10 | 11 | export const protocolList = [ 12 | { label: 'OPC_UA', value: 'OPC_UA', alias: 'opc-ua' }, 13 | { label: 'MODBUS_TCP', value: 'MODBUS_TCP', alias: 'Modbus/TCP' }, 14 | { label: 'COLLECTOR_GATEWAY', value: 'COLLECTOR_GATEWAY', alias: 'GATEWAY' }, 15 | { label: 'S7', value: 'snap7', alias: 'snap7' }, 16 | { label: 'IEC104', value: 'iec104', alias: 'IEC104' }, 17 | { label: 'BACNetIp', value: 'BACNetIp', alias: 'BACNet/IP' } 18 | ] 19 | 20 | export const langKey = 'Accept-Language' 21 | 22 | 23 | //规则编排国际化LocalStorage的key 24 | export const ruleEditorKey = 'editor-language' 25 | 26 | export const MODULES_KEYS: string[] = import.meta.env.VITE_BUILD_MODULES || []; 27 | 28 | export const isSubApp = (window as any).__MICRO_APP_ENVIRONMENT__ 29 | 30 | export const OpenMicroApp = import.meta.env.VITE_MICRO_APP 31 | -------------------------------------------------------------------------------- /src/utils/context.ts: -------------------------------------------------------------------------------- 1 | import { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from "axios"; 2 | 3 | export interface ContextOptions { 4 | filterUrl?: string[]; 5 | handleRequest?: ( 6 | config: InternalAxiosRequestConfig 7 | ) => InternalAxiosRequestConfig; 8 | handleResponse?: (response: AxiosResponse) => AxiosResponse; 9 | errorHandler?: (error: AxiosError) => void; 10 | loginInvalid?: () => void; 11 | } 12 | 13 | // 公用上下文 14 | export let context: ContextOptions = { 15 | filterUrl: [], 16 | handleRequest: undefined, 17 | handleResponse: undefined, 18 | errorHandler: undefined, 19 | }; 20 | 21 | export const initRequest = (func: () => ContextOptions) => { 22 | context = func(); 23 | }; 24 | -------------------------------------------------------------------------------- /src/utils/document.ts: -------------------------------------------------------------------------------- 1 | export const createScript = (src: string) => { 2 | return new Promise((resolve) => { 3 | const script = document.createElement('script') 4 | script.onload = () => { 5 | resolve(true) 6 | } 7 | script.setAttribute('type', 'text/javascript') 8 | script.setAttribute('src', src) 9 | document.body.appendChild(script) 10 | }) 11 | } -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './menu' 2 | export * from './comm' 3 | export * from './validate' 4 | export * from './regular' 5 | export * from './document' 6 | export * from './encodeQuery' 7 | export * from './utils' 8 | export * from './modules' 9 | -------------------------------------------------------------------------------- /src/utils/modules-loader.ts: -------------------------------------------------------------------------------- 1 | import { MODULES_KEYS } from '@/utils/consts' 2 | 3 | // const MODULES_KEYS = ['device-manager-ui'] 4 | 5 | export const getTargetModule = async (modulesFiles: Record, regexp: RegExp) => { 6 | const targetModules: Record = {} 7 | for (const path in modulesFiles) { 8 | const match = path.match(regexp); 9 | const moduleName = match?.[1]; 10 | if (MODULES_KEYS.length > 0 && moduleName && !MODULES_KEYS.includes(moduleName)) { 11 | continue; 12 | } 13 | targetModules[path] = modulesFiles[path]() 14 | } 15 | 16 | return targetModules 17 | } 18 | -------------------------------------------------------------------------------- /src/utils/modules.ts: -------------------------------------------------------------------------------- 1 | import {getTargetModule} from "./modules-loader"; 2 | 3 | export const modules = () => { 4 | const modulesMap = {} 5 | // const modulesFiles = await getTargetModule(import.meta.glob('../modules/*/index.ts'), /..\/modules\/(.*?)\/index\.ts/) 6 | const modulesFiles = import.meta.glob('../modules/*/index.ts', {eager: true}) 7 | return Object.assign(modulesMap, modulesFiles) 8 | } 9 | 10 | export const getModulesMenu = () => { 11 | // const modulesFiles = await getTargetModule(import.meta.glob('../modules/*/baseMenu.ts'), /..\/modules\/(.*?)\/baseMenu\.ts/) 12 | const modulesFiles = import.meta.glob('../modules/*/baseMenu.ts', {eager: true}) 13 | const menus: any[] = [] 14 | 15 | Object.values(modulesFiles).forEach((item: any) => { 16 | menus.push(...item.default?.()) 17 | }) 18 | 19 | return menus 20 | } 21 | -------------------------------------------------------------------------------- /src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | // 是否不是community版本 2 | import {getToken} from "@jetlinks-web/utils"; 3 | import { useSystemStore } from '@/store' 4 | 5 | export const isNoCommunity = !(localStorage.getItem('version_code') === 'community'); 6 | 7 | export const openEdgeUrl = (id: string) => { 8 | const systemStore = useSystemStore() 9 | 10 | window.open(`${systemStore.systemInfo.paths['api-path']}/#/login?token=${getToken()}&thingId=${id}&deviceId=${id}&terminal=cloud-pc&thingType=device`) 11 | } 12 | -------------------------------------------------------------------------------- /src/utils/validate.ts: -------------------------------------------------------------------------------- 1 | import { regIPv6,regIpv4 } from './regular' 2 | /** 3 | * 座机号+手机号校验 4 | * @param value 5 | * @returns {boolean} 6 | */ 7 | export const phoneRegEx = (value: string) => { 8 | const phone = new RegExp('^(((\\+86)|(\\+86-))|((86)|(86\\-))|((0086)|(0086\\-)))?1[3|5|7|8|9]\\d{9}$') 9 | const mobile = /(0[0-9]{2,3})([2-9][0-9]{6,7})+([0-9]{8,11})?$/ 10 | return phone.test(value) || mobile.test(value) 11 | } 12 | /** 13 | * 密码强度校验 必须至少包含大小写英文和数字 14 | * @param value 15 | * @returns {boolean} 16 | */ 17 | export const passwordRegEx = (value: string) => { 18 | const password = new RegExp(/^\S*(?=\S{8,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/) 19 | return password.test(value) 20 | } 21 | /** 22 | * 判断是否为正确的IP地址 23 | */ 24 | export const testIP = (value: string) => { 25 | const ip = 26 | /^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/; 27 | return ip.test(value); 28 | }; 29 | /** 30 | * 判断是否为Ipv4和Ipv6的地址 31 | */ 32 | export const testIpv4_6 = (value:string) => { 33 | return regIpv4.test(value) || regIPv6.test(value) 34 | } -------------------------------------------------------------------------------- /src/views/Error/404.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /src/views/TokenJump/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 39 | 40 | 56 | -------------------------------------------------------------------------------- /src/views/account/center/components/HomeView/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 57 | 58 | 76 | -------------------------------------------------------------------------------- /src/views/account/center/components/Subscribe/components/Wechat.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 48 | -------------------------------------------------------------------------------- /src/views/account/center/data.ts: -------------------------------------------------------------------------------- 1 | import i18n from "@/locales"; 2 | 3 | type KeyType = 'HomeView' | 'BindThirdAccount' | 'Subscribe' | 'StationMessage'; 4 | export const tabList: { key: KeyType; title: string }[] = [ 5 | { 6 | key: 'HomeView', 7 | title: i18n.global.t('center.data.756829-2'), 8 | }, 9 | { 10 | key: 'BindThirdAccount', 11 | title: i18n.global.t('center.data.756829-3'), 12 | }, 13 | { 14 | key: 'Subscribe', 15 | title: i18n.global.t('center.data.756829-0'), 16 | }, 17 | { 18 | key: 'StationMessage', 19 | title: i18n.global.t('center.data.756829-1'), 20 | }, 21 | ] 22 | -------------------------------------------------------------------------------- /src/views/demo/index.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 56 | 57 | 60 | -------------------------------------------------------------------------------- /src/views/init-home/Basic/components/upload/typing.ts: -------------------------------------------------------------------------------- 1 | // 上传相关信息接口 2 | export interface UploadInfoType { 3 | // 上传提示 4 | logoTip: object, 5 | icoTip: object, 6 | backgroundTip: object, 7 | // 上传的地址 8 | action: string, 9 | headers: object, 10 | // 是否展示uplaodList 11 | showUploadList: boolean, 12 | // 是否支持拖拽 13 | drag: true, 14 | // 上传接受的类型 15 | imageType: string, 16 | icoType: string, 17 | 18 | //验证图片是否在范围内 19 | isImageLessSize(file: File, size: number): boolean, 20 | 21 | // 验证是否是图片类型 22 | isImageType(file: File): boolean, 23 | 24 | // 验证是否时icon类型 25 | isIcoType(file: File): boolean, 26 | 27 | // 上传change事件 28 | changUpload(info: any, msg: string): void, 29 | 30 | // logo上传change事件 31 | changeLogoUpload(info): void, 32 | 33 | // 浏览器页签上传change事件 34 | changeIcoUpload(info): void, 35 | 36 | // 背景图片上传change事件 37 | changeBackgroundUpload(info): void, 38 | 39 | // logo 上传验证 40 | isLogoImage(file: File): boolean, 41 | 42 | // icon 上传验证 43 | isIcoImage(file: File): boolean, 44 | 45 | // 背景图片上传验证 46 | isBackground(file: File): boolean 47 | } 48 | 49 | // 接收参数类型 50 | export interface UploadPropsType { 51 | type: 'logo' | 'ico' | 'background' 52 | imgSrc: string 53 | height: string 54 | width: string 55 | } -------------------------------------------------------------------------------- /src/views/init-home/Basic/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 22 | 25 | -------------------------------------------------------------------------------- /src/views/init-home/data/baseMenu.ts: -------------------------------------------------------------------------------- 1 | import { 2 | USER_CENTER_MENU_BUTTON_CODE, 3 | USER_CENTER_MENU_CODE 4 | } from '@/utils/consts' 5 | 6 | export const USER_CENTER_MENU_DATA = { 7 | id: '19a1f2c763e1231f1e1', 8 | accessSupport: {value: 'unsupported', label: '不支持'}, 9 | supportDataAccess: false, 10 | code: USER_CENTER_MENU_CODE, 11 | name: '个人中心', 12 | i18nMessages: { 13 | name: { 14 | zh_CN: '个人中心', 15 | en_US: 'User Center', 16 | en: 'User Center' 17 | } 18 | }, 19 | url: '/account/center', 20 | sortIndex: 9999, 21 | granted: true, 22 | owner: 'iot', 23 | options: { 24 | show: true, 25 | }, 26 | permissions: [ 27 | { 28 | permission: 'system_config', 29 | actions: ['query'], 30 | }, 31 | ], 32 | buttons: [ 33 | { 34 | id: 'view', 35 | name: '查看', 36 | i18nMessages: { 37 | zh_CN: "查看", 38 | en_US: "View", 39 | en: "View" 40 | }, 41 | permissions: [] 42 | }, 43 | { 44 | id: USER_CENTER_MENU_BUTTON_CODE, 45 | name: '修改密码', 46 | i18nMessages: { 47 | zh_CN: "修改密码", 48 | en_US: "Update Password", 49 | en: "Update Password" 50 | }, 51 | permissions: [ 52 | { 53 | permission: 'user', 54 | actions: ['update-self-pwd'] 55 | }, 56 | { 57 | permission: 'system_config', 58 | actions: ['query'], 59 | }, 60 | ] 61 | } 62 | ] 63 | } 64 | 65 | export default [ 66 | 67 | ]; 68 | -------------------------------------------------------------------------------- /src/views/init-home/data/index.ts: -------------------------------------------------------------------------------- 1 | import proMenu from './baseMenu'; 2 | import {getModulesMenu} from '@/utils/modules' 3 | /** 4 | * 合并菜单数据 5 | * @param tree1 基础菜单数据 6 | * @param tree2 云端菜单数据 7 | * @returns 合并后的菜单数据 8 | */ 9 | export const mergeTrees = (tree1: any[], tree2: any[]) => { 10 | const map = new Map(); 11 | 12 | function addToMap(nodes: any[]) { 13 | for (const node of nodes) { 14 | if (!map.has(node.code)) { 15 | map.set(node.code, { ...node, children: [] }); 16 | } 17 | const existing = map.get(node.code); 18 | existing.children = mergeTrees(existing.children || [], node.children || []);; 19 | } 20 | } 21 | 22 | addToMap(tree1); 23 | addToMap(tree2); 24 | 25 | return Array.from(map.values()); 26 | } 27 | 28 | export const handleMenuOptions = (menus: any[], p: { id: string, name: string}): any[] => menus.map(item => ({ 29 | ...item, 30 | children: item.children ? handleMenuOptions(item.children, p) : undefined, 31 | options: { appName: p.id || p.name, ...item.options } 32 | })) 33 | 34 | const BaseMenuFn = async () => { 35 | const modules = await getModulesMenu() 36 | let baseModuleMenu: any = [...proMenu] 37 | baseModuleMenu = mergeTrees(baseModuleMenu, modules) 38 | return baseModuleMenu 39 | } 40 | 41 | export default BaseMenuFn 42 | -------------------------------------------------------------------------------- /src/views/init-home/data/interface.ts: -------------------------------------------------------------------------------- 1 | import type { UploadChangeParam, UploadProps } from 'ant-design-vue'; 2 | 3 | /**基本信息表单 */ 4 | export interface formState { 5 | title: string; // 系统名称 6 | headerTheme: string; // 主题色 7 | showRecordNumber: boolean; //是否显示备案号 8 | recordNumber: string; //备案号 9 | basePath: string; // 系统后台访问的URL 10 | logo: string; // 系统logo 11 | ico: string; // 浏览器页签 12 | background:string; //登录背景 13 | } 14 | 15 | /** 16 | * 图片上传表单 17 | */ 18 | export interface logoState { 19 | logoValue: string; 20 | logoLoading: boolean; 21 | backLoading: boolean; 22 | iconLoading: boolean; 23 | inLogo: boolean; 24 | inIcon: boolean; 25 | inBackground: boolean; 26 | iconValue: string; 27 | backValue: string; 28 | backSize: number; 29 | logoSize: number; 30 | imageTypes:Array; 31 | iconTypes: Array, 32 | beforeLogoUpload:(file: UploadProps['beforeUpload']) => void 33 | handleChangeLogo:(info: UploadChangeParam ) => void 34 | beforeBackUpload:(file: UploadProps['beforeUpload']) => void 35 | changeBackUpload:(info: UploadChangeParam ) => void 36 | beforeIconUpload:(file: UploadProps['beforeUpload']) => void 37 | changeIconUpload:(info: UploadChangeParam ) => void 38 | } 39 | -------------------------------------------------------------------------------- /src/views/login/index.vue: -------------------------------------------------------------------------------- 1 | 27 | 62 | 63 | 97 | -------------------------------------------------------------------------------- /src/views/login/remember.vue: -------------------------------------------------------------------------------- 1 | 4 | 18 | -------------------------------------------------------------------------------- /src/views/login/util.ts: -------------------------------------------------------------------------------- 1 | import standalone from '@/assets/apply/internal-standalone.png' 2 | import dingtalk from '@/assets/bindPage/dingtalk.png' 3 | import wechat from '@/assets/bindPage/wechat-webapp.png' 4 | import thirdParty from '@/assets/apply/third-party.png' 5 | import wechatMiniapp from '@/assets/apply/wechat-miniapp.png' 6 | 7 | export const rules = { 8 | username: [ 9 | { 10 | validator(_: any, value: string) { 11 | if (!value) { 12 | return Promise.reject('请输入账号!') 13 | } 14 | return Promise.resolve() 15 | }, 16 | trigger: 'change' 17 | } 18 | ], 19 | password: [ 20 | { 21 | validator(_: any, value: string) { 22 | if (!value) { 23 | return Promise.reject('请输入密码!') 24 | } 25 | return Promise.resolve() 26 | }, 27 | trigger: 'change' 28 | } 29 | ], 30 | verifyCode: [ 31 | { 32 | validator(_: any, value: string) { 33 | if (!value) { 34 | return Promise.reject('请输入验证码!') 35 | } 36 | return Promise.resolve() 37 | }, 38 | trigger: 'change' 39 | } 40 | ] 41 | } 42 | 43 | export const iconMap = new Map(); 44 | iconMap.set('dingtalk-ent-app', dingtalk); 45 | iconMap.set('wechat-webapp', wechat); 46 | iconMap.set('internal-standalone', standalone); 47 | iconMap.set('third-party', thirdParty); 48 | iconMap.set('wechat-miniapp', wechatMiniapp); 49 | 50 | -------------------------------------------------------------------------------- /src/views/mirco/SubAppRedirect/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 7 | 8 | 26 | -------------------------------------------------------------------------------- /src/views/oauth/WeChat.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 21 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare module "*.vue" { 3 | import { DefineComponent } from "vue" 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } 7 | 8 | declare module "@jetlinks-web/components" 9 | declare module "vue3-json-viewer" 10 | declare module "event-source-polyfill" 11 | -------------------------------------------------------------------------------- /tests/e2e/example.spec.ts: -------------------------------------------------------------------------------- 1 | import { test } from '@playwright/test'; 2 | import { chromium } from 'playwright'; 3 | 4 | test('搜索测试', async ({ }) => { 5 | const browser = await chromium.launch({ headless: false }); 6 | const page = await browser.newPage(); 7 | await page.goto('http://localhost:9100/#/iot/device/Product'); 8 | await page.waitForTimeout(3000); 9 | // Expect a title "to contain" a substring. 10 | const inputs = await page.$$('.ant-input'); 11 | console.log(inputs.length) 12 | await inputs[0].fill('xyh') 13 | await inputs[1].fill('Qwer11234') 14 | const buttons = await page.$('.ant-btn') 15 | console.log(buttons) 16 | await buttons.click() 17 | await page.waitForTimeout(10000); // 等待1秒 18 | await page.goto('http://localhost:9100/#/iot/device/Product'); 19 | await page.waitForTimeout(30000); 20 | }); 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "lib": ["ESNext", "DOM"], 14 | "skipLibCheck": true, 15 | "noEmit": true, 16 | "allowJs": true, 17 | "baseUrl": "./", 18 | "paths": { 19 | "@/*": ["./src/*"] 20 | }, 21 | "types": ["ant-design-vue/typings/global", "vite/client"], 22 | "suppressImplicitAnyIndexErrors": true 23 | }, 24 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 25 | "references": [{ "path": "./tsconfig.node.json" }], 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": [ 9 | "vite.config.ts", 10 | "src/vite-env.d.ts", 11 | "configs/**/*.ts" 12 | ] 13 | } 14 | --------------------------------------------------------------------------------