feat: add app management pages
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
|
VITE_APP_TITLE = 防御机管理系统
|
||||||
VITE_APP_LOGO_TITLE = RuoYi-Vue-Plus
|
VITE_APP_LOGO_TITLE = 防御机管理系统
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
VITE_APP_ENV = 'development'
|
VITE_APP_ENV = 'development'
|
||||||
@@ -12,19 +12,21 @@ VITE_APP_BASE_API = '/dev-api'
|
|||||||
VITE_APP_CONTEXT_PATH = '/'
|
VITE_APP_CONTEXT_PATH = '/'
|
||||||
|
|
||||||
# 监控地址
|
# 监控地址
|
||||||
VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications'
|
VITE_APP_MONITOR_ADMIN = 'http://localhost:9001/admin/applications'
|
||||||
|
|
||||||
# SnailJob 控制台地址
|
# SnailJob 控制台地址
|
||||||
VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
|
VITE_APP_SNAILJOB_ADMIN = 'http://localhost:9002/snail-job'
|
||||||
|
|
||||||
VITE_APP_PORT = 80
|
VITE_APP_PORT = 80
|
||||||
|
|
||||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||||
VITE_APP_ENCRYPT = true
|
VITE_APP_ENCRYPT = false
|
||||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
#VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
|
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJJA9FRt24dkoEqTRBdm9yx6MQ5+f+rDIrLdCAXFUtpGcsT+kea/iGzk50OfSzSYxQYF8g/iksanB9XN0Ab6anECAwEAAQ=='
|
||||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
#VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
||||||
|
VITE_APP_RSA_PRIVATE_KEY = 'MIIBOgIBAAJBAIHPXmO+vf9u33iXv97aYeuPsJ7Ut+GdBjpT7JOIEE1rIEIfaKK268uPwAHW+/fNOKQiTBuunI4PAiL7CAQoVeECAwEAAQJACS6S3aP9/9W8MY/XqZAcQbOjPvOK94bKNvv9YvN1O785/2U5z7hUHvF8O8qIttlMNqhJ60JO9x58EUE51/dZ1QIhAISwFmIah9HoOLR5M+sBsUb5dIAm1mg0hj7T/5LyMTO7AiEA+nKebopGVz7LVkX53m29975r3T+DYu9n24eIqNwTDRMCIHn6xxj4+tNlgHuo0KnCrI5q1UbabVDuuFsZ2WHldIXxAiEAx6BA5H9XHgexcC0Kw97ZgvXHaG1NvrhxIizgIyh4Dv0CIB+VslCqTQTr9idyfVuURAiDdzg/9tm07GhWLDn6I6+E'
|
||||||
|
|
||||||
# 客户端id
|
# 客户端id
|
||||||
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
|
VITE_APP_TITLE = 防御机管理系统
|
||||||
VITE_APP_LOGO_TITLE = RuoYi-Vue-Plus
|
VITE_APP_LOGO_TITLE = 防御机管理系统
|
||||||
|
|
||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
VITE_APP_ENV = 'production'
|
VITE_APP_ENV = 'production'
|
||||||
@@ -23,7 +23,8 @@ VITE_BUILD_COMPRESS = gzip
|
|||||||
VITE_APP_PORT = 80
|
VITE_APP_PORT = 80
|
||||||
|
|
||||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||||
VITE_APP_ENCRYPT = true
|
# defensive_machine 后端 api-decrypt.enabled = false
|
||||||
|
VITE_APP_ENCRYPT = false
|
||||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||||
|
|||||||
BIN
dm-ui-dist.zip
Normal file
BIN
dm-ui-dist.zip
Normal file
Binary file not shown.
@@ -44,7 +44,9 @@
|
|||||||
"vue-json-pretty": "2.6.0",
|
"vue-json-pretty": "2.6.0",
|
||||||
"vue-router": "5.0.3",
|
"vue-router": "5.0.3",
|
||||||
"vue-types": "6.0.0",
|
"vue-types": "6.0.0",
|
||||||
"vxe-table": "4.18.1"
|
"vxe-table": "4.18.1",
|
||||||
|
"xgplayer": "^3.0.24",
|
||||||
|
"xgplayer-flv": "^3.0.24"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify/json": "^2.2.448",
|
"@iconify/json": "^2.2.448",
|
||||||
|
|||||||
90
script/bt/nginx-dm-ui.conf
Normal file
90
script/bt/nginx-dm-ui.conf
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# Put this server block in the BaoTa site's Nginx config.
|
||||||
|
# Replace server_name with your domain, or keep _ for IP-based access.
|
||||||
|
server {
|
||||||
|
listen 8000;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /www/wwwroot/dm-ui/dist;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
client_max_body_size 20m;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss image/svg+xml;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /assets/ {
|
||||||
|
try_files $uri =404;
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /prod-api/resource/sse {
|
||||||
|
rewrite ^/prod-api/(.*)$ /$1 break;
|
||||||
|
proxy_pass http://127.0.0.1:8080;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_cache off;
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /prod-api/resource/websocket {
|
||||||
|
rewrite ^/prod-api/(.*)$ /$1 break;
|
||||||
|
proxy_pass http://127.0.0.1:8080;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /prod-api/ {
|
||||||
|
rewrite ^/prod-api/(.*)$ /$1 break;
|
||||||
|
proxy_pass http://127.0.0.1:8080;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /admin {
|
||||||
|
return 301 /admin/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /admin/ {
|
||||||
|
proxy_pass http://127.0.0.1:9001/admin/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /snail-job {
|
||||||
|
return 301 /snail-job/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /snail-job/ {
|
||||||
|
proxy_pass http://127.0.0.1:9002/snail-job/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
src/api/app/device/index.ts
Normal file
68
src/api/app/device/index.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { DeviceVO, DeviceForm, DeviceQuery } from '@/api/app/device/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备信息
|
||||||
|
列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listDevice = (query?: DeviceQuery): AxiosPromise<DeviceVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/device/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备信息
|
||||||
|
详细
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getDevice = (id: string | number): AxiosPromise<DeviceVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/device/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增设备信息
|
||||||
|
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addDevice = (data: DeviceForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/device',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改设备信息
|
||||||
|
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateDevice = (data: DeviceForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/device',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设备信息
|
||||||
|
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const delDevice = (id: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/device/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
306
src/api/app/device/types.ts
Normal file
306
src/api/app/device/types.ts
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
export interface DeviceVO {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1-在线 0-离线 2-故障 3-到期
|
||||||
|
*/
|
||||||
|
status: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFi名称
|
||||||
|
*/
|
||||||
|
wifiName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFi密码
|
||||||
|
*/
|
||||||
|
wifiPassword: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强光开启
|
||||||
|
*/
|
||||||
|
light: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警播放
|
||||||
|
*/
|
||||||
|
alertAudio: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警内容
|
||||||
|
*/
|
||||||
|
audioContet: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击距离
|
||||||
|
*/
|
||||||
|
strikeRange: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击间隔
|
||||||
|
*/
|
||||||
|
strikeInterval: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 容器数量
|
||||||
|
*/
|
||||||
|
container: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击位置
|
||||||
|
*/
|
||||||
|
strikePosition: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动布放开始时间
|
||||||
|
*/
|
||||||
|
startTime: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动布放结束时间
|
||||||
|
*/
|
||||||
|
endTime: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作模式 0-自动 1-半自动
|
||||||
|
*/
|
||||||
|
workMode: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备型号
|
||||||
|
*/
|
||||||
|
deviceEm: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备序列号
|
||||||
|
*/
|
||||||
|
deviceSn: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 固件版本
|
||||||
|
*/
|
||||||
|
fwVer: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 识别模式 0-蓝牙 1-蓝牙+人脸
|
||||||
|
*/
|
||||||
|
patternPerception?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeviceForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1-在线 0-离线 2-故障 3-到期
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFi名称
|
||||||
|
*/
|
||||||
|
wifiName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFi密码
|
||||||
|
*/
|
||||||
|
wifiPassword?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强光开启
|
||||||
|
*/
|
||||||
|
light?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警播放
|
||||||
|
*/
|
||||||
|
alertAudio?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警内容
|
||||||
|
*/
|
||||||
|
audioContet?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击距离
|
||||||
|
*/
|
||||||
|
strikeRange?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击间隔
|
||||||
|
*/
|
||||||
|
strikeInterval?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 容器数量
|
||||||
|
*/
|
||||||
|
container?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击位置
|
||||||
|
*/
|
||||||
|
strikePosition?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动布放开始时间
|
||||||
|
*/
|
||||||
|
startTime?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动布放结束时间
|
||||||
|
*/
|
||||||
|
endTime?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作模式 0-自动 1-半自动
|
||||||
|
*/
|
||||||
|
workMode?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备型号
|
||||||
|
*/
|
||||||
|
deviceEm?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备序列号
|
||||||
|
*/
|
||||||
|
deviceSn?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 固件版本
|
||||||
|
*/
|
||||||
|
fwVer?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 识别模式 0-蓝牙 1-蓝牙+人脸
|
||||||
|
*/
|
||||||
|
patternPerception?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeviceQuery extends PageQuery {
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1-在线 0-离线 2-故障 3-到期
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFi名称
|
||||||
|
*/
|
||||||
|
wifiName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFi密码
|
||||||
|
*/
|
||||||
|
wifiPassword?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强光开启
|
||||||
|
*/
|
||||||
|
light?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警播放
|
||||||
|
*/
|
||||||
|
alertAudio?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警内容
|
||||||
|
*/
|
||||||
|
audioContet?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击距离
|
||||||
|
*/
|
||||||
|
strikeRange?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击间隔
|
||||||
|
*/
|
||||||
|
strikeInterval?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 容器数量
|
||||||
|
*/
|
||||||
|
container?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打击位置
|
||||||
|
*/
|
||||||
|
strikePosition?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动布放开始时间
|
||||||
|
*/
|
||||||
|
startTime?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动布放结束时间
|
||||||
|
*/
|
||||||
|
endTime?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作模式 0-自动 1-半自动
|
||||||
|
*/
|
||||||
|
workMode?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备型号
|
||||||
|
*/
|
||||||
|
deviceEm?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备序列号
|
||||||
|
*/
|
||||||
|
deviceSn?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 固件版本
|
||||||
|
*/
|
||||||
|
fwVer?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 识别模式 0-蓝牙 1-蓝牙+人脸
|
||||||
|
*/
|
||||||
|
patternPerception?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
63
src/api/app/deviceUser/index.ts
Normal file
63
src/api/app/deviceUser/index.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { DeviceUserVO, DeviceUserForm, DeviceUserQuery } from '@/api/app/deviceUser/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备成员关联列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listDeviceUser = (query?: DeviceUserQuery): AxiosPromise<DeviceUserVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/deviceUser/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备成员关联详细
|
||||||
|
* @param deviceId
|
||||||
|
*/
|
||||||
|
export const getDeviceUser = (deviceId: string | number): AxiosPromise<DeviceUserVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/deviceUser/' + deviceId,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增设备成员关联
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addDeviceUser = (data: DeviceUserForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/deviceUser',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改设备成员关联
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateDeviceUser = (data: DeviceUserForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/deviceUser',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设备成员关联
|
||||||
|
* @param deviceId
|
||||||
|
*/
|
||||||
|
export const delDeviceUser = (deviceId: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/deviceUser/' + deviceId,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
78
src/api/app/deviceUser/types.ts
Normal file
78
src/api/app/deviceUser/types.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
export interface DeviceUserVO {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
deviceId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
userId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeviceUserForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
deviceId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
userId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeviceUserQuery extends PageQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
80
src/api/app/family/index.ts
Normal file
80
src/api/app/family/index.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { FamilyVO, FamilyForm, FamilyQuery } from '@/api/app/family/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询家庭成员列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listFamily = (query?: FamilyQuery): AxiosPromise<FamilyVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/family/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询家庭成员详细
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getFamily = (id: string | number): AxiosPromise<FamilyVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/family/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增家庭成员
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addFamily = (data: FamilyForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/family',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改家庭成员
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateFamily = (data: FamilyForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/family',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除家庭成员
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const delFamily = (id: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/family/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家庭成员状态修改
|
||||||
|
* @param id 家庭成员ID
|
||||||
|
* @param status 状态
|
||||||
|
*/
|
||||||
|
export const changeFamilyStatus = (id: string | number, status: string) => {
|
||||||
|
const data = {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
};
|
||||||
|
return request({
|
||||||
|
url: '/app/family/changeStatus',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
83
src/api/app/family/types.ts
Normal file
83
src/api/app/family/types.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
export interface FamilyVO {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家长id
|
||||||
|
*/
|
||||||
|
parentId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家长昵称
|
||||||
|
*/
|
||||||
|
parentName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成员id
|
||||||
|
*/
|
||||||
|
userId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FamilyForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家长id
|
||||||
|
*/
|
||||||
|
parentId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家长昵称
|
||||||
|
*/
|
||||||
|
parentName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成员id
|
||||||
|
*/
|
||||||
|
userId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FamilyQuery extends PageQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家长id
|
||||||
|
*/
|
||||||
|
parentId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家长昵称
|
||||||
|
*/
|
||||||
|
parentName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成员id
|
||||||
|
*/
|
||||||
|
userId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
63
src/api/app/familyDevice/index.ts
Normal file
63
src/api/app/familyDevice/index.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { FamilyDeviceVO, FamilyDeviceForm, FamilyDeviceQuery } from '@/api/app/familyDevice/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询家庭设备关联列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listFamilyDevice = (query?: FamilyDeviceQuery): AxiosPromise<FamilyDeviceVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/familyDevice/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询家庭设备关联详细
|
||||||
|
* @param userId
|
||||||
|
*/
|
||||||
|
export const getFamilyDevice = (userId: string | number): AxiosPromise<FamilyDeviceVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/familyDevice/' + userId,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增家庭设备关联
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addFamilyDevice = (data: FamilyDeviceForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/familyDevice',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改家庭设备关联
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateFamilyDevice = (data: FamilyDeviceForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/familyDevice',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除家庭设备关联
|
||||||
|
* @param userId
|
||||||
|
*/
|
||||||
|
export const delFamilyDevice = (userId: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/familyDevice/' + userId,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
78
src/api/app/familyDevice/types.ts
Normal file
78
src/api/app/familyDevice/types.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
export interface FamilyDeviceVO {
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
userId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
deviceId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FamilyDeviceForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
userId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
deviceId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FamilyDeviceQuery extends PageQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编号
|
||||||
|
*/
|
||||||
|
deviceNo?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
deviceName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
63
src/api/app/message/index.ts
Normal file
63
src/api/app/message/index.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { MessageVO, MessageForm, MessageQuery } from '@/api/app/message/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询告警消息列列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listMessage = (query?: MessageQuery): AxiosPromise<MessageVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/message/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询告警消息列详细
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getMessage = (id: string | number): AxiosPromise<MessageVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/message/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增告警消息列
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addMessage = (data: MessageForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/message',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改告警消息列
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateMessage = (data: MessageForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/message',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除告警消息列
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const delMessage = (id: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/message/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
87
src/api/app/message/types.ts
Normal file
87
src/api/app/message/types.ts
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
export interface MessageVO {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
category: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警类型
|
||||||
|
*/
|
||||||
|
categoryName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片地址
|
||||||
|
*/
|
||||||
|
image: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片地址Url
|
||||||
|
*/
|
||||||
|
imageUrl: string;
|
||||||
|
/**
|
||||||
|
* 视频地址
|
||||||
|
*/
|
||||||
|
video: string | number;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
category?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警类型
|
||||||
|
*/
|
||||||
|
categoryName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片地址
|
||||||
|
*/
|
||||||
|
image?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频地址
|
||||||
|
*/
|
||||||
|
video?: string | number;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageQuery extends PageQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
category?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警类型
|
||||||
|
*/
|
||||||
|
categoryName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片地址
|
||||||
|
*/
|
||||||
|
image?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频地址
|
||||||
|
*/
|
||||||
|
video?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
101
src/api/app/user/index.ts
Normal file
101
src/api/app/user/index.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { UserVO, UserForm, UserQuery } from '@/api/app/user/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询app用户信息列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listUser = (query?: UserQuery): AxiosPromise<UserVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/user/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询app用户信息详细
|
||||||
|
* @param userId
|
||||||
|
*/
|
||||||
|
export const getUser = (userId: string | number): AxiosPromise<UserVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/user/' + userId,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增app用户信息
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addUser = (data: UserForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/user',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改app用户信息
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateUser = (data: UserForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/user',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除app用户信息
|
||||||
|
* @param userId
|
||||||
|
*/
|
||||||
|
export const delUser = (userId: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/user/' + userId,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户状态修改
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param status 用户状态
|
||||||
|
*/
|
||||||
|
export const changeUserStatus = (userId: string | number, status: string) => {
|
||||||
|
const data = {
|
||||||
|
userId,
|
||||||
|
status
|
||||||
|
};
|
||||||
|
return request({
|
||||||
|
url: '/app/user/changeStatus',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置用户密码
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param password 新密码
|
||||||
|
*/
|
||||||
|
export const resetUserPwd = (userId: string | number, password: string) => {
|
||||||
|
const data = {
|
||||||
|
userId,
|
||||||
|
password
|
||||||
|
};
|
||||||
|
return request({
|
||||||
|
url: '/app/user/resetPwd',
|
||||||
|
method: 'put',
|
||||||
|
headers: {
|
||||||
|
isEncrypt: true,
|
||||||
|
repeatSubmit: false
|
||||||
|
},
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
273
src/api/app/user/types.ts
Normal file
273
src/api/app/user/types.ts
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
export interface UserVO {
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
userId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
userName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份证号
|
||||||
|
*/
|
||||||
|
idCard: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型(sys_user系统用户)
|
||||||
|
*/
|
||||||
|
userType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
phonenumber: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别(0男 1女 2未知)
|
||||||
|
*/
|
||||||
|
sex: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头像地址
|
||||||
|
*/
|
||||||
|
avatar: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
password: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人脸
|
||||||
|
*/
|
||||||
|
faceAddr: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机mac地址
|
||||||
|
*/
|
||||||
|
mac: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请码
|
||||||
|
*/
|
||||||
|
inviteUsed: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请码创建时间
|
||||||
|
*/
|
||||||
|
inviteTime: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录IP
|
||||||
|
*/
|
||||||
|
loginIp: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录时间
|
||||||
|
*/
|
||||||
|
loginDate: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
remark: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
userId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
userName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份证号
|
||||||
|
*/
|
||||||
|
idCard?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型(sys_user系统用户)
|
||||||
|
*/
|
||||||
|
userType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
email?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
phonenumber?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别(0男 1女 2未知)
|
||||||
|
*/
|
||||||
|
sex?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头像地址
|
||||||
|
*/
|
||||||
|
avatar?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
password?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人脸
|
||||||
|
*/
|
||||||
|
faceAddr?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机mac地址
|
||||||
|
*/
|
||||||
|
mac?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请码
|
||||||
|
*/
|
||||||
|
inviteUsed?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请码创建时间
|
||||||
|
*/
|
||||||
|
inviteTime?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录IP
|
||||||
|
*/
|
||||||
|
loginIp?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录时间
|
||||||
|
*/
|
||||||
|
loginDate?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
remark?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserQuery extends PageQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
userName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
nickName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份证号
|
||||||
|
*/
|
||||||
|
idCard?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型(sys_user系统用户)
|
||||||
|
*/
|
||||||
|
userType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
email?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
phonenumber?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别(0男 1女 2未知)
|
||||||
|
*/
|
||||||
|
sex?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头像地址
|
||||||
|
*/
|
||||||
|
avatar?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
password?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号状态(0正常 1停用)
|
||||||
|
*/
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人脸
|
||||||
|
*/
|
||||||
|
faceAddr?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机mac地址
|
||||||
|
*/
|
||||||
|
mac?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请码
|
||||||
|
*/
|
||||||
|
inviteUsed?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请码创建时间
|
||||||
|
*/
|
||||||
|
inviteTime?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录IP
|
||||||
|
*/
|
||||||
|
loginIp?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后登录时间
|
||||||
|
*/
|
||||||
|
loginDate?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
63
src/api/app/userdeviceToken/index.ts
Normal file
63
src/api/app/userdeviceToken/index.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { UserdeviceTokenVO, UserdeviceTokenForm, UserdeviceTokenQuery } from '@/api/app/userdeviceToken/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询推送用户手机token列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listUserdeviceToken = (query?: UserdeviceTokenQuery): AxiosPromise<UserdeviceTokenVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/userdeviceToken/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询推送用户手机token详细
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getUserdeviceToken = (id: string | number): AxiosPromise<UserdeviceTokenVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/app/userdeviceToken/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增推送用户手机token
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addUserdeviceToken = (data: UserdeviceTokenForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/userdeviceToken',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改推送用户手机token
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateUserdeviceToken = (data: UserdeviceTokenForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/userdeviceToken',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除推送用户手机token
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const delUserdeviceToken = (id: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/app/userdeviceToken/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
||||||
83
src/api/app/userdeviceToken/types.ts
Normal file
83
src/api/app/userdeviceToken/types.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
export interface UserdeviceTokenVO {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号用户id
|
||||||
|
*/
|
||||||
|
userId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备token
|
||||||
|
*/
|
||||||
|
token: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台 iOS/Android
|
||||||
|
*/
|
||||||
|
platform: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
createdTime: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserdeviceTokenForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号用户id
|
||||||
|
*/
|
||||||
|
userId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备token
|
||||||
|
*/
|
||||||
|
token?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台 iOS/Android
|
||||||
|
*/
|
||||||
|
platform?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
createdTime?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserdeviceTokenQuery extends PageQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号用户id
|
||||||
|
*/
|
||||||
|
userId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备token
|
||||||
|
*/
|
||||||
|
token?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台 iOS/Android
|
||||||
|
*/
|
||||||
|
platform?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
createdTime?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
@@ -144,7 +144,7 @@ const computedIds = (data) => {
|
|||||||
const getList = () => {
|
const getList = () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
api.listRole(proxy?.addDateRange(queryParams.value, dateRange.value)).then((res) => {
|
api.listRole(proxy?.addDateRange(queryParams.value, dateRange.value)).then((res) => {
|
||||||
roleList.value = res.rows;
|
roleList.value = res.data;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
|
|||||||
45
src/views/app/.workbuddy/memory/2026-06-04.md
Normal file
45
src/views/app/.workbuddy/memory/2026-06-04.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# 2026-06-04
|
||||||
|
|
||||||
|
## user/index.vue - 人脸列多图片展示
|
||||||
|
- 将人脸列从单张 `image-preview` 改为多张 `el-image` 缩略图布局
|
||||||
|
- 新增 `faceUrls()` 工具函数,将逗号分隔的 `faceAddr` 拆分为数组
|
||||||
|
- 每张缩略图 40x40,flex 横排,gap 4px
|
||||||
|
- 通过 `preview-src-list` + `initial-index` 实现点击任意一张可轮播预览全部
|
||||||
|
- 添加 hover 放大动效和图片加载失败的占位 icon
|
||||||
|
|
||||||
|
## user/index.vue - 用户账号列展示优化
|
||||||
|
- "用户账号"列改为优先展示手机号、其次邮箱、最后 userName 的降级逻辑
|
||||||
|
- 模板表达式:`phonenumber || email || userName || '-'`
|
||||||
|
|
||||||
|
## user/index.vue - 仿 sysuser 添加重置密码
|
||||||
|
- API: `d:\code\plus-ui\src\api\app\user\index.ts` 新增 `resetUserPwd(userId, password)` → `PUT /app/user/resetPwd`
|
||||||
|
- View: 操作列新增"重置密码"按钮(Key 图标),权限 `app:user:resetPwd`
|
||||||
|
- `handleResetPwd`: ElMessageBox.prompt 弹窗输入新密码,校验 5-20 位、禁非法字符 `<>"'|\`
|
||||||
|
- 成功提示包含新密码明文
|
||||||
|
|
||||||
|
## user/index.vue - 账号状态改为 el-switch 开关
|
||||||
|
- API: `d:\code\plus-ui\src\api\app\user\index.ts` 新增 `changeUserStatus(userId, status)` → `PUT /app/user/changeStatus`
|
||||||
|
- 状态列从纯文本改为 `el-switch`,`active-value="0"`(启用)、`inactive-value="1"`(停用)
|
||||||
|
- `handleStatusChange`: 切换前弹确认框,操作失败时回滚开关状态
|
||||||
|
|
||||||
|
## message/index.vue - 视频地址改为在线播放
|
||||||
|
- 视频地址列从纯文本改为"播放"按钮(`VideoPlay` 图标 + 点击触发 `handlePlayVideo`)
|
||||||
|
- 新增视频播放弹窗:`<video>` 标签 + `controls` + `autoplay`,宽度 100%,最大高度 60vh
|
||||||
|
- `videoDialog`: `{ visible: boolean; url: string }`,关闭弹窗时清空 url
|
||||||
|
- 无视频时显示 `-`
|
||||||
|
|
||||||
|
## message/index.vue - 视频地址改为在线播放(ZLMediaKit HTTP-FLV)
|
||||||
|
- 安装 `xgplayer` + `xgplayer-flv` 依赖(npm install --save)
|
||||||
|
- 视频地址列从纯文本改为"播放"按钮(`VideoPlay` 图标)
|
||||||
|
- 点击按钮弹出视频播放弹窗(720px 宽),内嵌 xgplayer 实例
|
||||||
|
- `initPlayer(url)`: 创建 xgplayer,配置 `flv.mediaDataSource.isLive=true`、`type=flv`
|
||||||
|
- `destroyPlayer()`: 弹窗关闭时销毁播放器,防止内存泄漏
|
||||||
|
- `nextTick` 延迟初始化确保 DOM 渲染完毕
|
||||||
|
- 播放器容器 CSS: 60vh 高度、黑色背景、圆角、overflow hidden
|
||||||
|
|
||||||
|
## family/index.vue - 状态改为 el-switch 开关
|
||||||
|
- API: `d:\code\plus-ui\src\api\app\family\index.ts` 新增 `changeFamilyStatus(id, status)` → `PUT /app/family/changeStatus`
|
||||||
|
- 移除重复的纯文本"账号状态"列,保留 el-switch 列
|
||||||
|
- `handleStatusChange`: 修复从错误引用(`phonenumber/email/userName`、`changeUserStatus`)改为 FamilyVO 字段(`parentName/id`)和 `changeFamilyStatus`
|
||||||
|
- 操作失败时自动回滚开关状态
|
||||||
|
|
||||||
32
src/views/app/.workbuddy/memory/2026-06-05.md
Normal file
32
src/views/app/.workbuddy/memory/2026-06-05.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# 2026-06-05
|
||||||
|
|
||||||
|
## device/index.vue - 设备信息页面4个字段展示改造
|
||||||
|
|
||||||
|
### 改动概述
|
||||||
|
按用户要求修改设备信息页面的4个字段展示方式:
|
||||||
|
|
||||||
|
| 字段 | 改造前 | 改造后 |
|
||||||
|
|---|---|---|
|
||||||
|
| `status` | 纯数字 (0/1/2/3) | el-tag 彩色标签:0=离线(info)、1=在线(success)、2=故障(danger)、3=到期(warning) |
|
||||||
|
| `light` | 纯数字输入框 → el-switch → **el-tag 标签** | el-tag 彩色标签:0=不开启(info)、1=开启(success),移除开关交互 |
|
||||||
|
| `alertAudio` | 纯数字输入框 → el-switch → **el-tag 标签** | el-tag 彩色标签:0=不播放(info)、1=播放(success),移除开关交互 |
|
||||||
|
| `recognizeMode` | 不存在 | 新增字段,el-tag 展示:0=蓝牙(info)、1=蓝牙+人脸(primary) |
|
||||||
|
| `workMode` | 纯数字文本 | el-tag 彩色标签:0=自动(success)、1=半自动(primary) |
|
||||||
|
|
||||||
|
### 涉及文件
|
||||||
|
1. **`src/api/app/device/types.ts`**
|
||||||
|
- `DeviceVO` 新增 `recognizeMode?: string` 字段
|
||||||
|
- `DeviceForm` 新增 `recognizeMode?: string` 字段
|
||||||
|
- `DeviceQuery` 新增 `recognizeMode?: string` 字段
|
||||||
|
|
||||||
|
2. **`src/views/app/device/index.vue`**
|
||||||
|
- 查询表单:`light`/`alertAudio` 改为 el-select 下拉选择,`recognizeMode` 新增查询条件
|
||||||
|
- 表格列:`status`/`light`/`alertAudio`/`recognizeMode` 改为标签/开关展示
|
||||||
|
- 弹窗表单:`light`/`alertAudio` 改为 el-switch,`recognizeMode` 新增表单字段
|
||||||
|
- Script:新增 `statusTagType()`、`statusLabel()`、`patternPerceptionLabel()`、`lightTagType()`、`lightLabel()`、`alertAudioTagType()`、`alertAudioLabel()` 函数;移除 `handleLightChange()`、`handleAlertAudioChange()` 开关 handler
|
||||||
|
|
||||||
|
### 注意事项
|
||||||
|
- `light`/`alertAudio` 最终改为纯展示(el-tag 标签,无交互),与 `status` 列展示风格统一
|
||||||
|
- `workMode` 列:纯数字文本 → el-tag 彩色标签(0=自动 success / 1=半自动 primary)
|
||||||
|
- `audioContet` 列:纯文本 → 超长截断(max-width 120px ellipsis)+ el-tooltip 悬停显示完整内容(show-after 200ms)
|
||||||
|
- `patternPerception` 字段名统一修正:DeviceVO 中原错误写为 `recognizeMode`,已统一改为 `patternPerception`
|
||||||
0
src/views/app/.workbuddy/memory/MEMORY.md
Normal file
0
src/views/app/.workbuddy/memory/MEMORY.md
Normal file
497
src/views/app/device/index.vue
Normal file
497
src/views/app/device/index.vue
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="设备编号" prop="deviceNo">
|
||||||
|
<el-input v-model="queryParams.deviceNo" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备名称" prop="deviceName">
|
||||||
|
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="WiFi名称" prop="wifiName">-->
|
||||||
|
<!-- <el-input v-model="queryParams.wifiName" placeholder="请输入WiFi名称" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="WiFi密码" prop="wifiPassword">-->
|
||||||
|
<!-- <el-input v-model="queryParams.wifiPassword" placeholder="请输入WiFi密码" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="强光开启" prop="light">-->
|
||||||
|
<!-- <el-select v-model="queryParams.light" placeholder="请选择" clearable @change="handleQuery">-->
|
||||||
|
<!-- <el-option label="不开启" value="0" />-->
|
||||||
|
<!-- <el-option label="开启" value="1" />-->
|
||||||
|
<!-- </el-select>-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="告警播放" prop="alertAudio">-->
|
||||||
|
<!-- <el-select v-model="queryParams.alertAudio" placeholder="请选择" clearable @change="handleQuery">-->
|
||||||
|
<!-- <el-option label="不播放" value="0" />-->
|
||||||
|
<!-- <el-option label="播放" value="1" />-->
|
||||||
|
<!-- </el-select>-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="识别模式" prop="patternPerception">-->
|
||||||
|
<!-- <el-select v-model="queryParams.patternPerception" placeholder="请选择" clearable @change="handleQuery">-->
|
||||||
|
<!-- <el-option label="蓝牙" value="0" />-->
|
||||||
|
<!-- <el-option label="蓝牙+人脸" value="1" />-->
|
||||||
|
<!-- </el-select>-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="告警内容" prop="audioContet">-->
|
||||||
|
<!-- <el-input v-model="queryParams.audioContet" placeholder="请输入告警内容" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="打击距离" prop="strikeRange">-->
|
||||||
|
<!-- <el-input v-model="queryParams.strikeRange" placeholder="请输入打击距离" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="打击间隔" prop="strikeInterval">-->
|
||||||
|
<!-- <el-input v-model="queryParams.strikeInterval" placeholder="请输入打击间隔" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="容器数量" prop="container">-->
|
||||||
|
<!-- <el-input v-model="queryParams.container" placeholder="请输入容器数量" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="打击位置" prop="strikePosition">-->
|
||||||
|
<!-- <el-input v-model="queryParams.strikePosition" placeholder="请输入打击位置" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="自动布放开始时间" prop="startTime">-->
|
||||||
|
<!-- <el-date-picker clearable v-model="queryParams.startTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择自动布放开始时间" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="自动布放结束时间" prop="endTime">-->
|
||||||
|
<!-- <el-date-picker clearable v-model="queryParams.endTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择自动布放结束时间" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="工作模式 0-自动 1-半自动" prop="workMode">-->
|
||||||
|
<!-- <el-input v-model="queryParams.workMode" placeholder="请输入工作模式 0-自动 1-半自动" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="设备型号" prop="deviceEm">-->
|
||||||
|
<!-- <el-input v-model="queryParams.deviceEm" placeholder="请输入设备型号" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="设备序列号" prop="deviceSn">-->
|
||||||
|
<!-- <el-input v-model="queryParams.deviceSn" placeholder="请输入设备序列号" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="固件版本" prop="fwVer">-->
|
||||||
|
<!-- <el-input v-model="queryParams.fwVer" placeholder="请输入固件版本" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['app:device:add']">新增</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['app:device:edit']">修改</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['app:device:remove']"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['app:device:export']">导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="deviceList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="" align="center" prop="id" v-if="true" />
|
||||||
|
<el-table-column label="设备编号" align="center" prop="deviceNo" />
|
||||||
|
<el-table-column label="设备名称" align="center" prop="deviceName" />
|
||||||
|
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="statusTagType(scope.row.status)">
|
||||||
|
{{ statusLabel(scope.row.status) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="WiFi名称" align="center" prop="wifiName" />
|
||||||
|
<el-table-column label="WiFi密码" align="center" prop="wifiPassword" />
|
||||||
|
<el-table-column label="强光开启" align="center" prop="light" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="lightTagType(scope.row.light)">
|
||||||
|
{{ lightLabel(scope.row.light) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="告警播放" align="center" prop="alertAudio" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="alertAudioTagType(scope.row.alertAudio)">
|
||||||
|
{{ alertAudioLabel(scope.row.alertAudio) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="识别模式" align="center" prop="patternPerception" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="scope.row.patternPerception === '1' ? 'primary' : 'info'">
|
||||||
|
{{ patternPerceptionLabel(scope.row.patternPerception) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="告警内容" align="center" prop="audioContet" min-width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tooltip v-if="scope.row.audioContet" :content="scope.row.audioContet" placement="top" :show-after="200">
|
||||||
|
<span class="text-ellipsis">{{ scope.row.audioContet }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="打击距离" align="center" prop="strikeRange" />
|
||||||
|
<el-table-column label="打击间隔" align="center" prop="strikeInterval" />
|
||||||
|
<el-table-column label="容器数量" align="center" prop="container" />
|
||||||
|
<el-table-column label="打击位置" align="center" prop="strikePosition" />
|
||||||
|
<el-table-column label="自动布放开始时间" align="center" prop="startTime" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="自动布放结束时间" align="center" prop="endTime" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="工作模式" align="center" prop="workMode" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="workModeTagType(scope.row.workMode)">
|
||||||
|
{{ workModeLabel(scope.row.workMode) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="设备型号" align="center" prop="deviceEm" />
|
||||||
|
<el-table-column label="设备序列号" align="center" prop="deviceSn" />
|
||||||
|
<el-table-column label="固件版本" align="center" prop="fwVer" />
|
||||||
|
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<!-- <el-tooltip content="修改" placement="top">-->
|
||||||
|
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['app:device:edit']"></el-button>-->
|
||||||
|
<!-- </el-tooltip>-->
|
||||||
|
<el-tooltip content="删除" placement="top">
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['app:device:remove']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改设备信息
|
||||||
|
对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="deviceFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="设备编号" prop="deviceNo">
|
||||||
|
<el-input v-model="form.deviceNo" placeholder="请输入设备编号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备名称" prop="deviceName">
|
||||||
|
<el-input v-model="form.deviceName" placeholder="请输入设备名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="WiFi名称" prop="wifiName">
|
||||||
|
<el-input v-model="form.wifiName" placeholder="请输入WiFi名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="WiFi密码" prop="wifiPassword">
|
||||||
|
<el-input v-model="form.wifiPassword" placeholder="请输入WiFi密码" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="强光开启" prop="light">
|
||||||
|
<el-switch v-model="form.light" active-value="1" inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="告警播放" prop="alertAudio">
|
||||||
|
<el-switch v-model="form.alertAudio" active-value="1" inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="识别模式" prop="patternPerception">
|
||||||
|
<el-select v-model="form.patternPerception" placeholder="请选择识别模式">
|
||||||
|
<el-option label="蓝牙" value="0" />
|
||||||
|
<el-option label="蓝牙+人脸" value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="告警内容" prop="audioContet">
|
||||||
|
<el-input v-model="form.audioContet" placeholder="请输入告警内容" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="打击距离" prop="strikeRange">
|
||||||
|
<el-input v-model="form.strikeRange" placeholder="请输入打击距离" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="打击间隔" prop="strikeInterval">
|
||||||
|
<el-input v-model="form.strikeInterval" placeholder="请输入打击间隔" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="容器数量" prop="container">
|
||||||
|
<el-input v-model="form.container" placeholder="请输入容器数量" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="打击位置" prop="strikePosition">
|
||||||
|
<el-input v-model="form.strikePosition" placeholder="请输入打击位置" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="自动布放开始时间" prop="startTime">
|
||||||
|
<el-date-picker clearable v-model="form.startTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择自动布放开始时间">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="自动布放结束时间" prop="endTime">
|
||||||
|
<el-date-picker clearable v-model="form.endTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择自动布放结束时间">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="工作模式 0-自动 1-半自动" prop="workMode">
|
||||||
|
<el-input v-model="form.workMode" placeholder="请输入工作模式 0-自动 1-半自动" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备型号" prop="deviceEm">
|
||||||
|
<el-input v-model="form.deviceEm" placeholder="请输入设备型号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备序列号" prop="deviceSn">
|
||||||
|
<el-input v-model="form.deviceSn" placeholder="请输入设备序列号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="固件版本" prop="fwVer">
|
||||||
|
<el-input v-model="form.fwVer" placeholder="请输入固件版本" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Device" lang="ts">
|
||||||
|
import { listDevice, getDevice, delDevice, addDevice, updateDevice } from '@/api/app/device';
|
||||||
|
import { DeviceVO, DeviceQuery, DeviceForm } from '@/api/app/device/types';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
/** 状态标签类型映射 */
|
||||||
|
const statusTagType = (status: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': 'info', '1': 'success', '2': 'danger', '3': 'warning' };
|
||||||
|
return map[status] || 'info';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 状态中文标签 */
|
||||||
|
const statusLabel = (status: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': '离线', '1': '在线', '2': '故障', '3': '到期' };
|
||||||
|
return map[status] || status || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 识别模式中文标签 */
|
||||||
|
const patternPerceptionLabel = (mode: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': '蓝牙', '1': '蓝牙+人脸' };
|
||||||
|
return map[mode] || mode || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 强光开启标签类型映射 */
|
||||||
|
const lightTagType = (light: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': 'info', '1': 'success' };
|
||||||
|
return map[light] || 'info';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 强光开启中文标签 */
|
||||||
|
const lightLabel = (light: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': '不开启', '1': '开启' };
|
||||||
|
return map[light] || light || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 告警播放标签类型映射 */
|
||||||
|
const alertAudioTagType = (alertAudio: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': 'info', '1': 'success' };
|
||||||
|
return map[alertAudio] || 'info';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 告警播放中文标签 */
|
||||||
|
const alertAudioLabel = (alertAudio: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': '不播放', '1': '播放' };
|
||||||
|
return map[alertAudio] || alertAudio || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 工作模式标签类型映射 */
|
||||||
|
const workModeTagType = (mode: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': 'success', '1': 'primary' };
|
||||||
|
return map[mode] || 'info';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 工作模式中文标签 */
|
||||||
|
const workModeLabel = (mode: string): string => {
|
||||||
|
const map: Record<string, string> = { '0': '自动', '1': '半自动' };
|
||||||
|
return map[mode] || mode || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
const deviceList = ref<DeviceVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const deviceFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: DeviceForm = {
|
||||||
|
id: undefined,
|
||||||
|
deviceNo: undefined,
|
||||||
|
deviceName: undefined,
|
||||||
|
status: undefined,
|
||||||
|
wifiName: undefined,
|
||||||
|
wifiPassword: undefined,
|
||||||
|
light: undefined,
|
||||||
|
alertAudio: undefined,
|
||||||
|
audioContet: undefined,
|
||||||
|
strikeRange: undefined,
|
||||||
|
strikeInterval: undefined,
|
||||||
|
container: undefined,
|
||||||
|
strikePosition: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
workMode: undefined,
|
||||||
|
deviceEm: undefined,
|
||||||
|
deviceSn: undefined,
|
||||||
|
fwVer: undefined,
|
||||||
|
patternPerception: undefined
|
||||||
|
};
|
||||||
|
const data = reactive<PageData<DeviceForm, DeviceQuery>>({
|
||||||
|
form: { ...initFormData },
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
deviceNo: undefined,
|
||||||
|
deviceName: undefined,
|
||||||
|
status: undefined,
|
||||||
|
wifiName: undefined,
|
||||||
|
wifiPassword: undefined,
|
||||||
|
light: undefined,
|
||||||
|
alertAudio: undefined,
|
||||||
|
audioContet: undefined,
|
||||||
|
strikeRange: undefined,
|
||||||
|
strikeInterval: undefined,
|
||||||
|
container: undefined,
|
||||||
|
strikePosition: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
workMode: undefined,
|
||||||
|
deviceEm: undefined,
|
||||||
|
deviceSn: undefined,
|
||||||
|
fwVer: undefined,
|
||||||
|
patternPerception: undefined,
|
||||||
|
params: {}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
id: [{ required: true, message: '不能为空', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询设备信息
|
||||||
|
列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listDevice(queryParams.value);
|
||||||
|
deviceList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = { ...initFormData };
|
||||||
|
deviceFormRef.value?.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: DeviceVO[]) => {
|
||||||
|
ids.value = selection.map((item) => item.id);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '添加设备信息';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: DeviceVO) => {
|
||||||
|
reset();
|
||||||
|
const _id = row?.id || ids.value[0];
|
||||||
|
const res = await getDevice(_id);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '修改设备信息';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
deviceFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateDevice(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
} else {
|
||||||
|
await addDevice(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: DeviceVO) => {
|
||||||
|
const _ids = row?.id || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除设备信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||||
|
await delDevice(_ids);
|
||||||
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
|
await getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download(
|
||||||
|
'app/device/export',
|
||||||
|
{
|
||||||
|
...queryParams.value
|
||||||
|
},
|
||||||
|
`device_${new Date().getTime()}.xlsx`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.text-ellipsis {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 120px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: bottom;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
237
src/views/app/deviceUser/index.vue
Normal file
237
src/views/app/deviceUser/index.vue
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="设备编号" prop="deviceNo">
|
||||||
|
<el-input v-model="queryParams.deviceNo" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备名称" prop="deviceName">
|
||||||
|
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户昵称" prop="nickName">
|
||||||
|
<el-input v-model="queryParams.nickName" placeholder="请输入用户昵称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<!-- <template #header>-->
|
||||||
|
<!-- <el-row :gutter="10" class="mb8">-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['app:deviceUser:add']">新增</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['app:deviceUser:edit']">修改</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['app:deviceUser:remove']">删除</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['app:deviceUser:export']">导出</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>-->
|
||||||
|
<!-- </el-row>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="deviceUserList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="设备ID" align="center" prop="deviceId" v-if="true" />
|
||||||
|
<el-table-column label="设备编号" align="center" prop="deviceNo" />
|
||||||
|
<el-table-column label="设备名称" align="center" prop="deviceName" />
|
||||||
|
<el-table-column label="用户ID" align="center" prop="userId" v-if="true" />
|
||||||
|
<el-table-column label="用户昵称" align="center" prop="nickName" />
|
||||||
|
<el-table-column label="用户身份证号" align="center" prop="idCard" />
|
||||||
|
<el-table-column label="用户手机号" align="center" prop="phonenumber" />
|
||||||
|
<el-table-column label="用户MAC地址" align="center" prop="mac" />
|
||||||
|
<!-- <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">-->
|
||||||
|
<!-- <template #default="scope">-->
|
||||||
|
<!-- <el-tooltip content="修改" placement="top">-->
|
||||||
|
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['app:deviceUser:edit']"></el-button>-->
|
||||||
|
<!-- </el-tooltip>-->
|
||||||
|
<!-- <el-tooltip content="删除" placement="top">-->
|
||||||
|
<!-- <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['app:deviceUser:remove']"></el-button>-->
|
||||||
|
<!-- </el-tooltip>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- </el-table-column>-->
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改设备成员关联对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="deviceUserFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="设备编号" prop="deviceNo">
|
||||||
|
<el-input v-model="form.deviceNo" placeholder="请输入设备编号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备名称" prop="deviceName">
|
||||||
|
<el-input v-model="form.deviceName" placeholder="请输入设备名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户昵称" prop="nickName">
|
||||||
|
<el-input v-model="form.nickName" placeholder="请输入用户昵称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="DeviceUser" lang="ts">
|
||||||
|
import { listDeviceUser, getDeviceUser, delDeviceUser, addDeviceUser, updateDeviceUser } from '@/api/app/deviceUser';
|
||||||
|
import { DeviceUserVO, DeviceUserQuery, DeviceUserForm } from '@/api/app/deviceUser/types';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
const deviceUserList = ref<DeviceUserVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const deviceUserFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: DeviceUserForm = {
|
||||||
|
deviceId: undefined,
|
||||||
|
deviceNo: undefined,
|
||||||
|
deviceName: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
nickName: undefined
|
||||||
|
};
|
||||||
|
const data = reactive<PageData<DeviceUserForm, DeviceUserQuery>>({
|
||||||
|
form: { ...initFormData },
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
deviceNo: undefined,
|
||||||
|
deviceName: undefined,
|
||||||
|
nickName: undefined,
|
||||||
|
params: {}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
deviceId: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||||
|
userId: [{ required: true, message: '用户ID不能为空', trigger: 'blur' }],
|
||||||
|
nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询设备成员关联列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listDeviceUser(queryParams.value);
|
||||||
|
deviceUserList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = { ...initFormData };
|
||||||
|
deviceUserFormRef.value?.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: DeviceUserVO[]) => {
|
||||||
|
ids.value = selection.map((item) => item.deviceId);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '添加设备成员关联';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: DeviceUserVO) => {
|
||||||
|
reset();
|
||||||
|
const _deviceId = row?.deviceId || ids.value[0];
|
||||||
|
const res = await getDeviceUser(_deviceId);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '修改设备成员关联';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
deviceUserFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.deviceId) {
|
||||||
|
await updateDeviceUser(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
} else {
|
||||||
|
await addDeviceUser(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: DeviceUserVO) => {
|
||||||
|
const _deviceIds = row?.deviceId || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除设备成员关联编号为"' + _deviceIds + '"的数据项?').finally(() => (loading.value = false));
|
||||||
|
await delDeviceUser(_deviceIds);
|
||||||
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
|
await getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download(
|
||||||
|
'app/deviceUser/export',
|
||||||
|
{
|
||||||
|
...queryParams.value
|
||||||
|
},
|
||||||
|
`deviceUser_${new Date().getTime()}.xlsx`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
255
src/views/app/family/index.vue
Normal file
255
src/views/app/family/index.vue
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="家长id" prop="parentId">
|
||||||
|
<el-input v-model="queryParams.parentId" placeholder="请输入家长id" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="家长昵称" prop="parentName">
|
||||||
|
<el-input v-model="queryParams.parentName" placeholder="请输入家长昵称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="成员id" prop="userId">
|
||||||
|
<el-input v-model="queryParams.userId" placeholder="请输入成员id" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<!-- <template #header>-->
|
||||||
|
<!-- <el-row :gutter="10" class="mb8">-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['app:family:add']">新增</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['app:family:edit']">修改</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['app:family:remove']">删除</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['app:family:export']">导出</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>-->
|
||||||
|
<!-- </el-row>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="familyList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="ID" align="center" prop="id" v-if="true" />
|
||||||
|
<el-table-column label="家长id" align="center" prop="parentId" />
|
||||||
|
<el-table-column label="家长昵称" align="center" prop="parentName" />
|
||||||
|
<el-table-column label="成员id" align="center" prop="userId" />
|
||||||
|
<el-table-column label="用户昵称" align="center" prop="nickName" />
|
||||||
|
<el-table-column label="用户身份证号" align="center" prop="idCard" />
|
||||||
|
<el-table-column label="用户手机号" align="center" prop="phonenumber" />
|
||||||
|
<el-table-column label="用户MAC地址" align="center" prop="mac" />
|
||||||
|
<el-table-column label="账号状态" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||||
|
<!-- <template #default="scope">-->
|
||||||
|
<!-- <el-tooltip content="修改" placement="top">-->
|
||||||
|
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['app:family:edit']"></el-button>-->
|
||||||
|
<!-- </el-tooltip>-->
|
||||||
|
<!-- <el-tooltip content="删除" placement="top">-->
|
||||||
|
<!-- <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['app:family:remove']"></el-button>-->
|
||||||
|
<!-- </el-tooltip>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改家庭成员对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="familyFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="家长id" prop="parentId">
|
||||||
|
<el-input v-model="form.parentId" placeholder="请输入家长id" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="家长昵称" prop="parentName">
|
||||||
|
<el-input v-model="form.parentName" placeholder="请输入家长昵称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="成员id" prop="userId">
|
||||||
|
<el-input v-model="form.userId" placeholder="请输入成员id" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Family" lang="ts">
|
||||||
|
import { listFamily, getFamily, delFamily, addFamily, updateFamily, changeFamilyStatus } from '@/api/app/family';
|
||||||
|
import { FamilyVO, FamilyQuery, FamilyForm } from '@/api/app/family/types';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
const familyList = ref<FamilyVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const familyFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: FamilyForm = {
|
||||||
|
id: undefined,
|
||||||
|
parentId: undefined,
|
||||||
|
parentName: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
status: undefined
|
||||||
|
};
|
||||||
|
const data = reactive<PageData<FamilyForm, FamilyQuery>>({
|
||||||
|
form: { ...initFormData },
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
parentId: undefined,
|
||||||
|
parentName: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
status: undefined,
|
||||||
|
params: {}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
id: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||||
|
parentId: [{ required: true, message: '家长id不能为空', trigger: 'blur' }],
|
||||||
|
userId: [{ required: true, message: '成员id不能为空', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询家庭成员列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listFamily(queryParams.value);
|
||||||
|
familyList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = { ...initFormData };
|
||||||
|
familyFormRef.value?.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: FamilyVO[]) => {
|
||||||
|
ids.value = selection.map((item) => item.id);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '添加家庭成员';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: FamilyVO) => {
|
||||||
|
reset();
|
||||||
|
const _id = row?.id || ids.value[0];
|
||||||
|
const res = await getFamily(_id);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '修改家庭成员';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
familyFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateFamily(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
} else {
|
||||||
|
await addFamily(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: FamilyVO) => {
|
||||||
|
const _ids = row?.id || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除家庭成员编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||||
|
await delFamily(_ids);
|
||||||
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
|
await getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download(
|
||||||
|
'app/family/export',
|
||||||
|
{
|
||||||
|
...queryParams.value
|
||||||
|
},
|
||||||
|
`family_${new Date().getTime()}.xlsx`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 用户状态修改 */
|
||||||
|
const handleStatusChange = async (row: FamilyVO) => {
|
||||||
|
const text = row.status === '0' ? '启用' : '停用';
|
||||||
|
try {
|
||||||
|
await proxy?.$modal.confirm('确认要"' + text + '""' + (row.parentName || row.id) + '"家庭吗?');
|
||||||
|
await changeFamilyStatus(row.id, row.status);
|
||||||
|
proxy?.$modal.msgSuccess(text + '成功');
|
||||||
|
} catch {
|
||||||
|
row.status = row.status === '0' ? '1' : '0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
237
src/views/app/familyDevice/index.vue
Normal file
237
src/views/app/familyDevice/index.vue
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="用户昵称" prop="nickName">
|
||||||
|
<el-input v-model="queryParams.nickName" placeholder="请输入用户昵称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备编号" prop="deviceNo">
|
||||||
|
<el-input v-model="queryParams.deviceNo" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备名称" prop="deviceName">
|
||||||
|
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['app:familyDevice:add']">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['app:familyDevice:edit']">修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['app:familyDevice:remove']">删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['app:familyDevice:export']">导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="familyDeviceList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="用户ID" align="center" prop="userId" v-if="true" />
|
||||||
|
<el-table-column label="用户昵称" align="center" prop="nickName" />
|
||||||
|
<el-table-column label="" align="center" prop="deviceId" v-if="true" />
|
||||||
|
<el-table-column label="设备编号" align="center" prop="deviceNo" />
|
||||||
|
<el-table-column label="设备名称" align="center" prop="deviceName" />
|
||||||
|
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tooltip content="修改" placement="top">
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['app:familyDevice:edit']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="删除" placement="top">
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['app:familyDevice:remove']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改家庭设备关联对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="familyDeviceFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="用户昵称" prop="nickName">
|
||||||
|
<el-input v-model="form.nickName" placeholder="请输入用户昵称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备编号" prop="deviceNo">
|
||||||
|
<el-input v-model="form.deviceNo" placeholder="请输入设备编号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备名称" prop="deviceName">
|
||||||
|
<el-input v-model="form.deviceName" placeholder="请输入设备名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="FamilyDevice" lang="ts">
|
||||||
|
import { listFamilyDevice, getFamilyDevice, delFamilyDevice, addFamilyDevice, updateFamilyDevice } from '@/api/app/familyDevice';
|
||||||
|
import { FamilyDeviceVO, FamilyDeviceQuery, FamilyDeviceForm } from '@/api/app/familyDevice/types';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
const familyDeviceList = ref<FamilyDeviceVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const familyDeviceFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: FamilyDeviceForm = {
|
||||||
|
userId: undefined,
|
||||||
|
nickName: undefined,
|
||||||
|
deviceId: undefined,
|
||||||
|
deviceNo: undefined,
|
||||||
|
deviceName: undefined,
|
||||||
|
}
|
||||||
|
const data = reactive<PageData<FamilyDeviceForm, FamilyDeviceQuery>>({
|
||||||
|
form: {...initFormData},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
nickName: undefined,
|
||||||
|
deviceNo: undefined,
|
||||||
|
deviceName: undefined,
|
||||||
|
params: {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
userId: [
|
||||||
|
{ required: true, message: "用户ID不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
nickName: [
|
||||||
|
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
deviceId: [
|
||||||
|
{ required: true, message: "不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询家庭设备关联列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listFamilyDevice(queryParams.value);
|
||||||
|
familyDeviceList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = {...initFormData};
|
||||||
|
familyDeviceFormRef.value?.resetFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: FamilyDeviceVO[]) => {
|
||||||
|
ids.value = selection.map(item => item.userId);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加家庭设备关联";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: FamilyDeviceVO) => {
|
||||||
|
reset();
|
||||||
|
const _userId = row?.userId || ids.value[0]
|
||||||
|
const res = await getFamilyDevice(_userId);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改家庭设备关联";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
familyDeviceFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.userId) {
|
||||||
|
await updateFamilyDevice(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
} else {
|
||||||
|
await addFamilyDevice(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: FamilyDeviceVO) => {
|
||||||
|
const _userIds = row?.userId || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除家庭设备关联编号为"' + _userIds + '"的数据项?').finally(() => loading.value = false);
|
||||||
|
await delFamilyDevice(_userIds);
|
||||||
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download('app/familyDevice/export', {
|
||||||
|
...queryParams.value
|
||||||
|
}, `familyDevice_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
353
src/views/app/message/index.vue
Normal file
353
src/views/app/message/index.vue
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="告警类型" prop="category">
|
||||||
|
<el-select v-model="queryParams.category" placeholder="请选择告警类型" clearable @change="handleQuery">
|
||||||
|
<el-option v-for="item in categoryOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="告警说明" prop="categoryName">-->
|
||||||
|
<!-- <el-input v-model="queryParams.categoryName" placeholder="请输入告警说明" clearable @keyup.enter="handleQuery" />-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<!-- <el-form-item label="视频地址" prop="video">
|
||||||
|
<el-input v-model="queryParams.video" placeholder="请输入视频地址" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>-->
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['app:message:add']">新增</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['app:message:edit']">修改</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['app:message:remove']"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['app:message:export']">导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="messageList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="ID" align="center" prop="id" v-if="true" />
|
||||||
|
<el-table-column label="设备ID" align="center" prop="deviceId" v-if="true" />
|
||||||
|
<el-table-column label="设备名" align="center" prop="deviceName" v-if="true" />
|
||||||
|
<el-table-column label="告警类型" align="center" prop="category" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="categoryTagType(scope.row.category)">
|
||||||
|
{{ categoryLabel(scope.row.category) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="告警说明" align="center" prop="categoryName" />
|
||||||
|
<el-table-column label="图片地址" align="center" prop="imageUrl" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<image-preview :src="scope.row.imageUrl" :width="50" :height="50" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="视频地址" align="center" prop="video" min-width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="scope.row.video">
|
||||||
|
<el-button link type="primary" @click="handlePlayVideo(scope.row.video)">
|
||||||
|
<el-icon><VideoPlay /></el-icon> 播放
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<span v-else class="text-gray-400 text-xs">-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<!-- <el-tooltip content="修改" placement="top">-->
|
||||||
|
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['app:message:edit']"></el-button>-->
|
||||||
|
<!-- </el-tooltip>-->
|
||||||
|
<el-tooltip content="删除" placement="top">
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['app:message:remove']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改告警消息列对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="messageFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="告警类型" prop="category">
|
||||||
|
<el-select v-model="form.category" placeholder="请选择告警类型">
|
||||||
|
<el-option v-for="item in categoryOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="告警说明" prop="categoryName">
|
||||||
|
<el-input v-model="form.categoryName" placeholder="请输入告警说明" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="图片地址" prop="image">
|
||||||
|
<image-upload v-model="form.image" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="视频地址" prop="video">
|
||||||
|
<el-input v-model="form.video" placeholder="请输入视频地址" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 视频播放弹窗 -->
|
||||||
|
<el-dialog title="视频播放" v-model="videoDialog.visible" width="720px" append-to-body :close-on-click-modal="false" @close="destroyPlayer">
|
||||||
|
<div ref="videoPlayerRef" class="video-player-wrap"></div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Message" lang="ts">
|
||||||
|
import { nextTick } from 'vue';
|
||||||
|
import { listMessage, getMessage, delMessage, addMessage, updateMessage } from '@/api/app/message';
|
||||||
|
import { MessageVO, MessageQuery, MessageForm } from '@/api/app/message/types';
|
||||||
|
import { VideoPlay } from '@element-plus/icons-vue';
|
||||||
|
import Player from 'xgplayer';
|
||||||
|
import 'xgplayer-flv';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
/** 视频播放器容器 ref */
|
||||||
|
const videoPlayerRef = ref<HTMLDivElement | null>(null);
|
||||||
|
/** xgplayer 实例 */
|
||||||
|
let player: InstanceType<typeof Player> | null = null;
|
||||||
|
|
||||||
|
/** 视频播放弹窗状态 */
|
||||||
|
const videoDialog = reactive<{ visible: boolean; url: string }>({
|
||||||
|
visible: false,
|
||||||
|
url: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 点击播放按钮 */
|
||||||
|
const handlePlayVideo = (url: string) => {
|
||||||
|
videoDialog.url = url;
|
||||||
|
videoDialog.visible = true;
|
||||||
|
nextTick(() => {
|
||||||
|
initPlayer(url);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 初始化 xgplayer 播放 FLV 流 */
|
||||||
|
const initPlayer = (url: string) => {
|
||||||
|
destroyPlayer();
|
||||||
|
if (!videoPlayerRef.value) return;
|
||||||
|
player = new Player({
|
||||||
|
el: videoPlayerRef.value,
|
||||||
|
url,
|
||||||
|
videoInit: true,
|
||||||
|
autoplay: true,
|
||||||
|
playsinline: true,
|
||||||
|
height: '100%',
|
||||||
|
width: '100%',
|
||||||
|
flv: {
|
||||||
|
mediaDataSource: {
|
||||||
|
isLive: true,
|
||||||
|
type: 'flv',
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 销毁播放器 */
|
||||||
|
const destroyPlayer = () => {
|
||||||
|
if (player) {
|
||||||
|
player.destroy();
|
||||||
|
player = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 告警类型选项 */
|
||||||
|
const categoryOptions = [
|
||||||
|
{ value: 1, label: '有人入侵' },
|
||||||
|
{ value: 2, label: '设备故障' },
|
||||||
|
{ value: 3, label: '到期提醒' }
|
||||||
|
];
|
||||||
|
|
||||||
|
/** 根据 category 值返回中文标签 */
|
||||||
|
const categoryLabel = (category: number): string => {
|
||||||
|
return categoryOptions.find((item) => item.value === category)?.label || category?.toString() || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 根据 category 值返回 el-tag 类型 */
|
||||||
|
const categoryTagType = (category: number): string => {
|
||||||
|
const map: Record<number, string> = { 1: 'danger', 2: 'warning', 3: 'info' };
|
||||||
|
return map[category] || 'info';
|
||||||
|
};
|
||||||
|
|
||||||
|
const messageList = ref<MessageVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const messageFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: MessageForm = {
|
||||||
|
id: undefined,
|
||||||
|
category: undefined,
|
||||||
|
categoryName: undefined,
|
||||||
|
image: undefined,
|
||||||
|
video: undefined
|
||||||
|
};
|
||||||
|
const data = reactive<PageData<MessageForm, MessageQuery>>({
|
||||||
|
form: { ...initFormData },
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
category: undefined,
|
||||||
|
categoryName: undefined,
|
||||||
|
image: undefined,
|
||||||
|
video: undefined,
|
||||||
|
params: {}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
id: [{ required: true, message: '不能为空', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询告警消息列列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listMessage(queryParams.value);
|
||||||
|
messageList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = { ...initFormData };
|
||||||
|
messageFormRef.value?.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: MessageVO[]) => {
|
||||||
|
ids.value = selection.map((item) => item.id);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '添加告警消息列';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: MessageVO) => {
|
||||||
|
reset();
|
||||||
|
const _id = row?.id || ids.value[0];
|
||||||
|
const res = await getMessage(_id);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '修改告警消息列';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
messageFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateMessage(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
} else {
|
||||||
|
await addMessage(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: MessageVO) => {
|
||||||
|
const _ids = row?.id || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除告警消息列编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||||
|
await delMessage(_ids);
|
||||||
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
|
await getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download(
|
||||||
|
'app/message/export',
|
||||||
|
{
|
||||||
|
...queryParams.value
|
||||||
|
},
|
||||||
|
`message_${new Date().getTime()}.xlsx`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.video-player-wrap {
|
||||||
|
width: 100%;
|
||||||
|
height: 60vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #000;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
432
src/views/app/user/index.vue
Normal file
432
src/views/app/user/index.vue
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="用户账号" prop="userName">
|
||||||
|
<el-input v-model="queryParams.userName" placeholder="请输入用户账号" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户昵称" prop="nickName">
|
||||||
|
<el-input v-model="queryParams.nickName" placeholder="请输入用户昵称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="身份证号" prop="idCard">
|
||||||
|
<el-input v-model="queryParams.idCard" placeholder="请输入身份证号" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户邮箱" prop="email">
|
||||||
|
<el-input v-model="queryParams.email" placeholder="请输入用户邮箱" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号码" prop="phonenumber">
|
||||||
|
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<!-- <template #header>-->
|
||||||
|
<!-- <el-row :gutter="10" class="mb8">-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['app:user:add']">新增</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['app:user:edit']">修改</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['app:user:remove']"-->
|
||||||
|
<!-- >删除</el-button-->
|
||||||
|
<!-- >-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="1.5">-->
|
||||||
|
<!-- <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['app:user:export']">导出</el-button>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>-->
|
||||||
|
<!-- </el-row>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="用户ID" align="center" prop="userId" v-if="true" />
|
||||||
|
<el-table-column label="用户账号" align="center" prop="userName">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ scope.row.phonenumber || scope.row.email || scope.row.userName || '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="用户昵称" align="center" prop="nickName" />
|
||||||
|
<el-table-column label="身份证号" align="center" prop="idCard" />
|
||||||
|
<!-- <el-table-column label="用户类型" align="center" prop="userType" />-->
|
||||||
|
<el-table-column label="用户邮箱" align="center" prop="email" />
|
||||||
|
<el-table-column label="手机号码" align="center" prop="phonenumber" />
|
||||||
|
<el-table-column label="用户性别" align="center" prop="sex" />
|
||||||
|
<!-- <el-table-column label="头像地址" align="center" prop="avatar" />-->
|
||||||
|
<el-table-column label="头像地址" align="center" prop="avatar" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<image-preview :src="scope.row.avatar" :width="50" :height="50" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<!-- <el-table-column label="密码" align="center" prop="password" />-->
|
||||||
|
<el-table-column label="账号状态" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="人脸" align="center" prop="faceAddr" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="face-image-list" v-if="scope.row.faceAddr">
|
||||||
|
<el-image
|
||||||
|
v-for="(url, idx) in faceUrls(scope.row.faceAddr)"
|
||||||
|
:key="idx"
|
||||||
|
:src="url"
|
||||||
|
:preview-src-list="faceUrls(scope.row.faceAddr)"
|
||||||
|
:initial-index="idx"
|
||||||
|
fit="cover"
|
||||||
|
style="width:40px;height:40px"
|
||||||
|
preview-teleported
|
||||||
|
>
|
||||||
|
<template #error>
|
||||||
|
<div class="face-error-slot">
|
||||||
|
<el-icon><PictureFilled /></el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-image>
|
||||||
|
</div>
|
||||||
|
<span v-else class="text-gray-400 text-xs">-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="手机mac地址" align="center" prop="mac" />
|
||||||
|
<!-- <el-table-column label="邀请码" align="center" prop="inviteUsed" />
|
||||||
|
<el-table-column label="邀请码创建时间" align="center" prop="inviteTime" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.inviteTime, '{y}-{m}-{d}') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>-->
|
||||||
|
<el-table-column label="最后登录IP" align="center" prop="loginIp" />
|
||||||
|
<el-table-column label="最后登录时间" align="center" prop="loginDate" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.loginDate, '{y}-{m}-{d}') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<!-- <el-table-column label="备注" align="center" prop="remark" />-->
|
||||||
|
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<!-- <el-tooltip content="修改" placement="top">-->
|
||||||
|
<!-- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['app:user:edit']"></el-button>-->
|
||||||
|
<!-- </el-tooltip>-->
|
||||||
|
<el-tooltip content="删除" placement="top">
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['app:user:remove']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="重置密码" placement="top">
|
||||||
|
<el-button link type="primary" icon="Key" @click="handleResetPwd(scope.row)" v-hasPermi="['app:user:resetPwd']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改app用户信息对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="userFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="用户账号" prop="userName">
|
||||||
|
<el-input v-model="form.userName" placeholder="请输入用户账号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户昵称" prop="nickName">
|
||||||
|
<el-input v-model="form.nickName" placeholder="请输入用户昵称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="身份证号" prop="idCard">
|
||||||
|
<el-input v-model="form.idCard" placeholder="请输入身份证号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户邮箱" prop="email">
|
||||||
|
<el-input v-model="form.email" placeholder="请输入用户邮箱" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号码" prop="phonenumber">
|
||||||
|
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="头像地址" prop="avatar">
|
||||||
|
<el-input v-model="form.avatar" placeholder="请输入头像地址" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" prop="password">
|
||||||
|
<el-input v-model="form.password" placeholder="请输入密码" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="人脸" prop="faceAddr">
|
||||||
|
<el-input v-model="form.faceAddr" placeholder="请输入人脸" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机mac地址" prop="mac">
|
||||||
|
<el-input v-model="form.mac" placeholder="请输入手机mac地址" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="邀请码" prop="inviteUsed">
|
||||||
|
<el-input v-model="form.inviteUsed" placeholder="请输入邀请码" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="邀请码创建时间" prop="inviteTime">
|
||||||
|
<el-date-picker clearable v-model="form.inviteTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择邀请码创建时间">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="最后登录IP" prop="loginIp">
|
||||||
|
<el-input v-model="form.loginIp" placeholder="请输入最后登录IP" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="最后登录时间" prop="loginDate">
|
||||||
|
<el-date-picker clearable v-model="form.loginDate" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择最后登录时间">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="User" lang="ts">
|
||||||
|
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus } from '@/api/app/user';
|
||||||
|
import { UserVO, UserQuery, UserForm } from '@/api/app/user/types';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
/** 将逗号分隔的人脸地址拆分为数组 */
|
||||||
|
const faceUrls = (faceAddr: string): string[] => {
|
||||||
|
if (!faceAddr) return [];
|
||||||
|
return faceAddr.split(',').map(u => u.trim()).filter(Boolean);
|
||||||
|
};
|
||||||
|
|
||||||
|
const userList = ref<UserVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const userFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: UserForm = {
|
||||||
|
userId: undefined,
|
||||||
|
userName: undefined,
|
||||||
|
nickName: undefined,
|
||||||
|
idCard: undefined,
|
||||||
|
userType: undefined,
|
||||||
|
email: undefined,
|
||||||
|
phonenumber: undefined,
|
||||||
|
sex: undefined,
|
||||||
|
avatar: undefined,
|
||||||
|
password: undefined,
|
||||||
|
status: undefined,
|
||||||
|
faceAddr: undefined,
|
||||||
|
mac: undefined,
|
||||||
|
inviteUsed: undefined,
|
||||||
|
inviteTime: undefined,
|
||||||
|
loginIp: undefined,
|
||||||
|
loginDate: undefined,
|
||||||
|
remark: undefined
|
||||||
|
};
|
||||||
|
const data = reactive<PageData<UserForm, UserQuery>>({
|
||||||
|
form: { ...initFormData },
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
userName: undefined,
|
||||||
|
nickName: undefined,
|
||||||
|
idCard: undefined,
|
||||||
|
userType: undefined,
|
||||||
|
email: undefined,
|
||||||
|
phonenumber: undefined,
|
||||||
|
sex: undefined,
|
||||||
|
avatar: undefined,
|
||||||
|
password: undefined,
|
||||||
|
status: undefined,
|
||||||
|
faceAddr: undefined,
|
||||||
|
mac: undefined,
|
||||||
|
inviteUsed: undefined,
|
||||||
|
inviteTime: undefined,
|
||||||
|
loginIp: undefined,
|
||||||
|
loginDate: undefined,
|
||||||
|
params: {}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
userId: [{ required: true, message: '用户ID不能为空', trigger: 'blur' }],
|
||||||
|
userName: [{ required: true, message: '用户账号不能为空', trigger: 'blur' }],
|
||||||
|
nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询app用户信息列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listUser(queryParams.value);
|
||||||
|
userList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = { ...initFormData };
|
||||||
|
userFormRef.value?.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: UserVO[]) => {
|
||||||
|
ids.value = selection.map((item) => item.userId);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '添加app用户信息';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: UserVO) => {
|
||||||
|
reset();
|
||||||
|
const _userId = row?.userId || ids.value[0];
|
||||||
|
const res = await getUser(_userId);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '修改app用户信息';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
userFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.userId) {
|
||||||
|
await updateUser(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
} else {
|
||||||
|
await addUser(form.value).finally(() => (buttonLoading.value = false));
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: UserVO) => {
|
||||||
|
const _userIds = row?.userId || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除app用户信息编号为"' + _userIds + '"的数据项?').finally(() => (loading.value = false));
|
||||||
|
await delUser(_userIds);
|
||||||
|
proxy?.$modal.msgSuccess('删除成功');
|
||||||
|
await getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download(
|
||||||
|
'app/user/export',
|
||||||
|
{
|
||||||
|
...queryParams.value
|
||||||
|
},
|
||||||
|
`user_${new Date().getTime()}.xlsx`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 用户状态修改 */
|
||||||
|
const handleStatusChange = async (row: UserVO) => {
|
||||||
|
const text = row.status === '0' ? '启用' : '停用';
|
||||||
|
try {
|
||||||
|
await proxy?.$modal.confirm('确认要"' + text + '""' + (row.phonenumber || row.email || row.userName) + '"用户吗?');
|
||||||
|
await changeUserStatus(row.userId, row.status);
|
||||||
|
proxy?.$modal.msgSuccess(text + '成功');
|
||||||
|
} catch {
|
||||||
|
row.status = row.status === '0' ? '1' : '0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 重置密码按钮操作 */
|
||||||
|
const handleResetPwd = async (row: UserVO) => {
|
||||||
|
const res = await ElMessageBox.prompt('请输入"' + (row.phonenumber || row.email || row.userName) + '"的新密码', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
inputPattern: /^.{5,20}$/,
|
||||||
|
inputErrorMessage: '用户密码长度必须介于 5 和 20 之间',
|
||||||
|
inputValidator: (value) => {
|
||||||
|
if (/<|>|"|'|\||\\/.test(value)) {
|
||||||
|
return '不能包含非法字符:< > " \' \\ |';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (res) {
|
||||||
|
await resetUserPwd(row.userId, res.value);
|
||||||
|
proxy?.$modal.msgSuccess('修改成功,新密码是:' + res.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.face-image-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.face-image-list .el-image {
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 0 3px 1px #ddd;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.face-image-list .el-image:hover {
|
||||||
|
transform: scale(1.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.face-error-slot {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
color: #c0c4cc;
|
||||||
|
font-size: 20px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
252
src/views/app/userdeviceToken/index.vue
Normal file
252
src/views/app/userdeviceToken/index.vue
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="账号用户id" prop="userId">
|
||||||
|
<el-input v-model="queryParams.userId" placeholder="请输入账号用户id" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备token" prop="token">
|
||||||
|
<el-input v-model="queryParams.token" placeholder="请输入设备token" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="平台 iOS/Android" prop="platform">
|
||||||
|
<el-input v-model="queryParams.platform" placeholder="请输入平台 iOS/Android" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="" prop="createdTime">
|
||||||
|
<el-date-picker clearable
|
||||||
|
v-model="queryParams.createdTime"
|
||||||
|
type="date"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
placeholder="请选择"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['app:userdeviceToken:add']">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['app:userdeviceToken:edit']">修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['app:userdeviceToken:remove']">删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['app:userdeviceToken:export']">导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="userdeviceTokenList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="" align="center" prop="id" v-if="true" />
|
||||||
|
<el-table-column label="账号用户id" align="center" prop="userId" />
|
||||||
|
<el-table-column label="设备token" align="center" prop="token" />
|
||||||
|
<el-table-column label="平台 iOS/Android" align="center" prop="platform" />
|
||||||
|
<el-table-column label="" align="center" prop="createdTime" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createdTime, '{y}-{m}-{d}') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tooltip content="修改" placement="top">
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['app:userdeviceToken:edit']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="删除" placement="top">
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['app:userdeviceToken:remove']"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改推送用户手机token对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="userdeviceTokenFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="账号用户id" prop="userId">
|
||||||
|
<el-input v-model="form.userId" placeholder="请输入账号用户id" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备token" prop="token">
|
||||||
|
<el-input v-model="form.token" placeholder="请输入设备token" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="平台 iOS/Android" prop="platform">
|
||||||
|
<el-input v-model="form.platform" placeholder="请输入平台 iOS/Android" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="" prop="createdTime">
|
||||||
|
<el-date-picker clearable
|
||||||
|
v-model="form.createdTime"
|
||||||
|
type="datetime"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
placeholder="请选择">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="UserdeviceToken" lang="ts">
|
||||||
|
import { listUserdeviceToken, getUserdeviceToken, delUserdeviceToken, addUserdeviceToken, updateUserdeviceToken } from '@/api/app/userdeviceToken';
|
||||||
|
import { UserdeviceTokenVO, UserdeviceTokenQuery, UserdeviceTokenForm } from '@/api/app/userdeviceToken/types';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
const userdeviceTokenList = ref<UserdeviceTokenVO[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref<Array<string | number>>([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const userdeviceTokenFormRef = ref<ElFormInstance>();
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const initFormData: UserdeviceTokenForm = {
|
||||||
|
id: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
token: undefined,
|
||||||
|
platform: undefined,
|
||||||
|
createdTime: undefined,
|
||||||
|
}
|
||||||
|
const data = reactive<PageData<UserdeviceTokenForm, UserdeviceTokenQuery>>({
|
||||||
|
form: {...initFormData},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
userId: undefined,
|
||||||
|
token: undefined,
|
||||||
|
platform: undefined,
|
||||||
|
createdTime: undefined,
|
||||||
|
params: {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
id: [
|
||||||
|
{ required: true, message: "不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询推送用户手机token列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listUserdeviceToken(queryParams.value);
|
||||||
|
userdeviceTokenList.value = res.rows;
|
||||||
|
total.value = res.total;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
const reset = () => {
|
||||||
|
form.value = {...initFormData};
|
||||||
|
userdeviceTokenFormRef.value?.resetFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
const handleSelectionChange = (selection: UserdeviceTokenVO[]) => {
|
||||||
|
ids.value = selection.map(item => item.id);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加推送用户手机token";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row?: UserdeviceTokenVO) => {
|
||||||
|
reset();
|
||||||
|
const _id = row?.id || ids.value[0]
|
||||||
|
const res = await getUserdeviceToken(_id);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改推送用户手机token";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
userdeviceTokenFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateUserdeviceToken(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
} else {
|
||||||
|
await addUserdeviceToken(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
|
dialog.visible = false;
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row?: UserdeviceTokenVO) => {
|
||||||
|
const _ids = row?.id || ids.value;
|
||||||
|
await proxy?.$modal.confirm('是否确认删除推送用户手机token编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
|
||||||
|
await delUserdeviceToken(_ids);
|
||||||
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
|
await getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
const handleExport = () => {
|
||||||
|
proxy?.download('app/userdeviceToken/export', {
|
||||||
|
...queryParams.value
|
||||||
|
}, `userdeviceToken_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,165 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container home">
|
<div class="app-container home">
|
||||||
<el-row :gutter="20">
|
<div class="welcome-wrapper">
|
||||||
<el-col :sm="24" :lg="12" style="padding-left: 20px">
|
<h1 class="welcome-title">欢迎使用智能防御机管理系统</h1>
|
||||||
<h2>RuoYi-Vue-Plus多租户管理系统</h2>
|
<p class="welcome-desc">智能防御 · 安全守护</p>
|
||||||
<p>
|
</div>
|
||||||
RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 分布式集群 场景升级(不兼容原框架)
|
|
||||||
<br />
|
|
||||||
* 前端开发框架 Vue3、TS、Element Plus<br />
|
|
||||||
* 后端开发框架 Spring Boot<br />
|
|
||||||
* 容器框架 Undertow 基于 Netty 的高性能容器<br />
|
|
||||||
* 权限认证框架 Sa-Token 支持多终端认证系统<br />
|
|
||||||
* 关系数据库 MySQL 适配 8.X 最低 5.7<br />
|
|
||||||
* 缓存数据库 Redis 适配 6.X 最低 4.X<br />
|
|
||||||
* 数据库框架 Mybatis-Plus 快速 CRUD 增加开发效率<br />
|
|
||||||
* 数据库框架 p6spy 更强劲的 SQL 分析<br />
|
|
||||||
* 多数据源框架 dynamic-datasource 支持主从与多种类数据库异构<br />
|
|
||||||
* 序列化框架 Jackson 统一使用 jackson 高效可靠<br />
|
|
||||||
* Redis客户端 Redisson 性能强劲、API丰富<br />
|
|
||||||
* 分布式限流 Redisson 全局、请求IP、集群ID 多种限流<br />
|
|
||||||
* 分布式锁 Lock4j 注解锁、工具锁 多种多样<br />
|
|
||||||
* 分布式幂等 Lock4j 基于分布式锁实现<br />
|
|
||||||
* 分布式链路追踪 SkyWalking 支持链路追踪、网格分析、度量聚合、可视化<br />
|
|
||||||
* 分布式任务调度 SnailJob 高性能 高可靠 易扩展<br />
|
|
||||||
* 文件存储 Minio 本地存储<br />
|
|
||||||
* 文件存储 七牛、阿里、腾讯 云存储<br />
|
|
||||||
* 监控框架 SpringBoot-Admin 全方位服务监控<br />
|
|
||||||
* 校验框架 Validation 增强接口安全性 严谨性<br />
|
|
||||||
* Excel框架 FastExcel(原Alibaba EasyExcel) 性能优异 扩展性强<br />
|
|
||||||
* 文档框架 SpringDoc、javadoc 无注解零入侵基于java注释<br />
|
|
||||||
* 工具类框架 Hutool、Lombok 减少代码冗余 增加安全性<br />
|
|
||||||
* 代码生成器 适配MP、SpringDoc规范化代码 一键生成前后端代码<br />
|
|
||||||
* 部署方式 Docker 容器编排 一键部署业务集群<br />
|
|
||||||
* 国际化 SpringMessage Spring标准国际化方案<br />
|
|
||||||
</p>
|
|
||||||
<p><b>当前版本:</b> <span>v5.6.0</span></p>
|
|
||||||
<p>
|
|
||||||
<el-tag type="danger">¥免费开源</el-tag>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访问码云</el-button>
|
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访问GitHub</el-button>
|
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')"
|
|
||||||
>更新日志</el-button
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<el-col :sm="24" :lg="12" style="padding-left: 20px">
|
|
||||||
<h2>RuoYi-Cloud-Plus多租户微服务管理系统</h2>
|
|
||||||
<p>
|
|
||||||
RuoYi-Cloud-Plus 微服务通用权限管理系统 重写 RuoYi-Cloud 全方位升级(不兼容原框架)
|
|
||||||
<br />
|
|
||||||
* 前端开发框架 Vue3、TS、Element UI<br />
|
|
||||||
* 后端开发框架 Spring Boot<br />
|
|
||||||
* 微服务开发框架 Spring Cloud、Spring Cloud Alibaba<br />
|
|
||||||
* 容器框架 Undertow 基于 XNIO 的高性能容器<br />
|
|
||||||
* 权限认证框架 Sa-Token、Jwt 支持多终端认证系统<br />
|
|
||||||
* 关系数据库 MySQL 适配 8.X 最低 5.7<br />
|
|
||||||
* 关系数据库 Oracle 适配 11g 12c<br />
|
|
||||||
* 关系数据库 PostgreSQL 适配 13 14<br />
|
|
||||||
* 关系数据库 SQLServer 适配 2017 2019<br />
|
|
||||||
* 缓存数据库 Redis 适配 6.X 最低 5.X<br />
|
|
||||||
* 分布式注册中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
|
|
||||||
* 分布式配置中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
|
|
||||||
* 服务网关 Spring Cloud Gateway 响应式高性能网关<br />
|
|
||||||
* 负载均衡 Spring Cloud Loadbalancer 负载均衡处理<br />
|
|
||||||
* RPC远程调用 Apache Dubbo 原生态使用体验、高性能<br />
|
|
||||||
* 分布式限流熔断 Alibaba Sentinel 无侵入、高扩展<br />
|
|
||||||
* 分布式事务 Alibaba Seata 无侵入、高扩展 支持 四种模式<br />
|
|
||||||
* 分布式消息队列 Apache Kafka 高性能高速度<br />
|
|
||||||
* 分布式消息队列 Apache RocketMQ 高可用功能多样<br />
|
|
||||||
* 分布式消息队列 RabbitMQ 支持各种扩展插件功能多样性<br />
|
|
||||||
* 分布式搜索引擎 ElasticSearch 业界知名<br />
|
|
||||||
* 分布式链路追踪 Apache SkyWalking 链路追踪、网格分析、度量聚合、可视化<br />
|
|
||||||
* 分布式日志中心 ELK 业界成熟解决方案<br />
|
|
||||||
* 分布式监控 Prometheus、Grafana 全方位性能监控<br />
|
|
||||||
* 其余与 Vue 版本一致<br />
|
|
||||||
</p>
|
|
||||||
<p><b>当前版本:</b> <span>v2.6.0</span></p>
|
|
||||||
<p>
|
|
||||||
<el-tag type="danger">¥免费开源</el-tag>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访问码云</el-button>
|
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访问GitHub</el-button>
|
|
||||||
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')"
|
|
||||||
>更新日志</el-button
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-divider />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Index" lang="ts">
|
<script setup name="Index" lang="ts">
|
||||||
const goTarget = (url: string) => {
|
|
||||||
window.open(url, '__blank');
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.home {
|
.home {
|
||||||
blockquote {
|
display: flex;
|
||||||
padding: 10px 20px;
|
align-items: center;
|
||||||
margin: 0 0 20px;
|
justify-content: center;
|
||||||
font-size: 17.5px;
|
min-height: calc(100vh - 120px);
|
||||||
border-left: 5px solid #eee;
|
}
|
||||||
}
|
|
||||||
hr {
|
.welcome-wrapper {
|
||||||
margin-top: 20px;
|
text-align: center;
|
||||||
margin-bottom: 20px;
|
|
||||||
border: 0;
|
.welcome-title {
|
||||||
border-top: 1px solid #eee;
|
font-size: 32px;
|
||||||
}
|
font-weight: 600;
|
||||||
.col-item {
|
color: #303133;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 16px;
|
||||||
|
letter-spacing: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
.welcome-desc {
|
||||||
padding: 0;
|
font-size: 16px;
|
||||||
margin: 0;
|
color: #909399;
|
||||||
}
|
letter-spacing: 4px;
|
||||||
|
|
||||||
font-family: 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
||||||
font-size: 13px;
|
|
||||||
color: #676a6c;
|
|
||||||
overflow-x: hidden;
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
margin-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin-top: 10px;
|
|
||||||
font-size: 26px;
|
|
||||||
font-weight: 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-top: 10px;
|
|
||||||
|
|
||||||
b {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.update-log {
|
|
||||||
ol {
|
|
||||||
display: block;
|
|
||||||
list-style-type: decimal;
|
|
||||||
margin-block-start: 1em;
|
|
||||||
margin-block-end: 1em;
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
padding-inline-start: 40px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -44,23 +44,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">{{ proxy.$t('login.rememberPassword') }}</el-checkbox>
|
<el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">{{ proxy.$t('login.rememberPassword') }}</el-checkbox>
|
||||||
<el-form-item style="float: right">
|
<!-- <el-form-item style="float: right">-->
|
||||||
<el-button circle :title="proxy.$t('login.social.wechat')" @click="doSocialLogin('wechat')">
|
<!-- <el-button circle :title="proxy.$t('login.social.wechat')" @click="doSocialLogin('wechat')">-->
|
||||||
<svg-icon icon-class="wechat" />
|
<!-- <svg-icon icon-class="wechat" />-->
|
||||||
</el-button>
|
<!-- </el-button>-->
|
||||||
<el-button circle :title="proxy.$t('login.social.maxkey')" @click="doSocialLogin('maxkey')">
|
<!-- <el-button circle :title="proxy.$t('login.social.maxkey')" @click="doSocialLogin('maxkey')">-->
|
||||||
<svg-icon icon-class="maxkey" />
|
<!-- <svg-icon icon-class="maxkey" />-->
|
||||||
</el-button>
|
<!-- </el-button>-->
|
||||||
<el-button circle :title="proxy.$t('login.social.topiam')" @click="doSocialLogin('topiam')">
|
<!-- <el-button circle :title="proxy.$t('login.social.topiam')" @click="doSocialLogin('topiam')">-->
|
||||||
<svg-icon icon-class="topiam" />
|
<!-- <svg-icon icon-class="topiam" />-->
|
||||||
</el-button>
|
<!-- </el-button>-->
|
||||||
<el-button circle :title="proxy.$t('login.social.gitee')" @click="doSocialLogin('gitee')">
|
<!-- <el-button circle :title="proxy.$t('login.social.gitee')" @click="doSocialLogin('gitee')">-->
|
||||||
<svg-icon icon-class="gitee" />
|
<!-- <svg-icon icon-class="gitee" />-->
|
||||||
</el-button>
|
<!-- </el-button>-->
|
||||||
<el-button circle :title="proxy.$t('login.social.github')" @click="doSocialLogin('github')">
|
<!-- <el-button circle :title="proxy.$t('login.social.github')" @click="doSocialLogin('github')">-->
|
||||||
<svg-icon icon-class="github" />
|
<!-- <svg-icon icon-class="github" />-->
|
||||||
</el-button>
|
<!-- </el-button>-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
<el-form-item style="width: 100%">
|
<el-form-item style="width: 100%">
|
||||||
<el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
|
<el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
|
||||||
<span v-if="!loading">{{ proxy.$t('login.login') }}</span>
|
<span v-if="!loading">{{ proxy.$t('login.login') }}</span>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<div class="el-login-footer">
|
<div class="el-login-footer">
|
||||||
<span>Copyright © 2018-2026 疯狂的狮子Li All Rights Reserved.</span>
|
<!-- <span>Copyright © 2018-2026 疯狂的狮子Li All Rights Reserved.</span>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -96,8 +96,10 @@ const { t } = useI18n();
|
|||||||
|
|
||||||
const loginForm = ref<LoginData>({
|
const loginForm = ref<LoginData>({
|
||||||
tenantId: '000000',
|
tenantId: '000000',
|
||||||
username: 'admin',
|
username: '',
|
||||||
password: 'admin123',
|
// username: 'admin',
|
||||||
|
// password: 'admin123',
|
||||||
|
password: '',
|
||||||
rememberMe: false,
|
rememberMe: false,
|
||||||
code: '',
|
code: '',
|
||||||
uuid: ''
|
uuid: ''
|
||||||
|
|||||||
Reference in New Issue
Block a user