Compare commits
55 Commits
feature/as
...
main
Author | SHA1 | Date | |
---|---|---|---|
0ef591ca1b | |||
edd7469ef2 | |||
acb1f89b0a | |||
a7ed0340b7 | |||
e6939183fe | |||
ac5c88a047 | |||
f0e9d7fda6 | |||
14e3f9ea4a | |||
68d834aec9 | |||
3e96223bd9 | |||
5d02cffcf4 | |||
14187ad9bc | |||
0772269c33 | |||
b55ba4003d | |||
502b4f3778 | |||
c8e00421b2 | |||
8b85e2d67c | |||
f956402648 | |||
c8d8fbf254 | |||
80fcfda16c | |||
a91c4397a4 | |||
5b1ff9749d | |||
8e2b5e1e2c | |||
9e5ff1544c | |||
d19c7fd240 | |||
b0d0194fe6 | |||
ccbacf9262 | |||
da8eb0d539 | |||
d05f9ab130 | |||
|
3d06cab696 | ||
5e13d284d3 | |||
4063c6a92d | |||
4769e77168 | |||
4ab4aeb7f0 | |||
eb60d1ed7d | |||
3a766f0db6 | |||
96fe7e279b | |||
258f28e056 | |||
2693ad5713 | |||
2dcfd957e5 | |||
deb193d242 | |||
01954e3f6e | |||
8c3e6b18f8 | |||
3460130e7e | |||
eee56c4273 | |||
ac867d368c | |||
f95f4cee85 | |||
5cb8e7da6e | |||
b6890e8311 | |||
14128e1fa8 | |||
bba1b2892e | |||
a7054c07b5 | |||
1a02d199ed | |||
c5345db462 | |||
3c876607ef |
@ -1,3 +1,4 @@
|
||||
VITE_API_BASEURL = "https://ibms-cvilux-api.production.mjmtech.com.tw"
|
||||
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
||||
VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
@ -1,3 +1,4 @@
|
||||
VITE_API_BASEURL = "https://ibms-cvilux-api.production.mjmtech.com.tw"
|
||||
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||
VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
||||
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
||||
# VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
@ -1,3 +1,3 @@
|
||||
VITE_API_BASEURL = "http://220.132.206.5:8008"
|
||||
VITE_FILE_API_BASEURL = "http://220.132.206.5:8085/file"
|
||||
VITE_FORGE_BASEURL = "http://localhost:5173"
|
||||
VITE_API_BASEURL = "https://ibms-cvilux-demo-api.production.mjmtech.com.tw"
|
||||
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
29
.github/prompts/exportCSV.prompt.md
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
mode: agent
|
||||
---
|
||||
# API 路徑整理與引用檢查規則
|
||||
|
||||
## 目標
|
||||
- 針對 apis 目錄下所有子資料夾(如 account、alert、asset、building、dashboard、energy、forge、graph、history、login、operation、productSetting、system)的 api.js 與 index.js 檔案,完整追蹤 API 路徑的實際引用情形。
|
||||
- 追蹤流程:
|
||||
1. 先在 api.js 找出所有 API 路徑常數(如 `export const GET_XXX_API = '/path'`)。
|
||||
2. 在 index.js 檔案確認這些常數有被 import 並包裝成 API function(如 `getXXX`)。
|
||||
3. 再全專案搜尋這些 API function 是否有被其他檔案 import 並呼叫。
|
||||
- 產生一份 csv 報表,格式如下:
|
||||
|
||||
| API 路徑 | 定義常數 | API function | 是否有被引用 |
|
||||
|----------|----------|--------------|-------------|
|
||||
| /user | GET_USER_API | getUser | Y |
|
||||
| /admin | GET_ADMIN_API | getAdmin | N |
|
||||
|
||||
## 詳細規則
|
||||
- 處理 apis 目錄下所有子資料夾的 api.js 與 index.js 檔案。
|
||||
- API 路徑的定義需涵蓋 get/post/put/delete 等(如 `export const API = '/path'`)。
|
||||
- 只統計有被 index.js import 並包裝成 function 的 API 路徑。
|
||||
- 檢查 function 是否有被其他檔案 import 並呼叫(排除 apis 目錄本身)。
|
||||
- 匹配到的檔案需記錄完整路徑,可多個檔案以分號分隔。
|
||||
- 統計結果輸出為 csv 檔案。
|
||||
|
||||
## 輸出
|
||||
- 檔名:api_usage_report.csv
|
||||
- 欄位:API 路徑, 定義常數, API function, 是否有被引用,
|
@ -3,7 +3,7 @@
|
||||
<html lang="en" data-theme="dracula">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.css"
|
||||
@ -12,11 +12,11 @@
|
||||
<title>Cvilux EMS</title>
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
|
||||
<script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>
|
||||
<script type="text/javascript" src="/requirejs/config.js"></script>
|
||||
<script
|
||||
<!-- <script type="text/javascript" src="/requirejs/config.js"></script> -->
|
||||
<!-- <script
|
||||
type="text/javascript"
|
||||
src="/module/js/com/tridium/js/ext/require/require.min.js?"
|
||||
></script>
|
||||
></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
909
package-lock.json
generated
@ -6,7 +6,8 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"build:staging": "vite build --mode staging"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
@ -21,13 +22,16 @@
|
||||
"date-fns": "^3.3.1",
|
||||
"dayjs": "^1.11.10",
|
||||
"echarts": "^5.4.3",
|
||||
"flag-icons": "^7.2.3",
|
||||
"jquery-ui": "^1.14.1",
|
||||
"json-schema-generator": "^2.0.6",
|
||||
"mqtt": "^5.10.3",
|
||||
"pinia": "^2.1.7",
|
||||
"requirejs": "^2.3.6",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-i18n": "^10.0.4",
|
||||
"vue-router": "^4.2.5",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"yup": "^1.4.0",
|
||||
"yup-phone-lite": "^2.0.1"
|
||||
},
|
||||
|
BIN
public/build_img.jpg
Normal file
After Width: | Height: | Size: 137 KiB |
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 8.9 KiB |
@ -18,15 +18,16 @@ const cancelToastOpen = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const openToast = (status, content, to = "body") => {
|
||||
const openToast = (status, content, to = "body", confirm = null) => {
|
||||
isToastOpen.value = {
|
||||
open: true,
|
||||
content,
|
||||
status,
|
||||
to,
|
||||
confirm,
|
||||
};
|
||||
};
|
||||
provide("app_toast", { openToast });
|
||||
provide("app_toast", { openToast, cancelToastOpen });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -35,6 +36,7 @@ provide("app_toast", { openToast });
|
||||
:open="isToastOpen.open"
|
||||
:status="isToastOpen.status"
|
||||
:cancel="cancelToastOpen"
|
||||
:confirm="isToastOpen.confirm"
|
||||
:to="isToastOpen.to"
|
||||
/>
|
||||
<div v-if="store.user.token" class="min-h-screen">
|
||||
|
@ -1,5 +1,6 @@
|
||||
export const POST_ACK_API = `/obix/alarm`;
|
||||
export const GET_ALERT_FORMID_API = `/Alert/AlertList`;
|
||||
export const GET_ALERT_LOG_API = `api/Alarm/GetAlarmLog`;
|
||||
export const POST_OPERATION_RECORD_API = `/operation/SavOpeRecord`;
|
||||
|
||||
export const GET_ALERT_SUB_LIST_API = `api/Device/GetMainSub`;
|
||||
@ -9,8 +10,17 @@ export const GET_ALERT_MEMBER = `api/Alarm/GetAlarmMember`;
|
||||
export const POST_ALERT_MEMBER = `api/Alarm/SaveAlarmMember`;
|
||||
export const DELETE_ALERT_MEMBER = `api/Alarm/DeleteAlarmMember`;
|
||||
export const GET_NOTICE_LIST_API = `api/Alarm/GetNotice`;
|
||||
export const GET_SHOW_ALERT_API = `api/Alarm/GetShowAlarm`; // 取得告警顯示清單
|
||||
|
||||
export const GET_OUTLIERS_LIST_API = `api/Alarm/GetAlarmSetting`;
|
||||
export const GET_OUTLIERS_DEVLIST_API = `api/Alarm/GetDevList`; // 取得設備
|
||||
export const GET_OUTLIERS_POINTS_API = `api/Alarm/GetAlarmPoints`; // 取得點位
|
||||
export const POST_OUTLIERS_SETTING_API = `api/Alarm/SaveAlarmSetting`; // 新增與修改
|
||||
export const DELETE_OUTLIERS_SETTING_API = `api/Alarm/DeleteAlarmSetting`; // 刪除
|
||||
export const GET_FACTOR_API = `api/Alarm/GetFactor`; // 刪除
|
||||
|
||||
export const GET_ALERT_SCHEDULE_LIST_API = `api/Alarm/GetAlarmSchedule`;
|
||||
export const POST_ALERT_SCHEDULE = `api/Alarm/SaveAlarmSchedule`;
|
||||
export const DELETE_ALERT_SCHEDULE = `api/Alarm/DeleteAlarmSchedule`;
|
||||
|
||||
export const POST_ALERT_MQTT_REFRESH = `api/Alarm/MQTTRefresh`;
|
@ -1,48 +1,28 @@
|
||||
import {
|
||||
POST_ACK_API,
|
||||
GET_ALERT_FORMID_API,
|
||||
GET_ALERT_LOG_API,
|
||||
POST_OPERATION_RECORD_API,
|
||||
GET_ALERT_SUB_LIST_API,
|
||||
GET_OUTLIERS_LIST_API,
|
||||
GET_OUTLIERS_DEVLIST_API,
|
||||
GET_OUTLIERS_POINTS_API,
|
||||
POST_OUTLIERS_SETTING_API,
|
||||
DELETE_OUTLIERS_SETTING_API,
|
||||
GET_FACTOR_API,
|
||||
GET_ALERT_MEMBER_LIST_API,
|
||||
GET_ALERT_MEMBER,
|
||||
POST_ALERT_MEMBER,
|
||||
DELETE_ALERT_MEMBER,
|
||||
GET_NOTICE_LIST_API,
|
||||
GET_SHOW_ALERT_API,
|
||||
GET_ALERT_SCHEDULE_LIST_API,
|
||||
POST_ALERT_SCHEDULE,
|
||||
DELETE_ALERT_SCHEDULE,
|
||||
POST_ALERT_MQTT_REFRESH
|
||||
} from "./api";
|
||||
import instance from "@/util/request";
|
||||
import apihandler from "@/util/apihandler";
|
||||
import axios from "axios";
|
||||
|
||||
export const postChgAck = async (uuid) => {
|
||||
try {
|
||||
const data =
|
||||
'<obj is="obix:AckAlarmIn"><str name="ackUser" val="obix" /></obj>';
|
||||
const res = await axios.post(`${POST_ACK_API}/${uuid}/ack`, data, {
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
});
|
||||
|
||||
// 解析XML錯誤信息
|
||||
const parser = new DOMParser();
|
||||
const xmlDoc = parser.parseFromString(res.data, "text/xml");
|
||||
const errElement = xmlDoc.querySelector("err");
|
||||
|
||||
if (errElement) {
|
||||
console.error("Error in acknowledging alarm");
|
||||
return { isSuccess: false, msg: `Error in acknowledging alarm` };
|
||||
}
|
||||
|
||||
return { isSuccess: true };
|
||||
} catch (error) {
|
||||
console.error("Error in acknowledging alarm:", error);
|
||||
return { isSuccess: false, msg: "Error in acknowledging alarm" };
|
||||
}
|
||||
};
|
||||
|
||||
export const getAlertFormId = async (uuid) => {
|
||||
const res = await instance.post(GET_ALERT_FORMID_API, uuid);
|
||||
@ -52,6 +32,24 @@ export const getAlertFormId = async (uuid) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getAlertLog = async ({
|
||||
Start_date,
|
||||
End_date,
|
||||
isRecovery,
|
||||
device_name_tag,
|
||||
}) => {
|
||||
const res = await instance.post(GET_ALERT_LOG_API, {
|
||||
Start_date,
|
||||
End_date,
|
||||
isRecovery,
|
||||
device_name_tag,
|
||||
});
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postOperationRecord = async (formData) => {
|
||||
const res = await instance.post(POST_OPERATION_RECORD_API, formData);
|
||||
|
||||
@ -61,8 +59,10 @@ export const postOperationRecord = async (formData) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getAlertSubList = async () => {
|
||||
const res = await instance.post(GET_ALERT_SUB_LIST_API, {});
|
||||
export const getAlertSubList = async (building_guid) => {
|
||||
const res = await instance.post(GET_ALERT_SUB_LIST_API, {
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
@ -148,6 +148,15 @@ export const getOutliersPoints = async (id) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getFactors = async () => {
|
||||
const res = await instance.post(GET_FACTOR_API);
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postOutliersSetting = async (data) => {
|
||||
const res = await instance.post(POST_OUTLIERS_SETTING_API, data);
|
||||
|
||||
@ -156,3 +165,63 @@ export const postOutliersSetting = async (data) => {
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const delOutliersSetting = async (Id) => {
|
||||
const res = await instance.post(DELETE_OUTLIERS_SETTING_API, {
|
||||
Id,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getShowAlarm = async () => {
|
||||
const res = await instance.post(GET_SHOW_ALERT_API);
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getAlarmScheduleList = async () => {
|
||||
const res = await instance.post(GET_ALERT_SCHEDULE_LIST_API, {});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postAlertSchedule = async (data) => {
|
||||
const res = await instance.post(POST_ALERT_SCHEDULE, data);
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteAlarmSchedule = async (id) => {
|
||||
try {
|
||||
const res = await instance.post(DELETE_ALERT_SCHEDULE, { id });
|
||||
return {
|
||||
isSuccess: res.code === "0000",
|
||||
msg: res.msg || "刪除成功",
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("API request failed", error);
|
||||
return { isSuccess: false, msg: "API request failed" };
|
||||
}
|
||||
};
|
||||
|
||||
export const postMQTTRefresh = async () => {
|
||||
const res = await instance.post(POST_ALERT_MQTT_REFRESH);
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
@ -1,5 +1,8 @@
|
||||
export const GET_ASSET_SUB_LIST_API = `/AssetManage/GetAssetSubList`;
|
||||
export const GET_ASSET_MAIN_LIST_API = `/AssetManage/GetAssetMainList`;
|
||||
export const DELETE_ASSET_MAIN_LIST_API = `/AssetManage/DeleteAssetMain`;
|
||||
export const POST_ASSET_MAIN_LIST_API = `/AssetManage/SaveAssetMain`;
|
||||
|
||||
export const GET_ASSET_SUB_LIST_API = `/AssetManage/GetAssetSubList`;
|
||||
export const POST_ASSET_SUB_LIST_API = `/AssetManage/SaveAssetSub`;
|
||||
export const DELETE_ASSET_SUB_LIST_API = `/AssetManage/DeleteAssetSub`;
|
||||
|
||||
@ -15,3 +18,22 @@ export const DELETE_ASSET_FLOOR_API = `/AssetManage/DeleteFloor`;
|
||||
|
||||
export const GET_ASSET_IOT_LIST_API = `/AssetManage/GetIOTList`;
|
||||
export const GET_ASSET_SUB_POINT_API = `/AssetManage/GetSubPoint`;
|
||||
|
||||
export const GET_ASSET_IOT_SCHEMA_API = `/AssetManage/GetResponseSchema`;
|
||||
export const POST_ASSET_IOT_SCHEMA_API = `/AssetManage/SaveResponseSchema`;
|
||||
|
||||
export const GET_ASSET_DEVICE_ITEM_API = `/AssetManage/GetDeviceItem`;
|
||||
export const POST_ASSET_DEVICE_ITEM_API = `/AssetManage/SaveDeviceItem`;
|
||||
export const DELETE_ASSET_DEVICE_ITEM_API = `/AssetManage/DeleteDeviceItem`;
|
||||
|
||||
export const GET_ASSET_DEPARTMENT_API = `/AssetManage/GetDepartment`;
|
||||
export const POST_ASSET_DEPARTMENT_API = `/AssetManage/SaveDepartment`;
|
||||
export const DELETE_ASSET_DEPARTMENT_API = `/AssetManage/DeleteDepartment`;
|
||||
|
||||
export const GET_ASSET_ELECTYPE_API = `/AssetManage/GetElecType`;
|
||||
export const POST_ASSET_ELECTYPE_API = `/AssetManage/SaveElecType`;
|
||||
export const DELETE_ASSET_ELECTYPE_API = `/AssetManage/DeleteElecType`;
|
||||
|
||||
export const POST_ASSET_ELEC_SETTING_API = `/AssetManage/SaveAssetSetting`;
|
||||
|
||||
export const POST_ASSET_MQTT_PUBLISH_API = `/api/mqtt/publish`;
|
@ -1,6 +1,8 @@
|
||||
import {
|
||||
GET_ASSET_SUB_LIST_API,
|
||||
GET_ASSET_MAIN_LIST_API,
|
||||
DELETE_ASSET_MAIN_LIST_API,
|
||||
POST_ASSET_MAIN_LIST_API,
|
||||
GET_ASSET_SUB_LIST_API,
|
||||
DELETE_ASSET_SUB_LIST_API,
|
||||
POST_ASSET_SUB_LIST_API,
|
||||
GET_ASSET_LIST_API,
|
||||
@ -12,13 +14,26 @@ import {
|
||||
DELETE_ASSET_ITEM_API,
|
||||
POST_ASSET_SINGLE_API,
|
||||
GET_ASSET_SUB_POINT_API,
|
||||
GET_ASSET_IOT_SCHEMA_API,
|
||||
POST_ASSET_IOT_SCHEMA_API,
|
||||
GET_ASSET_DEVICE_ITEM_API,
|
||||
POST_ASSET_DEVICE_ITEM_API,
|
||||
DELETE_ASSET_DEVICE_ITEM_API,
|
||||
GET_ASSET_DEPARTMENT_API,
|
||||
POST_ASSET_DEPARTMENT_API,
|
||||
DELETE_ASSET_DEPARTMENT_API,
|
||||
GET_ASSET_ELECTYPE_API,
|
||||
POST_ASSET_ELECTYPE_API,
|
||||
DELETE_ASSET_ELECTYPE_API,
|
||||
POST_ASSET_ELEC_SETTING_API,
|
||||
POST_ASSET_MQTT_PUBLISH_API,
|
||||
} from "./api";
|
||||
import instance from "@/util/request";
|
||||
import apihandler from "@/util/apihandler";
|
||||
import { object } from "yup";
|
||||
|
||||
export const getAssetSubList = async () => {
|
||||
const res = await instance.post(GET_ASSET_SUB_LIST_API);
|
||||
export const getAssetMainList = async (building_guid) => {
|
||||
const res = await instance.post(GET_ASSET_MAIN_LIST_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
@ -26,8 +41,8 @@ export const getAssetSubList = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getAssetMainList = async () => {
|
||||
const res = await instance.post(GET_ASSET_MAIN_LIST_API);
|
||||
export const deleteAssetMainItem = async (id) => {
|
||||
const res = await instance.post(DELETE_ASSET_MAIN_LIST_API, { id });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
@ -35,17 +50,17 @@ export const getAssetMainList = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const postAssetSubList = async ({
|
||||
export const postAssetMainList = async ({
|
||||
id,
|
||||
system_key,
|
||||
system_value,
|
||||
system_parent_id,
|
||||
id,
|
||||
building_guid,
|
||||
}) => {
|
||||
const res = await instance.post(POST_ASSET_SUB_LIST_API, {
|
||||
const res = await instance.post(POST_ASSET_MAIN_LIST_API, {
|
||||
id,
|
||||
system_key,
|
||||
system_value,
|
||||
system_parent_id,
|
||||
id,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
@ -54,6 +69,24 @@ export const postAssetSubList = async ({
|
||||
});
|
||||
};
|
||||
|
||||
export const getAssetSubList = async (id) => {
|
||||
const res = await instance.post(GET_ASSET_SUB_LIST_API, { id });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postAssetSubList = async (formData) => {
|
||||
const res = await instance.post(POST_ASSET_SUB_LIST_API, formData);
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteAssetSubItem = async (id) => {
|
||||
const res = await instance.post(DELETE_ASSET_SUB_LIST_API, { id });
|
||||
|
||||
@ -100,16 +133,15 @@ export const postAssetSingle = async (data) => {
|
||||
});
|
||||
} else {
|
||||
value.forEach((element, index) => {
|
||||
formData.append(`sub_device[${index}].device_number`, element.device_number);
|
||||
formData.append(
|
||||
`sub_device[${index}].device_number`,
|
||||
element.device_number
|
||||
);
|
||||
formData.append(`sub_device[${index}].points`, element.points);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (key === "device_number" && value === "") {
|
||||
formData.append(key, "0");
|
||||
} else {
|
||||
formData.append(key, value);
|
||||
}
|
||||
formData.append(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,8 +158,8 @@ export const deleteAssetItem = async (main_id) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getAssetFloorList = async () => {
|
||||
const res = await instance.post(GET_ASSET_FLOOR_LIST_API);
|
||||
export const getAssetFloorList = async (building_guid) => {
|
||||
const res = await instance.post(GET_ASSET_FLOOR_LIST_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
@ -175,3 +207,155 @@ export const getAssetSubPoint = async (sub_system_tag) => {
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getIOTSchema = async (variable_id) => {
|
||||
const res = await instance.post(GET_ASSET_IOT_SCHEMA_API, { variable_id });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postIOTSchema = async ({ name, variable_id, points }) => {
|
||||
const res = await instance.post(POST_ASSET_IOT_SCHEMA_API, {
|
||||
name,
|
||||
variable_id,
|
||||
points,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeviceItem = async (variable_id) => {
|
||||
const res = await instance.post(GET_ASSET_DEVICE_ITEM_API, { variable_id });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postDeviceItem = async ({
|
||||
id,
|
||||
variable_id,
|
||||
full_name,
|
||||
points,
|
||||
decimals,
|
||||
is_bool,
|
||||
is_link,
|
||||
show_event_switch_btn,
|
||||
event_switch_on_message,
|
||||
event_switch_off_message,
|
||||
}) => {
|
||||
const res = await instance.post(POST_ASSET_DEVICE_ITEM_API, {
|
||||
id,
|
||||
variable_id,
|
||||
full_name,
|
||||
points,
|
||||
decimals,
|
||||
is_bool,
|
||||
is_link,
|
||||
show_event_switch_btn,
|
||||
event_switch_on_message,
|
||||
event_switch_off_message,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteDeviceItem = async (id) => {
|
||||
const res = await instance.post(DELETE_ASSET_DEVICE_ITEM_API, { id });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getDepartmentList = async () => {
|
||||
const res = await instance.post(GET_ASSET_DEPARTMENT_API, {});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postDepartmentList = async ({ name, id }) => {
|
||||
const res = await instance.post(POST_ASSET_DEPARTMENT_API, {
|
||||
name,
|
||||
id,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteDepartmentItem = async (id) => {
|
||||
const res = await instance.post(DELETE_ASSET_DEPARTMENT_API, { id });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getElecTypeList = async () => {
|
||||
const res = await instance.post(GET_ASSET_ELECTYPE_API, {});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postElecTypeList = async ({ name, id }) => {
|
||||
const res = await instance.post(POST_ASSET_ELECTYPE_API, {
|
||||
name,
|
||||
id,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteElecTypeItem = async (id) => {
|
||||
const res = await instance.post(DELETE_ASSET_ELECTYPE_API, { id });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postAssetElecSetting = async (formData) => {
|
||||
const res = await instance.post(POST_ASSET_ELEC_SETTING_API, formData);
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postMQTTpublish = async ({ Topic, Payload }) => {
|
||||
const res = await instance.post(POST_ASSET_MQTT_PUBLISH_API, {
|
||||
Topic,
|
||||
Payload,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
@ -1,4 +1,6 @@
|
||||
export const GET_BUILDING_API = `/api/Device/GetBuild`;
|
||||
export const GET_BUILDING_API = `/AssetManage/GetBuildingList`;
|
||||
export const POST_BUILDING_API = `/AssetManage/SaveBuilding`;
|
||||
export const DELETE_BUILDING_API = `/AssetManage/DeleteBuilding`;
|
||||
export const GET_AUTHPAGE_API = `/api/GetUsrFroList`;
|
||||
export const GET_SUBAUTHPAGE_API = `/api/Device/GetMainSub`;
|
||||
export const GET_ALL_DEVICE_API = `/api/Device/GetAllDevice`;
|
||||
|
@ -1,5 +1,7 @@
|
||||
import {
|
||||
GET_BUILDING_API,
|
||||
POST_BUILDING_API,
|
||||
DELETE_BUILDING_API,
|
||||
GET_AUTHPAGE_API,
|
||||
GET_SUBAUTHPAGE_API,
|
||||
GET_ALL_DEVICE_API,
|
||||
@ -16,6 +18,27 @@ export const getBuildings = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const postBuildings = async ({ full_name, building_guid }) => {
|
||||
const res = await instance.post(POST_BUILDING_API, {
|
||||
full_name,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteBuildings = async (building_guid) => {
|
||||
const res = await instance.post(DELETE_BUILDING_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getAuth = async (lang) => {
|
||||
const res = await instance.post(GET_AUTHPAGE_API, {
|
||||
lang,
|
||||
@ -26,10 +49,8 @@ export const getAuth = async (lang) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getAllSysSidebar = async () => {
|
||||
const res = await instance.post(GET_SUBAUTHPAGE_API, {
|
||||
building_tag: "",
|
||||
});
|
||||
export const getAllSysSidebar = async (building_guid) => {
|
||||
const res = await instance.post(GET_SUBAUTHPAGE_API, {building_guid});
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
|
@ -6,4 +6,12 @@ export const GET_DASHBOARD_ROOM_TEMP_API = `/SituationRoom/GetFormulaRoomStatusD
|
||||
export const GET_DASHBOARD_ENERGY_API = `/SituationRoom/GetEnergeData`;
|
||||
export const POST_DASHBOARD_PRODUCT_TARGET_SETTING_API = `/SituationRoom/SetTargetSetting`;
|
||||
export const GET_DASHBOARD_PRODUCT_TARGET_SETTING_API = `/SituationRoom/GetTargetSetting`
|
||||
export const GET_DASHBOARD_PRODUCT_HISTORY_API = `/SituationRoom/GetProductionHistory`
|
||||
export const GET_DASHBOARD_PRODUCT_HISTORY_API = `/SituationRoom/GetProductionHistory`
|
||||
|
||||
export const GET_DASHBOARD_ENERGY_INFO_API = `api/dashboard/GetEnergyInfo`
|
||||
export const GET_DASHBOARD_ENERGY_COST_API = `api/dashboard/GetEnergyCost`
|
||||
export const GET_DASHBOARD_ALARMOPERATION_INFO_API = `api/dashboard/GetAlarmOperationInfo`
|
||||
|
||||
export const GET_DASHBOARD_2D3DINFO_API = `api/setting/visual/query`
|
||||
export const POST_DASHBOARD_2D3DINFO_API = `api/setting/visual/update`
|
||||
|
||||
|
@ -8,6 +8,11 @@ import {
|
||||
POST_DASHBOARD_PRODUCT_TARGET_SETTING_API,
|
||||
GET_DASHBOARD_PRODUCT_TARGET_SETTING_API,
|
||||
GET_DASHBOARD_PRODUCT_HISTORY_API,
|
||||
GET_DASHBOARD_ENERGY_INFO_API,
|
||||
GET_DASHBOARD_ENERGY_COST_API,
|
||||
GET_DASHBOARD_ALARMOPERATION_INFO_API,
|
||||
GET_DASHBOARD_2D3DINFO_API,
|
||||
POST_DASHBOARD_2D3DINFO_API
|
||||
} from "./api";
|
||||
import instance from "@/util/request";
|
||||
import apihandler from "@/util/apihandler";
|
||||
@ -135,3 +140,60 @@ export const getDashboardProductRecord = async ({ start_time, end_time }) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getEnergyInfo = async (building_guid) => {
|
||||
const res = await instance.post(GET_DASHBOARD_ENERGY_INFO_API, {
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getEnergyCost = async ({
|
||||
department_id,
|
||||
floor_guid,
|
||||
building_guid,
|
||||
}) => {
|
||||
const res = await instance.post(GET_DASHBOARD_ENERGY_COST_API, {
|
||||
department_id,
|
||||
floor_guid,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getAlarmOperationInfo = async (building_guid) => {
|
||||
const res = await instance.post(GET_DASHBOARD_ALARMOPERATION_INFO_API, {
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getDashboard2D3D = async (BuildingId) => {
|
||||
const res = await instance.post(GET_DASHBOARD_2D3DINFO_API, {
|
||||
BuildingId});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const posttDashboard2D3D = async (formData) => {
|
||||
const res = await instance.post(POST_DASHBOARD_2D3DINFO_API, formData);
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
23
src/apis/energy/api.js
Normal file
@ -0,0 +1,23 @@
|
||||
export const GET_REALTIME_DIST_API = `/api/Energe/GetRealTimeDistribution`;
|
||||
export const GET_ELECUSE_DAY_API = `/api/Energe/GetElecUseDay`;
|
||||
export const GET_TAI_POWER_API = `/api/Energe/GetTaipower`;
|
||||
|
||||
export const GET_SIDEBAR_API = `/api/GetSideBar`;
|
||||
export const GET_SEARCH_API = `/api/Energe/GetFilter`;
|
||||
|
||||
export const GET_REPORT_API = `/api/Energe/GetReport`;
|
||||
export const GET_Excel_API = `/api/Energe/GetReportExcel`;
|
||||
|
||||
// 即時需量
|
||||
export const GET_DEMAND_API = `/api/Energe/SearchDemandValue`;
|
||||
export const POST_ADD_DEMAND_API = `/api/Energe/AddDemandValue`;
|
||||
export const POST_EDIT_DEMAND_API = `/api/Energe/UpdateDemandValue`;
|
||||
export const GET_REALTIME_DEMAND_API = `/api/Energe/GetRealTimeDemand`;
|
||||
|
||||
// 碳排係數
|
||||
export const GET_CARBON_API = `/api/Energe/SearchCarbonValue`;
|
||||
export const POST_EDIT_CARBON_API = `/api/Energe/UpdateCarbonValue`;
|
||||
|
||||
// 時間電價
|
||||
export const GET_TIME_ELEC_API = `/api/Energe/SearchTimeElec`;
|
||||
export const POST_TIME_ELEC_API = `/api/Energe/UpdateTimeElecValue`;
|
232
src/apis/energy/index.js
Normal file
@ -0,0 +1,232 @@
|
||||
import {
|
||||
GET_REALTIME_DIST_API,
|
||||
GET_ELECUSE_DAY_API,
|
||||
GET_TAI_POWER_API,
|
||||
GET_SIDEBAR_API,
|
||||
GET_SEARCH_API,
|
||||
GET_REPORT_API,
|
||||
GET_Excel_API,
|
||||
GET_DEMAND_API,
|
||||
POST_EDIT_DEMAND_API,
|
||||
GET_REALTIME_DEMAND_API,
|
||||
GET_CARBON_API,
|
||||
POST_EDIT_CARBON_API,
|
||||
GET_TIME_ELEC_API,
|
||||
POST_TIME_ELEC_API,
|
||||
} from "./api";
|
||||
import instance, { fileInstance } from "@/util/request";
|
||||
import apihandler from "@/util/apihandler";
|
||||
import downloadExcel from "@/util/downloadExcel";
|
||||
|
||||
export const getRealTimeDist = async ({
|
||||
building_guid,
|
||||
department_id_list,
|
||||
floor_guid_list,
|
||||
}) => {
|
||||
const res = await instance.post(GET_REALTIME_DIST_API, {
|
||||
building_guid,
|
||||
department_id_list,
|
||||
floor_guid_list,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getElecUseDay = async ({
|
||||
building_guid,
|
||||
department_id_list,
|
||||
floor_guid_list,
|
||||
}) => {
|
||||
const res = await instance.post(GET_ELECUSE_DAY_API,{
|
||||
building_guid,
|
||||
department_id_list,
|
||||
floor_guid_list,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getTaipower = async ({
|
||||
coefficient,
|
||||
building_guid,
|
||||
department_id_list,
|
||||
floor_guid_list,
|
||||
}) => {
|
||||
const res = await instance.post(GET_TAI_POWER_API, {
|
||||
coefficient,
|
||||
building_guid,
|
||||
department_id_list,
|
||||
floor_guid_list,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getSideBar = async (system_type) => {
|
||||
const res = await instance.post(GET_SIDEBAR_API, { system_type });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getEnergySearch = async (type) => {
|
||||
const res = await instance.post(GET_SEARCH_API, { type });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getReport = async ({
|
||||
department,
|
||||
elecType,
|
||||
floor,
|
||||
start_time,
|
||||
end_time,
|
||||
type,
|
||||
}) => {
|
||||
const res = await instance.post(GET_REPORT_API, {
|
||||
department,
|
||||
elecType,
|
||||
floor,
|
||||
start_time,
|
||||
end_time,
|
||||
type,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getExcel = async ({
|
||||
department,
|
||||
elecType,
|
||||
floor,
|
||||
start_time,
|
||||
end_time,
|
||||
type,
|
||||
}) => {
|
||||
const res = await fileInstance.post(
|
||||
GET_Excel_API,
|
||||
{
|
||||
department,
|
||||
elecType,
|
||||
floor,
|
||||
start_time,
|
||||
end_time,
|
||||
type,
|
||||
},
|
||||
{ responseType: "blob" }
|
||||
);
|
||||
|
||||
return apihandler(
|
||||
res.code,
|
||||
res,
|
||||
{
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
},
|
||||
downloadExcel
|
||||
);
|
||||
};
|
||||
|
||||
export const getDemand = async (building_guid) => {
|
||||
const res = await instance.post(GET_DEMAND_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postEditDemand = async ({
|
||||
id,
|
||||
contract,
|
||||
alert,
|
||||
reset,
|
||||
building_guid,
|
||||
}) => {
|
||||
const res = await instance.put(POST_EDIT_DEMAND_API, {
|
||||
id,
|
||||
contract,
|
||||
alert,
|
||||
reset,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCarbonValue = async (building_guid) => {
|
||||
const res = await instance.post(GET_CARBON_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postEditCarbonValue = async ({
|
||||
id,
|
||||
coefficient,
|
||||
building_guid,
|
||||
}) => {
|
||||
const res = await instance.put(POST_EDIT_CARBON_API, {
|
||||
id,
|
||||
coefficient,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getRealTimeDemand = async (building_guid) => {
|
||||
const res = await instance.post(GET_REALTIME_DEMAND_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getTimeElec = async (building_guid) => {
|
||||
const res = await instance.post(GET_TIME_ELEC_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postTimeElec = async ({ sheet, cost, building_guid }) => {
|
||||
const res = await instance.put(POST_TIME_ELEC_API, {
|
||||
sheet,
|
||||
cost,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
@ -85,8 +85,8 @@ export const addGraphTableData = async (formData) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const delGraphData = async (id) => {
|
||||
const res = await instance.post(DELETE_GRAPH_TABLE_API, { id });
|
||||
export const delGraphData = async (id, hard_delete = false, recover_delete = false) => {
|
||||
const res = await instance.post(DELETE_GRAPH_TABLE_API, { id, hard_delete, recover_delete });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
|
@ -4,6 +4,10 @@ export const GET_HISTORY_SIDEBAR_API = `/api/History/GetDeviceInfo`;
|
||||
export const GET_HISTORY_POINT_API = `/api/History/GetAllDevPoi`;
|
||||
export const GET_HISTORY_DATA_API = `/api/History/GetHistoryData`;
|
||||
export const GET_HISTORY_EXPORT_API = `/api/ExportHistoryExcel`;
|
||||
export const GET_HISTORY_EXPORT_REPORT_API = `/api/History/GetHistoryExcelReport`;
|
||||
export const GET_HISTORY_EXPORT_CURVE_API = `/api/History/GetHistoricalCurveExcelReport`;
|
||||
export const GET_HISTORY_EXPORT_QUICK_API = `/api/History/GetQuickMeteringExcelReport`;
|
||||
export const GET_HISTORY_EXPORT_CLASS_API = `/api/History/GetElectricityClassificationExcelReport`;
|
||||
|
||||
export const GET_HISTORY_FAVORITE_API = `/api/History/GetHistoryFavorite`;
|
||||
export const POST_HISTORY_FAVORITE_API = `/api/History/SaveHistoryFavorite`;
|
||||
|
@ -7,14 +7,26 @@ import {
|
||||
DELETE_HISTORY_FAVORITE_API,
|
||||
UPDATE_HISTORY_FAVORITE_API,
|
||||
GET_HISTORY_EXPORT_API,
|
||||
GET_HISTORY_EXPORT_REPORT_API,
|
||||
GET_HISTORY_EXPORT_CURVE_API,
|
||||
GET_HISTORY_EXPORT_QUICK_API,
|
||||
GET_HISTORY_EXPORT_CLASS_API,
|
||||
} from "./api";
|
||||
import instance, { fileInstance } from "@/util/request";
|
||||
import apihandler from "@/util/apiHandler";
|
||||
import downloadExcel from "@/util/downloadExcel";
|
||||
|
||||
export const getHistorySideBar = async (sub_system_tag) => {
|
||||
export const getHistorySideBar = async ({
|
||||
sub_system_tag,
|
||||
department_id,
|
||||
elec_type_id,
|
||||
building_guid,
|
||||
}) => {
|
||||
const res = await instance.post(GET_HISTORY_SIDEBAR_API, {
|
||||
sub_system_tag,
|
||||
department_id,
|
||||
elec_type_id,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
@ -42,6 +54,7 @@ export const getHistoryData = async ({
|
||||
End_time,
|
||||
Device_list,
|
||||
Points,
|
||||
table_type,
|
||||
}) => {
|
||||
/*
|
||||
{
|
||||
@ -62,6 +75,7 @@ export const getHistoryData = async ({
|
||||
Device_list: Array.isArray(Device_list) ? Device_list : [Device_list],
|
||||
Points: Array.isArray(Points) ? Points : [Points],
|
||||
Type: parseInt(Type),
|
||||
table_type: parseInt(table_type),
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
@ -71,7 +85,52 @@ export const getHistoryData = async ({
|
||||
};
|
||||
|
||||
export const getHistoryExportData = async ({
|
||||
Start_date,
|
||||
End_date,
|
||||
Start_time,
|
||||
End_time,
|
||||
Device_list,
|
||||
Points,
|
||||
Type,
|
||||
table_type,
|
||||
}) => {
|
||||
const api =
|
||||
parseInt(table_type) === 1
|
||||
? GET_HISTORY_EXPORT_CURVE_API
|
||||
: parseInt(table_type) === 2
|
||||
? GET_HISTORY_EXPORT_QUICK_API
|
||||
: parseInt(table_type) === 3
|
||||
? GET_HISTORY_EXPORT_CLASS_API
|
||||
: GET_HISTORY_EXPORT_API;
|
||||
|
||||
const res = await fileInstance.post(
|
||||
api,
|
||||
{
|
||||
Start_date: Start_date,
|
||||
End_date: End_date,
|
||||
Start_time: Start_time,
|
||||
End_time: End_time,
|
||||
Points: Array.isArray(Points) ? Points : [Points],
|
||||
Device_list: Array.isArray(Device_list) ? Device_list : [Device_list],
|
||||
Type: parseInt(Type),
|
||||
Building_tag_list: [...new Set(Device_list.map((d) => d.split("_")[1]))],
|
||||
table_type: parseInt(table_type),
|
||||
},
|
||||
{ responseType: "blob" }
|
||||
);
|
||||
|
||||
return apihandler(
|
||||
res.code,
|
||||
res,
|
||||
{
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
},
|
||||
downloadExcel
|
||||
);
|
||||
};
|
||||
|
||||
export const getHistoryExportReport = async ({
|
||||
Start_date,
|
||||
End_date,
|
||||
Start_time,
|
||||
@ -79,19 +138,8 @@ export const getHistoryExportData = async ({
|
||||
Device_list,
|
||||
Points,
|
||||
}) => {
|
||||
/*
|
||||
{
|
||||
Type,
|
||||
Start_date,
|
||||
End_date,
|
||||
Start_time,
|
||||
End_time,
|
||||
Device_list,
|
||||
Points,
|
||||
}
|
||||
*/
|
||||
const res = await fileInstance.post(
|
||||
GET_HISTORY_EXPORT_API,
|
||||
GET_HISTORY_EXPORT_REPORT_API,
|
||||
{
|
||||
// ...exportContent,
|
||||
Start_date: Start_date,
|
||||
@ -100,7 +148,6 @@ export const getHistoryExportData = async ({
|
||||
End_time: End_time,
|
||||
Points: Array.isArray(Points) ? Points : [Points],
|
||||
Device_list: Array.isArray(Device_list) ? Device_list : [Device_list],
|
||||
Type: parseInt(Type),
|
||||
Building_tag_list: [...new Set(Device_list.map((d) => d.split("_")[1]))],
|
||||
},
|
||||
{ responseType: "blob" }
|
||||
|
@ -13,6 +13,10 @@ export async function Login({ account, password }) {
|
||||
document.cookie = `JWT-Authorization=${res.data.token}; Max-Age=${
|
||||
24 * 60 * 60 * 1000
|
||||
}`;
|
||||
// 設定 user_name Cookie
|
||||
document.cookie = `user_name=${res.data.user_name}; Max-Age=${
|
||||
24 * 60 * 60 * 1000
|
||||
}`;
|
||||
}
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
POST_OPERATION_RECORD_API,
|
||||
GET_OPERATION_EXPORT_API,
|
||||
GET_OPERATION_FORMID_API,
|
||||
DELETE_OPERATION_RECORD_API,
|
||||
POST_OPERATION_COMPANY_API,
|
||||
UPDATE_OPERATION_COMPANY_API,
|
||||
DELETE_OPERATION_COMPANY_API,
|
||||
@ -23,10 +24,10 @@ export const getOperationRecord = async ({
|
||||
}) => {
|
||||
const res = await instance.post(GET_OPERATION_RECORD_API, {
|
||||
work_type: parseInt(work_type),
|
||||
start_created_at: dayjs(start_created_at).format("YYYY-MM-DDTHH:mm:ss"),
|
||||
end_created_at: dayjs(end_created_at)
|
||||
.date(dayjs(end_created_at).get("date") + 1)
|
||||
.format("YYYY-MM-DDTHH:mm:ss"),
|
||||
// start_created_at: dayjs(start_created_at).format("YYYY-MM-DDTHH:mm:ss"),
|
||||
// end_created_at: dayjs(end_created_at)
|
||||
// .date(dayjs(end_created_at).get("date") + 1)
|
||||
// .format("YYYY-MM-DDTHH:mm:ss"),
|
||||
serial_number: serial_number || null,
|
||||
main_system_tag: null,
|
||||
sub_system_tag:
|
||||
|
@ -20,13 +20,13 @@ export const getSystemFloors = async (building_tag, sub_system_tag) => {
|
||||
|
||||
export const getSystemDevices = async ({
|
||||
sub_system_tag,
|
||||
building_tag,
|
||||
floor_tag,
|
||||
building_guid,
|
||||
department_id_list,
|
||||
}) => {
|
||||
const res = await instance.post(GET_SYSTEM_DEVICE_LIST_API, {
|
||||
sub_system_tag,
|
||||
building_tag,
|
||||
floor_tag,
|
||||
building_guid,
|
||||
department_id_list,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
|
@ -58,6 +58,7 @@
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
scrollbar-color: auto !important;
|
||||
}
|
||||
|
||||
body {
|
||||
|
@ -3,9 +3,9 @@
|
||||
<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 124.4 12" style="enable-background:new 0 0 124.4 12;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#0CA9D4;}
|
||||
.st0{fill:#17CEE3;}
|
||||
.st1{opacity:0.3;fill:#969696;}
|
||||
.st2{opacity:0.8;fill:#0CA9D4;}
|
||||
.st2{opacity:0.8;fill:#17CEE3;}
|
||||
</style>
|
||||
<g>
|
||||
<polygon class="st0" points="92.7,2.9 31.5,2.9 28.8,0 95.6,0 "/>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -1 +1,12 @@
|
||||
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 124.4 12.01"><defs><style>.cls-1,.cls-3{fill:#ffe422;}.cls-2{fill:#969696;opacity:0.3;}.cls-3{opacity:0.8;}</style></defs><polygon class="cls-1" points="92.68 2.87 31.5 2.87 28.8 0 95.59 0 92.68 2.87"/><path class="cls-2" d="M124.4.14V11.86c0,.08-.3.15-.66.15H97.84a2.27,2.27,0,0,1-.5,0l-1.76-.45a2.34,2.34,0,0,0-.5,0H29.76a2.2,2.2,0,0,0-.5,0L27.5,12a2.34,2.34,0,0,1-.5,0H.66C.3,12,0,11.94,0,11.86V.14C0,.06.3,0,.66,0L26.87.11a1.79,1.79,0,0,1,.5.05L29,2.25a2.27,2.27,0,0,0,.5,0H94.86a2.34,2.34,0,0,0,.5,0L97.25.16a1.83,1.83,0,0,1,.5,0l26-.11C124.1,0,124.4.06,124.4.14Z"/><path class="cls-3" d="M122.92,12V2.12a.89.89,0,0,0-.89-.89H96.41a.9.9,0,0,0-.67.31l-1.83,1.6a.36.36,0,0,1-.29.13H30.73a.36.36,0,0,1-.29-.13l-1.6-1.6a.9.9,0,0,0-.67-.31H2.37a.89.89,0,0,0-.89.89V12m.25,0V2.12a.64.64,0,0,1,.64-.64h25.8a.65.65,0,0,1,.48.23l1.6,1.59a.64.64,0,0,0,.48.22H93.62a.62.62,0,0,0,.48-.22l1.83-1.59a.65.65,0,0,1,.48-.23H122a.64.64,0,0,1,.64.64V12"/></svg>
|
||||
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 124.4 12.01">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1,.cls-3 { fill: #E4EA00; }
|
||||
.cls-2 { fill: #969696; opacity: 0.3; }
|
||||
.cls-3 { opacity: 0.8; }
|
||||
</style>
|
||||
</defs>
|
||||
<polygon class="cls-1" points="92.68 2.87 31.5 2.87 28.8 0 95.59 0 92.68 2.87"/>
|
||||
<path class="cls-2" d="M124.4.14V11.86c0,.08-.3.15-.66.15H97.84a2.27,2.27,0,0,1-.5,0l-1.76-.45a2.34,2.34,0,0,0-.5,0H29.76a2.2,2.2,0,0,0-.5,0L27.5,12a2.34,2.34,0,0,1-.5,0H.66C.3,12,0,11.94,0,11.86V.14C0,.06.3,0,.66,0L26.87.11a1.79,1.79,0,0,1,.5.05L29,2.25a2.27,2.27,0,0,0,.5,0H94.86a2.34,2.34,0,0,0,.5,0L97.25.16a1.83,1.83,0,0,1,.5,0l26-.11C124.1,0,124.4.06,124.4.14Z"/>
|
||||
<path class="cls-3" d="M122.92,12V2.12a.89.89,0,0,0-.89-.89H96.41a.9.9,0,0,0-.67.31l-1.83,1.6a.36.36,0,0,1-.29.13H30.73a.36.36,0,0,1-.29-.13l-1.6-1.6a.9.9,0,0,0-.67-.31H2.37a.89.89,0,0,0-.89.89V12m.25,0V2.12a.64.64,0,0,1,.64-.64h25.8a.65.65,0,0,1,.48.23l1.6,1.59a.64.64,0,0,0,.48.22H93.62a.62.62,0,0,0,.48-.22l1.83-1.59a.65.65,0,0,1,.48-.23H122a.64.64,0,0,1,.64.64V12"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.1 KiB |
21
src/assets/img/chart-title03.svg
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 124.4 12" style="enable-background:new 0 0 124.4 12;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#62E39A;}
|
||||
.st1{opacity:0.3;fill:#969696;}
|
||||
.st2{opacity:0.8;fill:#62E39A;}
|
||||
</style>
|
||||
<g>
|
||||
<polygon class="st0" points="92.7,2.9 31.5,2.9 28.8,0 95.6,0 "/>
|
||||
<path class="st1" d="M124.4,0.1v11.7c0,0.1-0.3,0.1-0.7,0.1H97.8c-0.2,0-0.4,0-0.5-0.1l-1.8-0.4c-0.1,0-0.3-0.1-0.5-0.1H29.8
|
||||
c-0.2,0-0.4,0-0.5,0.1L27.5,12C27.4,12,27.2,12,27,12H0.7C0.3,12,0,11.9,0,11.9V0.1C0,0.1,0.3,0,0.7,0l26.2,0.1
|
||||
c0.2,0,0.4,0,0.5,0.1L29,2.2c0.1,0,0.3,0.1,0.5,0.1h65.3c0.2,0,0.4,0,0.5-0.1l1.9-2.1c0.1,0,0.3-0.1,0.5-0.1l26-0.1
|
||||
C124.1,0,124.4,0.1,124.4,0.1z"/>
|
||||
<path class="st2" d="M122.9,12V2.1c0-0.5-0.4-0.9-0.9-0.9H96.4c-0.3,0-0.5,0.1-0.7,0.3l-1.8,1.6c-0.1,0.1-0.2,0.1-0.3,0.1H30.7
|
||||
c-0.1,0-0.2,0-0.3-0.1l-1.6-1.6c-0.2-0.2-0.4-0.3-0.7-0.3H2.4c-0.5,0-0.9,0.4-0.9,0.9V12 M1.7,12V2.1c0-0.4,0.3-0.6,0.6-0.6h25.8
|
||||
c0.2,0,0.4,0.1,0.5,0.2l1.6,1.6c0.1,0.1,0.3,0.2,0.5,0.2h62.9c0.2,0,0.4-0.1,0.5-0.2l1.8-1.6c0.1-0.1,0.3-0.2,0.5-0.2H122
|
||||
c0.4,0,0.6,0.3,0.6,0.6V12"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
21
src/assets/img/chart-title04.svg
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 124.4 12" style="enable-background:new 0 0 124.4 12;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#E9971F;}
|
||||
.st1{opacity:0.3;fill:#969696;}
|
||||
.st2{opacity:0.8;fill:#E9971F;}
|
||||
</style>
|
||||
<g>
|
||||
<polygon class="st0" points="92.7,2.9 31.5,2.9 28.8,0 95.6,0 "/>
|
||||
<path class="st1" d="M124.4,0.1v11.7c0,0.1-0.3,0.1-0.7,0.1H97.8c-0.2,0-0.4,0-0.5-0.1l-1.8-0.4c-0.1,0-0.3-0.1-0.5-0.1H29.8
|
||||
c-0.2,0-0.4,0-0.5,0.1L27.5,12C27.4,12,27.2,12,27,12H0.7C0.3,12,0,11.9,0,11.9V0.1C0,0.1,0.3,0,0.7,0l26.2,0.1
|
||||
c0.2,0,0.4,0,0.5,0.1L29,2.2c0.1,0,0.3,0.1,0.5,0.1h65.3c0.2,0,0.4,0,0.5-0.1l1.9-2.1c0.1,0,0.3-0.1,0.5-0.1l26-0.1
|
||||
C124.1,0,124.4,0.1,124.4,0.1z"/>
|
||||
<path class="st2" d="M122.9,12V2.1c0-0.5-0.4-0.9-0.9-0.9H96.4c-0.3,0-0.5,0.1-0.7,0.3l-1.8,1.6c-0.1,0.1-0.2,0.1-0.3,0.1H30.7
|
||||
c-0.1,0-0.2,0-0.3-0.1l-1.6-1.6c-0.2-0.2-0.4-0.3-0.7-0.3H2.4c-0.5,0-0.9,0.4-0.9,0.9V12 M1.7,12V2.1c0-0.4,0.3-0.6,0.6-0.6h25.8
|
||||
c0.2,0,0.4,0.1,0.5,0.2l1.6,1.6c0.1,0.1,0.3,0.2,0.5,0.2h62.9c0.2,0,0.4-0.1,0.5-0.2l1.8-1.6c0.1-0.1,0.3-0.2,0.5-0.2H122
|
||||
c0.4,0,0.6,0.3,0.6,0.6V12"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -1,25 +1,41 @@
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
import useAlarmStore from "@/stores/useAlarmStore";
|
||||
import { ackSingleAlarm } from "@/apis/building";
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
import { getAlertLog } from "@/apis/alert";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const store = useAlarmStore();
|
||||
const dataSource = ref([]);
|
||||
let intervalId = null; // 用來儲存 setInterval 的 ID
|
||||
|
||||
const getAlarmData = async () => {
|
||||
const res = await getAlertLog({
|
||||
isRecovery: 1,
|
||||
Start_date: dayjs().format("YYYY-MM-DD"),
|
||||
End_date: dayjs().format("YYYY-MM-DD"),
|
||||
});
|
||||
dataSource.value = (res.data || []).map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
store.getAlarmDataFromBaja();
|
||||
getAlarmData();
|
||||
|
||||
intervalId = setInterval(() => {
|
||||
getAlarmData();
|
||||
}, 30 * 1000);
|
||||
});
|
||||
|
||||
const ackedAlarm = async (uuid) => {
|
||||
const res = await ackSingleAlarm(uuid);
|
||||
console.log("ackedAlarm", res);
|
||||
};
|
||||
onUnmounted(() => {
|
||||
if (intervalId) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ul class="pr-4 min-h-full text-base-content">
|
||||
<!-- Sidebar content here -->
|
||||
<li class="my-3" v-for="alarm in store.alarmData" :key="alarm.uuid">
|
||||
<li class="my-3" v-for="alarm in dataSource" :key="alarm.id">
|
||||
<div
|
||||
class="w-full shadow-xl border border-success bg-body bg-opacity-80"
|
||||
>
|
||||
@ -34,30 +50,22 @@ const ackedAlarm = async (uuid) => {
|
||||
>
|
||||
<small>
|
||||
<span class="mr-4"
|
||||
>{{ alarm.timestamp_date }} {{ alarm.timestamp_time }}</span
|
||||
>{{ alarm.created_at }}</span
|
||||
>
|
||||
<font-awesome-icon
|
||||
<!-- <font-awesome-icon
|
||||
:icon="['fas', 'times']"
|
||||
size="lg"
|
||||
class="text-white"
|
||||
/>
|
||||
/> -->
|
||||
</small>
|
||||
</p>
|
||||
<div class="divider my-2"></div>
|
||||
<div>
|
||||
<p>{{ $t("alarm.number") }}:{{ alarm.uuid }}</p>
|
||||
<!-- <p>異常等級:255</p> -->
|
||||
<p>{{ $t("alarm.category") }}:{{ alarm.alarmClass }}</p>
|
||||
<p>{{ $t("alarm.device_name") }}:{{ alarm.full_name }}</p>
|
||||
<p>{{ $t("alarm.message") }}:{{ alarm.msg }}</p>
|
||||
</div>
|
||||
<div class="card-actions mt-1 justify-end">
|
||||
<button
|
||||
class="btn btn-sm btn-success"
|
||||
@click="() => ackedAlarm(alarm.uuid)"
|
||||
>
|
||||
{{ $t("alarm.confirm") }}
|
||||
</button>
|
||||
<p>{{ $t("alarm.number") }}:{{ alarm.id }}</p>
|
||||
<p>{{ $t("alert.alarmClass") }}:{{ alarm.factor }}</p>
|
||||
<p>{{ $t("alarm.device_name") }}:{{ alarm.device_number }}</p>
|
||||
<p>{{ $t("alert.device_point_name") }}:{{ alarm.points }}</p>
|
||||
<p>{{ $t("alert.error_msg") }}:{{ alarm.reason }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -68,12 +76,12 @@ const ackedAlarm = async (uuid) => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card::before {
|
||||
@apply absolute h-5 w-5 top-1 left-1 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background01.svg')] bg-center;
|
||||
@apply absolute h-5 w-5 top-1 left-1 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background01.svg')] bg-center;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.card::after {
|
||||
@apply absolute bottom-1 right-1 h-5 w-5 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background05.svg')] bg-center;
|
||||
@apply absolute bottom-1 right-1 h-5 w-5 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background05.svg')] bg-center;
|
||||
content: "";
|
||||
}
|
||||
</style>
|
||||
</style>
|
@ -16,7 +16,7 @@ const toggleErrIcon = () => {
|
||||
<!-- Page content here -->
|
||||
<label
|
||||
for="alarm"
|
||||
class="drawer-button flex flex-col justify-center items-center btn-group"
|
||||
class="drawer-button flex flex-col justify-center items-center bg-transparent w-[95px]"
|
||||
@click="toggleErrIcon"
|
||||
>
|
||||
<font-awesome-icon
|
||||
@ -31,12 +31,12 @@ const toggleErrIcon = () => {
|
||||
size="2x"
|
||||
class="text-white w-10 m-auto"
|
||||
/>
|
||||
<span class="text-white"> {{ $t("alarm.title") }}</span>
|
||||
<span class="text-white block mt-0"> {{ $t("alarm.title") }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
v-if="showErr"
|
||||
class="drawer-side translate-y-20 max-h-[90vh] overflow-x-hidden overflow-y-scroll"
|
||||
class="drawer-side translate-y-20 max-h-[90vh] overflow-x-hidden overflow-y-scroll w-[300px] left-auto right-0"
|
||||
>
|
||||
<AlarmCards />
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import * as echarts from "echarts";
|
||||
import { onMounted, ref, markRaw } from "vue";
|
||||
import { onMounted, ref, markRaw, nextTick } from "vue";
|
||||
import axios from "axios";
|
||||
|
||||
const props = defineProps({
|
||||
@ -24,9 +24,15 @@ async function updateSvg(svg, option) {
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
axios.get(svg.path).then(({ data }) => {
|
||||
axios.get(svg.path).then(async ({ data }) => {
|
||||
echarts.registerMap(svg.full_name, { svg: data });
|
||||
chart.value.setOption(option);
|
||||
await nextTick();
|
||||
// 延遲執行以避免在主進程中調用 setOption
|
||||
setTimeout(() => {
|
||||
if (chart.value && !chart.value.isDisposed()) {
|
||||
chart.value.setOption(option);
|
||||
}
|
||||
}, 0);
|
||||
if (props.getCoordinate) {
|
||||
chart.value.getZr().on("click", function (params) {
|
||||
var pixelPoint = [params.offsetX, params.offsetY];
|
||||
@ -44,11 +50,15 @@ async function updateSvg(svg, option) {
|
||||
value: dataPoint, // 當前座標值
|
||||
itemStyle: { color: "#0000FF" }, // 設為藍色
|
||||
});
|
||||
chart.value.setOption({
|
||||
series: {
|
||||
data: updatedData,
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
if (chart.value && !chart.value.isDisposed()) {
|
||||
chart.value.setOption({
|
||||
series: {
|
||||
data: updatedData,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -118,6 +118,6 @@ const curWidth = computed(() => {
|
||||
</style>
|
||||
<style scoped>
|
||||
.line {
|
||||
@apply mr-3 relative z-20 after:absolute after:top-1/2 after:-right-3 after:w-3 after:h-[1px] after:bg-info after:z-10 last:after:h-0;
|
||||
@apply mr-3 relative z-30 after:absolute after:top-1/2 after:-right-3 after:w-3 after:h-[1px] after:bg-info after:z-10 last:after:h-0;
|
||||
}
|
||||
</style>
|
||||
|
436
src/components/customUI/DraggableTable.vue
Normal file
@ -0,0 +1,436 @@
|
||||
<script setup>
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { computed, defineProps, provide, ref, watch } from "vue";
|
||||
import Pagination from "@/components/customUI/Pagination.vue";
|
||||
import Checkbox from "@/components/customUI/Checkbox.vue";
|
||||
import draggable from "vuedraggable";
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
/*
|
||||
column={
|
||||
title,key,class, width, filter:Boolean, sort:Boolean
|
||||
}
|
||||
*/
|
||||
const props = defineProps({
|
||||
columns: Array,
|
||||
dataSource: Array,
|
||||
rowKey: String,
|
||||
withStyle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
withDraggable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
pagination: { type: Boolean, default: true } || {
|
||||
pageSize: Number,
|
||||
totalPages: Number,
|
||||
totalItems: Number,
|
||||
},
|
||||
loading: Boolean,
|
||||
});
|
||||
|
||||
const currentDataSource = ref([]);
|
||||
const dataSourceStorage = ref([]);
|
||||
const isDraggable = ref(props.withDraggable);
|
||||
|
||||
watch(
|
||||
() => props.dataSource,
|
||||
(newValue) => {
|
||||
dataSourceStorage.value = newValue;
|
||||
filterItems.value = Object.fromEntries(
|
||||
props.columns.map((c, i) => [
|
||||
c.key,
|
||||
[...new Set(newValue.map((d) => d[c.key]))].map((name) => ({
|
||||
name,
|
||||
selected: false,
|
||||
})),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const updateDataSource = (data) => {
|
||||
console.log("update", data);
|
||||
currentDataSource.value = data;
|
||||
};
|
||||
provide("current_table_data", {
|
||||
updateDataSource,
|
||||
});
|
||||
|
||||
const sortRule = ref({});
|
||||
const filterColumn = ref({});
|
||||
const filterItems = ref({});
|
||||
const selectedFilterItem = ref({});
|
||||
|
||||
const toggleFilterModal = (key) => {
|
||||
let newFilter = Object.assign(filterColumn.value);
|
||||
|
||||
for (let oKey in newFilter) {
|
||||
newFilter[oKey] = key === oKey && !newFilter[key];
|
||||
}
|
||||
|
||||
filterColumn.value = newFilter;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.columns,
|
||||
(newValue) => {
|
||||
sortRule.value = Object.fromEntries(newValue.map((c) => [c.key, 0]));
|
||||
filterColumn.value = Object.fromEntries(
|
||||
newValue.map((c, i) => [c.key, false])
|
||||
);
|
||||
selectedFilterItem.value = Object.fromEntries(
|
||||
newValue.map((c, i) => [c.key, []])
|
||||
);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
0:取消
|
||||
1:ascending
|
||||
2:descending
|
||||
*/
|
||||
const toggleSortRule = (key) => {
|
||||
let newSort = Object.assign(sortRule.value);
|
||||
|
||||
for (let oKey in newSort) {
|
||||
newSort[oKey] = key === oKey ? newSort[key] : 0;
|
||||
}
|
||||
|
||||
sortRule.value = newSort;
|
||||
};
|
||||
|
||||
const sort = (column) => {
|
||||
toggleSortRule(column);
|
||||
const cantSort = ["object", "boolean"];
|
||||
console.log(props.dataSource?.[0][column]);
|
||||
if (cantSort.includes(typeof props.dataSource?.[0][column])) return;
|
||||
// 小->大
|
||||
const newArray = Object.assign(props.dataSource, []).sort((a, b) => {
|
||||
// if (column === "timestamp") {
|
||||
// return dayjs(a[column]).valueOf() - dayjs(b[column]).valueOf();
|
||||
// }
|
||||
if (typeof a[column] === "number") return a[column] - b[column];
|
||||
else if (typeof a[column] === "string") {
|
||||
console.log(a[column], b[column], a[column].localeCompare(b[column]));
|
||||
return a[column].localeCompare(b[column]);
|
||||
}
|
||||
// return parseInt(a[column]) - parseInt(b[column]);
|
||||
});
|
||||
if (sortRule.value[column] === 0) {
|
||||
sortRule.value[column] = 1;
|
||||
dataSourceStorage.value = newArray;
|
||||
} else if (sortRule.value[column] === 1) {
|
||||
sortRule.value[column] = 2;
|
||||
dataSourceStorage.value = newArray.reverse();
|
||||
} else if (sortRule.value[column] === 2) {
|
||||
sortRule.value[column] = 0;
|
||||
dataSourceStorage.value = props.dataSource;
|
||||
}
|
||||
};
|
||||
const form = ref(null);
|
||||
|
||||
const onFilter = (key, reset = false) => {
|
||||
const formData = new FormData(form.value);
|
||||
reset && formData.delete(key);
|
||||
for (let [name, value] of formData) {
|
||||
console.log(name, value);
|
||||
}
|
||||
selectedFilterItem.value[key] = formData.getAll(key);
|
||||
toggleFilterModal(key);
|
||||
};
|
||||
|
||||
watch(
|
||||
selectedFilterItem,
|
||||
(newVal) => {
|
||||
let newData = Object.assign(props.dataSource);
|
||||
for (let key in newVal) {
|
||||
if (newVal[key].length > 0) {
|
||||
newData = newData.filter((d) => newVal[key].includes(d[key]));
|
||||
}
|
||||
}
|
||||
dataSourceStorage.value = newData;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="withStyle ? 'content-box' : 'py-5'">
|
||||
<div class="content-decoration">
|
||||
<button
|
||||
v-if="withDraggable"
|
||||
class="btn btn-sm mb-2"
|
||||
@click.stop.prevent="isDraggable = !isDraggable"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'stream']" />
|
||||
{{ isDraggable ? "開始排序" : "完成排序" }}
|
||||
</button>
|
||||
<slot name="beforeTable"></slot>
|
||||
<form ref="form" class="overflow-x-auto">
|
||||
<table
|
||||
:class="
|
||||
twMerge(
|
||||
withStyle ? 'table' : 'table border',
|
||||
currentDataSource.length === 0 ? 'h-28' : ''
|
||||
)
|
||||
"
|
||||
>
|
||||
<!-- head -->
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
v-for="column in columns"
|
||||
:key="column.key"
|
||||
:class="`${column.class ? column.class : ''}`"
|
||||
:style="{
|
||||
width: `${
|
||||
column.width
|
||||
? typeof column.width === 'string'
|
||||
? column.width
|
||||
: column.width + 'px'
|
||||
: 'auto'
|
||||
}`,
|
||||
}"
|
||||
>
|
||||
<span class="flex justify-center">
|
||||
{{ column.title }}
|
||||
<div
|
||||
v-if="column.sort"
|
||||
class="flex flex-col justify-center w-3 mx-2 relative"
|
||||
@click="() => sort(column.key)"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'sort-up']"
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute top-0',
|
||||
sortRule[column.key] === 1 ? 'text-success' : ''
|
||||
)
|
||||
"
|
||||
size="lg"
|
||||
/>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'sort-down']"
|
||||
:class="
|
||||
twMerge(
|
||||
'absolute bottom-1',
|
||||
sortRule[column.key] === 2 ? 'text-success' : ''
|
||||
)
|
||||
"
|
||||
size="lg"
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-2 relative" v-if="column.filter">
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'filter']"
|
||||
:class="
|
||||
twMerge(
|
||||
filterColumn[column.key] ||
|
||||
selectedFilterItem[column.key].length > 0
|
||||
? 'text-success'
|
||||
: ''
|
||||
)
|
||||
"
|
||||
@click="() => toggleFilterModal(column.key)"
|
||||
/>
|
||||
<div
|
||||
class="absolute top-full -left-1/2 z-50"
|
||||
v-if="filterColumn[column.key]"
|
||||
>
|
||||
<div class="card min-w-max bg-body shadow-xl px-10 py-5">
|
||||
<Checkbox
|
||||
v-for="item in filterItems[column.key]"
|
||||
:title="item.name"
|
||||
:value="item.name"
|
||||
:key="item.name"
|
||||
:name="column.key"
|
||||
:checked="
|
||||
selectedFilterItem[column.key].includes(item.name)
|
||||
"
|
||||
className="justify-start"
|
||||
/>
|
||||
<div class="card-actions mt-4 justify-end">
|
||||
<input
|
||||
type="reset"
|
||||
class="btn btn-sm text-white btn-error"
|
||||
:value="t('button.reset')"
|
||||
@click="() => onFilter(column.key, true)"
|
||||
/>
|
||||
<button
|
||||
class="btn btn-sm btn-success"
|
||||
@click.stop.prevent="() => onFilter(column.key)"
|
||||
>
|
||||
{{ $t("button.submit") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-if="isDraggable">
|
||||
<tr v-if="loading">
|
||||
<td :colspan="columns.length">
|
||||
<Loading />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-else-if="currentDataSource.length == 0">
|
||||
<td :colspan="columns.length">{{ $t("table.no_data") }}</td>
|
||||
</tr>
|
||||
<template v-else :sort="sortRule">
|
||||
<tr
|
||||
v-for="(data, index) in currentDataSource"
|
||||
:key="data.key || data[rowKey]"
|
||||
>
|
||||
<template
|
||||
v-for="column in columns"
|
||||
:key="`${data.key || data[rowKey]}_${column.key}`"
|
||||
>
|
||||
<td
|
||||
:class="column.class"
|
||||
:style="{
|
||||
width: `${
|
||||
column.width
|
||||
? typeof column.width === 'string'
|
||||
? column.width
|
||||
: column.width + 'px'
|
||||
: 'auto'
|
||||
}`,
|
||||
}"
|
||||
>
|
||||
<slot
|
||||
name="bodyCell"
|
||||
v-bind="{ record: data, column, index }"
|
||||
>
|
||||
{{ data[column.key] }}</slot
|
||||
>
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
<draggable
|
||||
tag="tbody"
|
||||
:list="dataSourceStorage"
|
||||
item-key="rowKey"
|
||||
v-else
|
||||
>
|
||||
<template #item="{ element, index }">
|
||||
<tr :key="element[rowKey] || element.key" >
|
||||
<template
|
||||
v-for="column in columns"
|
||||
:key="`${element[rowKey] || element.key}_${column.key}`"
|
||||
>
|
||||
<td
|
||||
:class="column.class"
|
||||
:style="{
|
||||
width: `
|
||||
${
|
||||
column.width
|
||||
? typeof column.width === 'string'
|
||||
? column.width
|
||||
: column.width + 'px'
|
||||
: 'auto'
|
||||
}`,
|
||||
}"
|
||||
>
|
||||
<slot
|
||||
name="bodyCell"
|
||||
v-bind="{ record: element, column, index }"
|
||||
>
|
||||
{{ element[column.key] }}</slot
|
||||
>
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
</draggable>
|
||||
</table>
|
||||
</form>
|
||||
<slot name="afterTable"></slot>
|
||||
<Pagination
|
||||
:class="twMerge(!isDraggable ? 'hidden' : 'flex')"
|
||||
:pagination="pagination"
|
||||
:dataSource="dataSourceStorage"
|
||||
:sort="sortRule"
|
||||
/>
|
||||
</div>
|
||||
<div class="content-decoration2"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
/**資料框**/
|
||||
.content-box {
|
||||
@apply border border-info p-1 relative mb-4 bg-transparent;
|
||||
}
|
||||
|
||||
.content-box .table {
|
||||
@apply rounded-none;
|
||||
}
|
||||
|
||||
.table th {
|
||||
@apply bg-cyan-600 bg-opacity-30 border-r border-b border-white text-lg font-semibold text-white text-center px-2 py-3;
|
||||
}
|
||||
|
||||
.table td {
|
||||
@apply border-r border-b border-white text-lg font-semibold text-white text-center px-2 py-3;
|
||||
}
|
||||
|
||||
.table tr td:last-child,
|
||||
.table tr:first-child th:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
/* .table tr:last-child td {
|
||||
border-bottom: v-bind("withStyle ? '0px': '1px'");
|
||||
} */
|
||||
|
||||
/**資料框裝飾**/
|
||||
.content-box::before {
|
||||
@apply absolute top-1 left-1 h-5 w-5 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background01.svg')] bg-center;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.content-box::after {
|
||||
@apply absolute bottom-1 right-1 h-5 w-5 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background05.svg')] bg-center;
|
||||
content: "";
|
||||
}
|
||||
.content-box .content-decoration {
|
||||
@apply bg-normal px-8 py-4;
|
||||
}
|
||||
|
||||
/* .content-box .content-decoration::before {
|
||||
@apply absolute -top-3 -right-[10px] h-8 w-8 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background02.svg')] bg-center;
|
||||
content: "";
|
||||
} */
|
||||
|
||||
.content-box .content-decoration2::before {
|
||||
@apply absolute -bottom-1 -left-8 h-14 w-14 bg-no-repeat z-10 bg-[url('../../assets/img/table/content-box-background03.svg')] bg-center;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* .content-box .content-decoration2::after {
|
||||
content: "";
|
||||
background: url(../../assets/img/table/content-box-background04.svg) center
|
||||
center;
|
||||
position: absolute;
|
||||
right: -27px;
|
||||
bottom: -7px;
|
||||
height: 65px;
|
||||
width: 50px;
|
||||
background-repeat: no-repeat;
|
||||
z-index: 2;
|
||||
} */
|
||||
</style>
|
@ -64,10 +64,11 @@ watch(
|
||||
twMerge(
|
||||
'flex-col text-xl',
|
||||
cls,
|
||||
openChildren.includes(dataParentKey) || open ? 'flex' : 'hidden'
|
||||
openChildren.includes(d.key) || open ? 'flex' : 'hidden'
|
||||
)
|
||||
"
|
||||
v-for="d in data"
|
||||
:key="d.key"
|
||||
:data-parent="d.key"
|
||||
:open="open"
|
||||
>
|
||||
|
@ -9,7 +9,7 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
value: String,
|
||||
value: Object,
|
||||
isTopLabelExist: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
@ -73,7 +73,7 @@ const curWidth = computed(() => {
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-500 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-300 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
/>
|
||||
<input
|
||||
v-else
|
||||
@ -84,7 +84,7 @@ const curWidth = computed(() => {
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-500 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-300 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
/>
|
||||
<div :class="twMerge(isBottomLabelExist ? 'label' : '')">
|
||||
<span class="label-text-alt"><slot name="bottomLeft"></slot></span>
|
||||
|
@ -9,7 +9,7 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
value: String,
|
||||
value: Object,
|
||||
isTopLabelExist: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
@ -48,10 +48,10 @@ onMounted(() => {
|
||||
'modal',
|
||||
backdrop
|
||||
? ''
|
||||
: 'h-fit w-fit max-h-fit max-w-fit focus-visible:outline-none backdrop:bg-transparent',
|
||||
: 'focus-visible:outline-none backdrop:bg-transparent',
|
||||
)" :style="modalStyle" v-draggable="draggable">
|
||||
<div :class="twMerge(
|
||||
'modal-box static rounded-md border border-info py-5 px-6 overflow-y-scroll bg-normal',
|
||||
'modal-box static rounded-md border border-info py-5 px-6 overflow-y-auto bg-normal',
|
||||
modalClass
|
||||
)
|
||||
" :style="{ minWidth: isNaN(width) ? width : `${width}px` }">
|
||||
@ -60,7 +60,7 @@ onMounted(() => {
|
||||
{{ title }}
|
||||
</slot>
|
||||
</div>
|
||||
<div class="min-h-[400px]">
|
||||
<div class="min-h-[200px]">
|
||||
<slot name="modalContent"></slot>
|
||||
</div>
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { twMerge } from "tailwind-merge";
|
||||
|
||||
const props = defineProps({
|
||||
name: String,
|
||||
value: String,
|
||||
value: Object,
|
||||
items: Array,
|
||||
isLabelExist: {
|
||||
type: Boolean,
|
||||
|
128
src/components/customUI/SearchSelect.vue
Normal file
@ -0,0 +1,128 @@
|
||||
<script setup>
|
||||
import { defineProps, ref, computed, watch, nextTick, watchEffect } from "vue";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
/* --------------------------------------------------------------
|
||||
options: [
|
||||
{
|
||||
key: unique,
|
||||
content: "",
|
||||
selected: true / false,
|
||||
disabled: true / false
|
||||
}
|
||||
]
|
||||
---------------------------------------------------------------- */
|
||||
|
||||
const props = defineProps({
|
||||
options: Array,
|
||||
name: String,
|
||||
Attribute: String,
|
||||
onChange: Function,
|
||||
selectClass: String,
|
||||
value: Object,
|
||||
isTopLabelExist: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isBottomLabelExist: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
search: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const searchQuery = ref("");
|
||||
const isOpen = ref(false);
|
||||
const selectedOption = ref(null);
|
||||
|
||||
const filteredOptions = computed(() => {
|
||||
return props.options.filter((option) => {
|
||||
const content = option[props.Attribute] || option.key || "";
|
||||
return content.toLowerCase().includes(searchQuery.value.toLowerCase());
|
||||
});
|
||||
});
|
||||
|
||||
const selectOption = (value) => {
|
||||
if (props.onChange) {
|
||||
props.onChange(value);
|
||||
} else {
|
||||
props.value[props.name] = value.key;
|
||||
selectedOption.value = props.options.find(
|
||||
(option) => option.key === value.key
|
||||
);
|
||||
}
|
||||
isOpen.value = false;
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
isOpen.value = false;
|
||||
selectedOption.value = props.options.find(
|
||||
(option) => option.key == props.value[props.name]
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label class="form-control w-80 max-w-sm relative">
|
||||
<div :class="twMerge(isTopLabelExist ? 'label' : '')">
|
||||
<span class="label-text text-lg"><slot name="topLeft"></slot></span>
|
||||
<span class="label-text-alt"> <slot name="topRight"></slot></span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class="
|
||||
twMerge(
|
||||
'select rounded-md text-lg cursor-pointer pt-2',
|
||||
disabled ? 'text-gray-300' : 'bg-transparent border-info'
|
||||
)
|
||||
"
|
||||
@click="disabled ? () => {} : (isOpen = !isOpen)"
|
||||
>
|
||||
{{ selectedOption ? selectedOption[Attribute] : "" }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="isOpen"
|
||||
class="absolute z-10 bg-gray-800 border border-info rounded-md w-full p-2"
|
||||
>
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
class="input input-bordered border-info rounded-md w-full mb-2 px-2"
|
||||
/>
|
||||
|
||||
<ul class="max-h-60 overflow-auto">
|
||||
<li
|
||||
v-for="option in filteredOptions"
|
||||
:key="option.key || option"
|
||||
@click="selectOption(option)"
|
||||
class="px-4 py-2 hover:bg-gray-600 cursor-pointer"
|
||||
>
|
||||
{{ option[Attribute] || option }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div :class="twMerge(isBottomLabelExist ? 'label' : '')">
|
||||
<span class="label-text-alt"> <slot name="bottomLeft"></slot></span>
|
||||
<span class="label-text-alt"> <slot name="bottomRight"></slot></span>
|
||||
</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -18,7 +18,7 @@ const props = defineProps({
|
||||
Attribute: String,
|
||||
onChange: Function,
|
||||
selectClass: String,
|
||||
value: String || Number,
|
||||
value: Object,
|
||||
isTopLabelExist: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
@ -70,9 +70,7 @@ const props = defineProps({
|
||||
:class="twMerge(disabled ? `text-white` : 'text-dark')"
|
||||
:value="option.value || option.key || option"
|
||||
>
|
||||
<span>
|
||||
{{ option[Attribute] || option }}
|
||||
</span>
|
||||
</option>
|
||||
</select>
|
||||
<div :class="twMerge(isBottomLabelExist ? 'label' : '')">
|
||||
|
@ -30,6 +30,10 @@ const props = defineProps({
|
||||
const currentDataSource = ref([]);
|
||||
const dataSourceStorage = ref([]);
|
||||
|
||||
const tableDataSource = computed(() =>
|
||||
props.pagination ? currentDataSource.value : dataSourceStorage.value
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.dataSource,
|
||||
(newValue) => {
|
||||
@ -47,7 +51,7 @@ watch(
|
||||
);
|
||||
|
||||
const updateDataSource = (data) => {
|
||||
console.log("update", data);
|
||||
// console.log("update", data);
|
||||
currentDataSource.value = data;
|
||||
};
|
||||
provide("current_table_data", {
|
||||
@ -58,6 +62,7 @@ const sortRule = ref({});
|
||||
const filterColumn = ref({});
|
||||
const filterItems = ref({});
|
||||
const selectedFilterItem = ref({});
|
||||
const searchQuery = ref("");
|
||||
|
||||
const toggleFilterModal = (key) => {
|
||||
let newFilter = Object.assign(filterColumn.value);
|
||||
@ -132,7 +137,10 @@ const form = ref(null);
|
||||
|
||||
const onFilter = (key, reset = false) => {
|
||||
const formData = new FormData(form.value);
|
||||
reset && formData.delete(key);
|
||||
if (reset) {
|
||||
formData.delete(key);
|
||||
searchQuery.value = "";
|
||||
}
|
||||
for (let [name, value] of formData) {
|
||||
console.log(name, value);
|
||||
}
|
||||
@ -228,22 +236,38 @@ watch(
|
||||
"
|
||||
@click="() => toggleFilterModal(column.key)"
|
||||
/>
|
||||
<div
|
||||
class="absolute top-full -left-1/2 z-50"
|
||||
v-if="filterColumn[column.key]"
|
||||
>
|
||||
<div class="fixed z-50" v-if="filterColumn[column.key]">
|
||||
<div class="card min-w-max bg-body shadow-xl px-10 py-5">
|
||||
<Checkbox
|
||||
v-for="item in filterItems[column.key]"
|
||||
:title="item.name"
|
||||
:value="item.name"
|
||||
:key="item.name"
|
||||
:name="column.key"
|
||||
:checked="
|
||||
selectedFilterItem[column.key].includes(item.name)
|
||||
"
|
||||
className="justify-start"
|
||||
/>
|
||||
<label
|
||||
class="input input-bordered bg-transparent rounded-lg flex items-center px-2 mb-4 border-success focus-within:border-success"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'search']"
|
||||
class="w-6 h-6 mr-2 text-success"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
:placeholder="t('operation.enter_text')"
|
||||
class="text-white bg-transparent w-full"
|
||||
v-model="searchQuery"
|
||||
/>
|
||||
</label>
|
||||
<div class="max-h-72 overflow-x-auto px-2">
|
||||
<Checkbox
|
||||
v-for="item in filterItems[column.key].filter(
|
||||
(item) =>
|
||||
item.name && item.name.includes(searchQuery)
|
||||
)"
|
||||
:title="item.name"
|
||||
:value="item.name"
|
||||
:key="item.name"
|
||||
:name="column.key"
|
||||
:checked="
|
||||
selectedFilterItem[column.key].includes(item.name)
|
||||
"
|
||||
className="justify-start"
|
||||
/>
|
||||
</div>
|
||||
<div class="card-actions mt-4 justify-end">
|
||||
<input
|
||||
type="reset"
|
||||
@ -271,12 +295,12 @@ watch(
|
||||
<Loading />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-else-if="currentDataSource.length == 0">
|
||||
<tr v-else-if="tableDataSource.length == 0">
|
||||
<td :colspan="columns.length">{{ $t("table.no_data") }}</td>
|
||||
</tr>
|
||||
<template v-else :sort="sortRule">
|
||||
<tr
|
||||
v-for="(data, index) in currentDataSource"
|
||||
v-for="(data, index) in tableDataSource"
|
||||
:key="data.key || data[rowKey]"
|
||||
>
|
||||
<template
|
||||
@ -310,6 +334,7 @@ watch(
|
||||
</form>
|
||||
<slot name="afterTable"></slot>
|
||||
<Pagination
|
||||
v-if="pagination"
|
||||
:pagination="pagination"
|
||||
:dataSource="dataSourceStorage"
|
||||
:sort="sortRule"
|
||||
@ -322,7 +347,7 @@ watch(
|
||||
<style lang="css" scoped>
|
||||
/**資料框**/
|
||||
.content-box {
|
||||
@apply border border-info p-1 relative mb-4 bg-transparent ;
|
||||
@apply border border-info p-1 relative mb-4 bg-transparent;
|
||||
}
|
||||
|
||||
.content-box .table {
|
||||
|
@ -3,7 +3,7 @@ import { defineProps } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
name: String,
|
||||
value: String,
|
||||
value: Object,
|
||||
placeholder: String,
|
||||
});
|
||||
</script>
|
||||
@ -15,7 +15,7 @@ const props = defineProps({
|
||||
<span class="label-text-alt"> <slot name="topRight"></slot></span>
|
||||
</div>
|
||||
<textarea
|
||||
class="textarea text-lg rounded-md border-info focus-within:border-info h-24"
|
||||
class="textarea text-lg rounded-md border-info focus-within:border-info h-40"
|
||||
:placeholder="placeholder"
|
||||
:name="name"
|
||||
v-model="value[name]"
|
||||
|
@ -1,12 +1,14 @@
|
||||
<script setup>
|
||||
import { defineProps, ref, watch } from "vue";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const props = defineProps({
|
||||
content: String,
|
||||
status: String,
|
||||
open: Boolean,
|
||||
cancel: Function,
|
||||
confirm: Function,
|
||||
to: {
|
||||
default: "body",
|
||||
type: String,
|
||||
@ -19,7 +21,7 @@ watch(
|
||||
() => props.open,
|
||||
(newVal) => {
|
||||
isOpen.value = newVal;
|
||||
if (newVal) {
|
||||
if (newVal && props.status !== "warning") {
|
||||
setTimeout(() => {
|
||||
props.cancel && props.cancel();
|
||||
}, 3000);
|
||||
@ -35,11 +37,13 @@ watch(
|
||||
role="alert"
|
||||
:class="
|
||||
twMerge(
|
||||
`alert text-xl rounded-md absolute left-1/2 -translate-x-1/2 top-5 z-[1000] max-w-fit`,
|
||||
`alert text-xl rounded-md fixed left-1/2 -translate-x-1/2 top-24 z-[1000] max-w-fit`,
|
||||
status === 'info'
|
||||
? 'alert-info'
|
||||
: status === 'error'
|
||||
? 'alert-error text-white'
|
||||
: status === 'warning'
|
||||
? 'alert-warning bg-yellow-400'
|
||||
: 'alert-success'
|
||||
)
|
||||
"
|
||||
@ -58,6 +62,10 @@ watch(
|
||||
></path>
|
||||
</svg>
|
||||
<span>{{ content }}</span>
|
||||
<div v-if="status === 'warning'">
|
||||
<button @click="props.cancel && props.cancel();" className="btn btn-sm btn-outline me-2">{{$t("button.cancel")}}</button>
|
||||
<button @click="props.confirm && props.confirm()" className="btn btn-sm">{{$t("button.confirm")}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Teleport>
|
||||
|
@ -9,6 +9,7 @@ const props = defineProps({
|
||||
getFileList: Function,
|
||||
multiple: Boolean,
|
||||
baseUrl: String,
|
||||
formats: { type: String, default: "txt、doc、xls、pdf、png、jpg、ppt、zip、rar" },
|
||||
});
|
||||
|
||||
const acceptFileType = [
|
||||
@ -25,6 +26,13 @@ const acceptFileType = [
|
||||
"application/msword",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
"application/vnd.ms-powerpoint",
|
||||
".ppt",
|
||||
".pptx",
|
||||
".zip",
|
||||
".rar",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation", // PowerPoint Files 2007+
|
||||
"application/zip", // ZIP Files
|
||||
"application/x-rar-compressed", // RAR Files
|
||||
];
|
||||
|
||||
const loading = ref(false);
|
||||
@ -134,7 +142,7 @@ const revokeURL = (src) => {
|
||||
|
||||
<template>
|
||||
<label class="form-control w-full">
|
||||
<div class="label">
|
||||
<div class="label" @click.stop.prevent="() => {}">
|
||||
<span class="label-text text-lg"><slot name="topLeft"></slot></span>
|
||||
<span class="label-text-alt"> <slot name="topRight"></slot></span>
|
||||
</div>
|
||||
@ -236,6 +244,14 @@ const revokeURL = (src) => {
|
||||
:icon="['fas', 'file-powerpoint']"
|
||||
/>
|
||||
</template>
|
||||
<template
|
||||
v-else-if="file.type?.match(/zip|rar/g) || file.ext?.match(/zip|rar/g)"
|
||||
>
|
||||
<font-awesome-icon
|
||||
class="mx-auto mb-2 text-4xl text-white"
|
||||
:icon="['fas', 'file-archive']"
|
||||
/>
|
||||
</template>
|
||||
<template
|
||||
v-else-if="
|
||||
!file.type?.match('image/*') &&
|
||||
@ -265,6 +281,9 @@ const revokeURL = (src) => {
|
||||
</div>
|
||||
<p class="text-2xl my-2">{{ $t("upload.title") }}</p>
|
||||
<p class="mb-0 col-grey">{{ $t("upload.description") }}</p>
|
||||
<p class="mb-0 col-grey">
|
||||
{{ $t("upload.formats") }} : {{ props.formats }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
|
||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
|
||||
const forgeDom = ref(null);
|
||||
let viewer = null;
|
||||
@ -34,6 +34,20 @@ const initViewer = (container) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 設置攝影機位置
|
||||
const setCameraPosition = (position, target) => {
|
||||
const nav = viewer.navigation;
|
||||
// 使用 THREE.Vector3 定義位置與焦點
|
||||
const newPosition = new THREE.Vector3(position.x, position.y, position.z);
|
||||
const newTarget = new THREE.Vector3(target.x, target.y, target.z);
|
||||
|
||||
// 設定攝影機的新位置與焦點
|
||||
nav.setView(newPosition, newTarget);
|
||||
console.log("攝影機定位完成:");
|
||||
console.log("新位置:", newPosition);
|
||||
console.log("新焦點:", newTarget);
|
||||
};
|
||||
|
||||
// 使用本地 .svf 文件加載模型
|
||||
const loadModel = (filePath) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -43,6 +57,21 @@ const loadModel = (filePath) => {
|
||||
(model) => {
|
||||
viewer.impl.invalidate(true);
|
||||
viewer.fitToView();
|
||||
// 設置攝影機位置
|
||||
setTimeout(() => {
|
||||
setCameraPosition(
|
||||
{
|
||||
x: -212.33421531428007,
|
||||
y: 299.3895400707608,
|
||||
z: 157.48711907404862,
|
||||
}, // 攝影機的新位置
|
||||
{
|
||||
x: 151.61159898775077,
|
||||
y: -196.55136189609067,
|
||||
z: -136.47282256290345,
|
||||
} // 攝影機的焦點
|
||||
);
|
||||
}, 500);
|
||||
resolve(model);
|
||||
console.log("模型加載完成");
|
||||
},
|
||||
@ -54,7 +83,7 @@ const loadModel = (filePath) => {
|
||||
onMounted(async () => {
|
||||
console.log("Forge 加載");
|
||||
await initViewer(forgeDom.value);
|
||||
const filePath = `${FILE_BASEURL}/upload/forge/0.svf`;
|
||||
const filePath = `${FILE_BASEURL}/upload/forge/0.svf`;
|
||||
loadModel(filePath);
|
||||
});
|
||||
|
||||
@ -85,5 +114,4 @@ onUnmounted(() => {
|
||||
display: none;
|
||||
bottom: 200px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -30,7 +30,7 @@ const props = defineProps({
|
||||
});
|
||||
const store = useHeatmapBarStore();
|
||||
|
||||
const { updateDataVisualization, createSprites, showSubSystemObjects, forgeClickListener, clear } = useForgeSprite()
|
||||
const { updateDataVisualization, createSprites, showSubSystemObjects, forgeClickListener, clear, setCameraPosition } = useForgeSprite()
|
||||
|
||||
const forgeDom = ref(null);
|
||||
|
||||
@ -80,6 +80,20 @@ const loadModel = (viewer, filePath) => {
|
||||
(model) => {
|
||||
viewer.impl.invalidate(true);
|
||||
viewer.fitToView();
|
||||
setTimeout(() => {
|
||||
setCameraPosition(
|
||||
{
|
||||
x: 241.40975707867645,
|
||||
y: -260.4481491801548,
|
||||
z: 129.5719879121458,
|
||||
}, // 攝影機的新位置
|
||||
{
|
||||
x: -183.36302786348594,
|
||||
y: 194.05657710941966,
|
||||
z: -149.3902249981004,
|
||||
} // 攝影機的焦點
|
||||
);
|
||||
}, 500);
|
||||
updateDataVisualization(viewer)
|
||||
resolve(model);
|
||||
console.log("模型加載完成");
|
||||
|
@ -93,8 +93,8 @@ const createSprites = async (dataVizExtn) => {
|
||||
const DataVizCore = Autodesk.DataVisualization.Core;
|
||||
const viewableType = DataVizCore.ViewableType.SPRITE;
|
||||
let spriteColor = new THREE.Color(0xffffff);
|
||||
const BASEURL = import.meta.env.VITE_FORGE_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/hotspot.svg`;
|
||||
const BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/dist/hotspot.svg`;
|
||||
const style = new DataVizCore.ViewableStyle(
|
||||
viewableType,
|
||||
spriteColor,
|
||||
|
@ -1,17 +1,22 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import NavbarItem from "./NavbarItem.vue";
|
||||
import NavbarBuilding from "./NavbarBuilding.vue";
|
||||
import Logo from "@/assets/img/logo.svg";
|
||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
|
||||
import AlarmDrawer from "@/components/alarm/AlarmDrawer.vue";
|
||||
import NavbarLang from "./NavbarLang.vue";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
const user = ref("");
|
||||
const menuShow = ref(true);
|
||||
const router = useRouter();
|
||||
|
||||
const store = useUserInfoStore();
|
||||
const storeBuilding = useBuildingStore();
|
||||
onMounted(() => {
|
||||
const name = store.user.user_name;
|
||||
if (name) {
|
||||
@ -24,12 +29,26 @@ const toggleMenu = () => {
|
||||
};
|
||||
|
||||
const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo;
|
||||
|
||||
const logout = () => {
|
||||
document.cookie = "JWT-Authorization=; Max-Age=0";
|
||||
document.cookie = "user_name=; Max-Age=0";
|
||||
store.user.token = "";
|
||||
store.user.user_name = "";
|
||||
storeBuilding.deleteBuilding();
|
||||
router.push({ path: "/login" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="navbar bg-dark text-light-info w-full relative z-50">
|
||||
<div class="navbar-start">
|
||||
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden" @click="toggleMenu">
|
||||
<div class="navbar-start min-w-[480px] lg:min-w-[440px]">
|
||||
<div
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="btn btn-ghost lg:hidden"
|
||||
@click="toggleMenu"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
@ -67,7 +86,7 @@ const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo;
|
||||
<NavbarItem />
|
||||
</div>
|
||||
<div class="navbar-end mr-4">
|
||||
<ul class="menu-box">
|
||||
<ul class="left-menu">
|
||||
<li>
|
||||
<NavbarLang />
|
||||
</li>
|
||||
@ -93,12 +112,12 @@ const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo;
|
||||
class="dropdown-content translate-y-2 z-[100] menu py-3 shadow rounded w-32 bg-[#4c625e] border text-center"
|
||||
>
|
||||
<li class="text-white">
|
||||
<router-link
|
||||
to="logout"
|
||||
type="link"
|
||||
<a
|
||||
href="#"
|
||||
@click.prevent="logout"
|
||||
class="flex flex-col justify-center items-center"
|
||||
>{{ $t("sign_out") }}
|
||||
</router-link>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -112,39 +131,17 @@ const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo;
|
||||
.sub-drawer {
|
||||
@apply bg-dark bg-opacity-90 shadow-xl !important;
|
||||
}
|
||||
/**menu**/
|
||||
.menu-box {
|
||||
@apply flex flex-wrap justify-center ;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
|
||||
.left-menu {
|
||||
@apply flex flex-wrap justify-center relative z-0;
|
||||
}
|
||||
|
||||
.menu-box .btn-group {
|
||||
background: transparent;
|
||||
width: 95px;
|
||||
.left-menu > li {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.menu-box > li {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.menu-box > li:not(:last-child)::after {
|
||||
.left-menu > li:not(:last-child)::after {
|
||||
@apply absolute top-5 bottom-0 left-20 right-0 block w-6 h-0.5 bg-[#93c0dc] z-0;
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
bottom: 0;
|
||||
left: 84px;
|
||||
right: 0px;
|
||||
display: block;
|
||||
width: 25px;
|
||||
height: 2px;
|
||||
background-color: #93c0dc;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.menu-box .btn-group span {
|
||||
color: #fff;
|
||||
display: block;
|
||||
margin-top: 0px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,50 +1,48 @@
|
||||
<script setup>
|
||||
import { getBuildings } from "@/apis/building";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
|
||||
const store = useBuildingStore();
|
||||
|
||||
const getBui = async () => {
|
||||
console.log(store.buildings);
|
||||
const res = await getBuildings();
|
||||
store.buildings = res.data;
|
||||
store.selectedBuilding = res?.data[0];
|
||||
};
|
||||
|
||||
const selectBuilding = (bui) => {
|
||||
store.selectedBuilding = bui;
|
||||
store.selectedBuilding = bui; // 改變 selectedBuilding,watch 會自動更新資料
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getBui();
|
||||
store.initialize(); // 初始化資料
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown dropdown-bottom">
|
||||
<div
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="text-white ml-8 text-lg font-semiLight"
|
||||
>
|
||||
{{ store.selectedBuilding?.full_name }}
|
||||
<font-awesome-icon :icon="['fas', 'angle-down']" class="ml-1" />
|
||||
</div>
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="dropdown-content left-8 translate-y-2 z-[1] menu py-3 shadow rounded bg-[#4c625e] border text-center"
|
||||
>
|
||||
<li
|
||||
class="text-white my-1 text-base"
|
||||
v-for="bui in store.buildings"
|
||||
:key="bui.building_tag"
|
||||
@click="selectBuilding(bui)"
|
||||
<template v-if="store.buildings.length > 1">
|
||||
<div class="dropdown dropdown-bottom">
|
||||
<div
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="text-white ml-8 text-lg font-semiLight"
|
||||
>
|
||||
{{ bui.full_name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{ store.selectedBuilding?.full_name }}
|
||||
<font-awesome-icon :icon="['fas', 'angle-down']" class="ml-1" />
|
||||
</div>
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="dropdown-content w-48 left-8 translate-y-2 z-[1] menu py-3 shadow rounded bg-[#4c625e] border text-center"
|
||||
>
|
||||
<li
|
||||
class="text-white my-1 text-base cursor-pointer"
|
||||
v-for="bui in store.buildings"
|
||||
:key="bui.building_tag"
|
||||
@click="selectBuilding(bui)"
|
||||
>
|
||||
{{ bui.full_name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="text-white ml-8 text-lg font-semiLight">
|
||||
{{ store.selectedBuilding?.full_name }}
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { onMounted, ref, watch, computed } from "vue";
|
||||
import { AUTHPAGES } from "@/constant";
|
||||
import { getAuth, getAllSysSidebar } from "@/apis/building";
|
||||
import { getSideBar } from "@/apis/energy";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||
import { useI18n } from "vue-i18n";
|
||||
@ -13,6 +14,8 @@ const store = useUserInfoStore();
|
||||
const buildingStore = useBuildingStore();
|
||||
const route = useRoute();
|
||||
const openKeys = ref([]); // 追蹤當前打開的子菜單
|
||||
const menu_array = ref([]);
|
||||
const currentAuthCode = ref("");
|
||||
|
||||
const iniFroList = async () => {
|
||||
const res = await getAuth(locale.value);
|
||||
@ -34,12 +37,22 @@ const authPages = computed(() =>
|
||||
);
|
||||
|
||||
const open = ref(false);
|
||||
const getSubMonitorPage = async (building) => {
|
||||
const res = await getAllSysSidebar();
|
||||
const getSubMonitorPage = async (building_guid) => {
|
||||
const res = await getAllSysSidebar(building_guid);
|
||||
buildingStore.mainSubSys = res.data.history_Main_Systems;
|
||||
menu_array.value = res.data.history_Main_Systems;
|
||||
};
|
||||
const showDrawer = () => {
|
||||
getSubMonitorPage();
|
||||
const getSubPage = async (system_type) => {
|
||||
const res = await getSideBar(system_type);
|
||||
menu_array.value = res.data;
|
||||
};
|
||||
const showDrawer = async (authCode) => {
|
||||
if (authCode === "PF1") {
|
||||
await getSubMonitorPage(buildingStore.selectedBuilding.building_guid);
|
||||
} else if (authCode === "PF2" || authCode === "PF11") {
|
||||
await getSubPage(authCode === "PF2" ? "Energy" : "Setting");
|
||||
}
|
||||
currentAuthCode.value = authCode;
|
||||
open.value = true;
|
||||
};
|
||||
const onClose = () => {
|
||||
@ -58,7 +71,7 @@ watch(
|
||||
() => buildingStore.selectedBuilding,
|
||||
(newVal) => {
|
||||
if (newVal !== null) {
|
||||
getSubMonitorPage(newVal.building_tag);
|
||||
getSubMonitorPage(newVal.building_guid);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -76,27 +89,39 @@ onMounted(() => {
|
||||
<li class="flex flex-col items-center justify-center">
|
||||
<router-link
|
||||
:to="{ name: 'dashboard' }"
|
||||
class="flex flex-col justify-center items-center btn-group text-white"
|
||||
class="flex lg:flex-col justify-center items-center btn-group text-white"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'home']"
|
||||
size="2x"
|
||||
class="w-10 m-auto"
|
||||
/>
|
||||
{{ $t("home") }}
|
||||
<span>{{ $t("home") }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li
|
||||
v-for="page in authPages"
|
||||
class="flex flex-col items-center justify-center"
|
||||
:key="page.authCode"
|
||||
>
|
||||
<a
|
||||
v-if="page.authCode === 'PF1'"
|
||||
@click="showDrawer"
|
||||
v-if="
|
||||
page.authCode === 'PF1' ||
|
||||
page.authCode === 'PF2' ||
|
||||
page.authCode === 'PF11'
|
||||
"
|
||||
@click="showDrawer(page.authCode)"
|
||||
:class="
|
||||
twMerge(
|
||||
'flex flex-col justify-center items-center btn-group text-white cursor-pointer',
|
||||
route.fullPath.includes('/system')
|
||||
'flex lg:flex-col justify-center items-center btn-group text-white cursor-pointer',
|
||||
page.authCode === 'PF1' && route.fullPath.includes('/system')
|
||||
? 'router-link-active router-link-exact-active'
|
||||
: '',
|
||||
page.authCode === 'PF2' &&
|
||||
route.fullPath.includes('/energyManagement')
|
||||
? 'router-link-active router-link-exact-active'
|
||||
: '',
|
||||
page.authCode === 'PF11' && route.fullPath.includes('/setting')
|
||||
? 'router-link-active router-link-exact-active'
|
||||
: ''
|
||||
)
|
||||
@ -107,20 +132,20 @@ onMounted(() => {
|
||||
size="2x"
|
||||
class="w-10 m-auto"
|
||||
/>
|
||||
{{ page.subName }}
|
||||
<span>{{ page.subName }}</span>
|
||||
</a>
|
||||
<router-link
|
||||
v-else
|
||||
:to="page.navigate"
|
||||
type="link"
|
||||
class="flex flex-col justify-center items-center btn-group text-white"
|
||||
class="flex lg:flex-col justify-center items-center btn-group text-white"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', page.icon]"
|
||||
size="2x"
|
||||
class="w-10 m-auto"
|
||||
/>
|
||||
{{ page.subName }}
|
||||
<span>{{ page.subName }}</span>
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
@ -142,22 +167,34 @@ onMounted(() => {
|
||||
@openChange="handleOpenChange"
|
||||
>
|
||||
<a-sub-menu
|
||||
v-for="main in buildingStore.mainSubSys"
|
||||
v-for="main in menu_array"
|
||||
:key="main.main_system_tag"
|
||||
:title="main.full_name"
|
||||
v-if="menu_array.length > 0 && open"
|
||||
>
|
||||
<a-menu-item
|
||||
v-for="sub in main.history_Sub_systems"
|
||||
:key="sub.sub_system_tag"
|
||||
v-for="sub in currentAuthCode === 'PF1'
|
||||
? main.history_Sub_systems
|
||||
: currentAuthCode === 'PF2'
|
||||
? main.sub
|
||||
: main.sub"
|
||||
:key="sub.sub_system_tag + `_` + sub.type"
|
||||
@click="() => onClose()"
|
||||
>
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'sub_system',
|
||||
name:
|
||||
currentAuthCode === 'PF2'
|
||||
? 'energyManagement'
|
||||
: currentAuthCode === 'PF11'
|
||||
? 'setting'
|
||||
: 'sub_system',
|
||||
params: {
|
||||
main_system_id: main.main_system_tag,
|
||||
sub_system_id: sub.sub_system_tag,
|
||||
floor_id: 'main',
|
||||
...(currentAuthCode === 'PF2' || currentAuthCode === 'PF11'
|
||||
? { type: sub.type }
|
||||
: { floor_id: 'main' }),
|
||||
},
|
||||
}"
|
||||
>
|
||||
@ -169,8 +206,30 @@ onMounted(() => {
|
||||
</a-drawer>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
/**menu**/
|
||||
.menu-box {
|
||||
@apply flex flex-wrap lg:flex-row flex-col items-start lg:justify-center relative z-0 h-full w-60 lg:w-auto;
|
||||
}
|
||||
|
||||
.menu-box .btn-group {
|
||||
@apply bg-transparent lg:w-[95px] w-full mb-5 lg:mb-0;
|
||||
}
|
||||
|
||||
.menu-box .btn-group span {
|
||||
@apply text-2xl ms-2 lg:ms-0 lg:text-sm;
|
||||
}
|
||||
|
||||
.menu-box > li {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.menu-box > li:not(:last-child)::after {
|
||||
@apply absolute top-5 bottom-0 left-20 right-0 lg:block hidden w-6 h-0.5 bg-[#93c0dc] z-0;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.router-link-active.router-link-exact-active {
|
||||
color: #93c0dc;
|
||||
@apply text-[#93c0dc];
|
||||
}
|
||||
|
||||
:deep(.ant-menu-submenu-selected) {
|
||||
|
@ -15,14 +15,14 @@ const toggleLanguage = (lang) => {
|
||||
<button
|
||||
tabindex="0"
|
||||
type="button"
|
||||
class="flex flex-col justify-center items-center btn-group"
|
||||
class="flex flex-col justify-center items-center bg-transparent w-[95px]"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'globe']"
|
||||
size="2x"
|
||||
class="text-white w-10 m-auto"
|
||||
/>
|
||||
<span class="text-white">{{ $t("language") }}</span>
|
||||
<span class="text-white block mt-0">{{ $t("language") }}</span>
|
||||
</button>
|
||||
<ul
|
||||
tabindex="0"
|
||||
|
@ -8,25 +8,56 @@
|
||||
"table": {
|
||||
"no_data": "表中数据为空",
|
||||
"in_otal": "笔资料",
|
||||
"skip_to": "跳至"
|
||||
"skip_to": "跳至",
|
||||
"serial_number": "序列号",
|
||||
"name": "名称",
|
||||
"time": "时间"
|
||||
},
|
||||
"upload": {
|
||||
"title": "选择一个文件或拖放到这里",
|
||||
"description": "档案不超过 10MB"
|
||||
"description": "档案不超过 10MB",
|
||||
"formats": "档案格式"
|
||||
},
|
||||
"dashboard": {
|
||||
"yesterday_today": "昨天/今天",
|
||||
"elec_consumption_comparison": "用电量比较",
|
||||
"today_electricity_consumption": "今日用电量",
|
||||
"yesterday_electricity_consumption": "昨天用电量",
|
||||
"elec_consumption_comparison_trend": "用电量比较趋势",
|
||||
"electricity_consumption": "用电量",
|
||||
"today_electricity_consumption": "今日用电量 ( kWH )",
|
||||
"yesterday_electricity_consumption": "昨天用电量 ( kWH )",
|
||||
"instant_power": "即时功率 ( kW )",
|
||||
"instant_contract_capacity_ratio": "契約容量佔比 ( % )",
|
||||
"this_last_week": "本周/上周",
|
||||
"thisweek_electricity_consumption": "本周用电量",
|
||||
"lastweek_electricity_consumption": "上周用电量"
|
||||
"lastweek_electricity_consumption": "上周用电量",
|
||||
"one_hour": "1小时",
|
||||
"four_hour": "4小时",
|
||||
"eight_hour": "8小时",
|
||||
"energy_ranking": "能耗排行",
|
||||
"last_30_days_energy_trend": "近30天能耗趋势",
|
||||
"today_energy_consumption": "本日能耗",
|
||||
"this_month_energy_consumption": "本月能耗",
|
||||
"relative_energy_consumption": "环比能耗",
|
||||
"daily_relative_change": "日环比",
|
||||
"weekly_relative_change": "周环比",
|
||||
"monthly_relative_change": "月环比",
|
||||
"yearly_relative_change": "年环比",
|
||||
"today": "今日",
|
||||
"yesterday": "昨日",
|
||||
"this_week": "本周",
|
||||
"last_week": "上周",
|
||||
"this_month": "本月",
|
||||
"last_month": "上月",
|
||||
"this_year": "今年",
|
||||
"last_year": "去年",
|
||||
"work_order": "工单",
|
||||
"system_status": "系统状态"
|
||||
},
|
||||
"history": {
|
||||
"title": "历史资料",
|
||||
"building_name": "厂区",
|
||||
"device_name": "设备名称",
|
||||
"system_category": "系统类别",
|
||||
"device_category": "设备类别",
|
||||
"category": "类别",
|
||||
"value": "数值",
|
||||
@ -52,6 +83,11 @@
|
||||
"green_elec": "绿电",
|
||||
"immediate_demand": "即时需量",
|
||||
"average_demand": "平均需量",
|
||||
"real_time_Trend": "即时趋势",
|
||||
"contract_capacity": "契约容量",
|
||||
"alert_capacity": "警戒容量",
|
||||
"reset_value": "复归值",
|
||||
"edit_automatic_demand": "编辑自动需量",
|
||||
"elec_bills": "今年电费累计(元)",
|
||||
"interval_elec_charges": "区间电费(元)",
|
||||
"year_carbon_emission": "今年碳排当量累计(公斤)",
|
||||
@ -61,12 +97,70 @@
|
||||
"monthly_elec_consumption": "每月用电分析",
|
||||
"monthly_carbon_emission_and_reduction": "每月碳排当量 (kgCO2e)",
|
||||
"monthly_bill_power": "每月计费度数 (kWh)",
|
||||
"interval_bill_degree": "区间计费度数"
|
||||
"interval_bill_degree": "区间计费度数",
|
||||
"peak": "尖峰",
|
||||
"semi_peak": "半尖峰",
|
||||
"off_peak": "离峰",
|
||||
"var_elec_cost": "流动电费",
|
||||
"fixed_elec_cost": "基本电费",
|
||||
"total_elec_cost": "总电费",
|
||||
"carbon_equivalent": "碳排当量",
|
||||
"edit_carbon_emission": "编辑碳排放系数",
|
||||
"carbon_emission_coefficient": "碳排放系数",
|
||||
"electricity_classification": "用电分类",
|
||||
"electricity_price": "电费每度单价",
|
||||
"floor": "楼层",
|
||||
"maximum": "最大值",
|
||||
"maximum_time": "最大值时间",
|
||||
"minimum": "最小值",
|
||||
"minimum_time": "最小值时间",
|
||||
"average_value": "平均值",
|
||||
"start_value": "起始值(kWh)",
|
||||
"end_value": "截止值(kWh)",
|
||||
"difference": "差值(kWh)",
|
||||
"power_consumption": "用电量(kWh)",
|
||||
"ranking": "排名",
|
||||
"subtotal": "小计",
|
||||
"unit_price": "单价",
|
||||
"total_amount": "金额总计",
|
||||
"elec_price_list": "电价表",
|
||||
"residential": "住宅型",
|
||||
"standard": "标准型",
|
||||
"simple_elec_price_two_stage": "简易型时间电价二段式",
|
||||
"simple_elec_price_three_stage": "简易型时间电价三段式",
|
||||
"classification": "分类",
|
||||
"summer_months": "夏月",
|
||||
"non_summer_months": "非夏月",
|
||||
"time_outside_summer_months": "夏月以外的时间",
|
||||
"basic_elec_charge": "基本电费",
|
||||
"charged_per_household": "按户计收",
|
||||
"per_household_month": "每户每月",
|
||||
"mon_to_friday": "周一~周五",
|
||||
"peak_hours": "尖峰时间",
|
||||
"semi_peak_hours": "半尖峰时间",
|
||||
"off_peak_hours": "离峰时间",
|
||||
"price_per_kwh": "每度",
|
||||
"all_day": "全日",
|
||||
"sat_sun_off_peak_days": "周六、周日及离峰日",
|
||||
"usage_over_2000kwh": "每月总度数超过2000度之部分",
|
||||
"add": "加",
|
||||
"standard_time_of_use_tariff_2_stage": "标准型时间电价二段式",
|
||||
"standard_time_of_use_tariff_3_stage": "标准型时间电价三段式",
|
||||
"single_phase": "单相",
|
||||
"three_phase": "三相",
|
||||
"frequent_contract": "经常契约",
|
||||
"per_kw_per_month": "每瓩每月",
|
||||
"non_summer_contract": "非夏日契约",
|
||||
"saturday_semi_peak_contract": "周六半尖峰契约",
|
||||
"off_peak_contract": "离峰契约",
|
||||
"variable_electricity_charge": "流动电费",
|
||||
"saturday": "周六",
|
||||
"sunday_and_off_peak_days": "周日及离峰日"
|
||||
},
|
||||
"alarm": {
|
||||
"title": "显示警告",
|
||||
"notify": "异常通知",
|
||||
"number": "异常编号",
|
||||
"number": "异常ID",
|
||||
"category": "异常类别",
|
||||
"device_name": "设备名称",
|
||||
"message": "异常讯息",
|
||||
@ -84,9 +178,10 @@
|
||||
"end_date": "结束日期",
|
||||
"building_and_floor": "栋别-楼层",
|
||||
"uuid": "异常ID",
|
||||
"alarmClass": "异常类别",
|
||||
"alarmClass": "告警条件",
|
||||
"device_name": "设备名称",
|
||||
"device_number": "设备编号",
|
||||
"device_point_name": "点位名称",
|
||||
"date": "发生日期",
|
||||
"time": "发生时间",
|
||||
"error_msg": "异常原因",
|
||||
@ -113,10 +208,12 @@
|
||||
"qualifications": "限定条件",
|
||||
"upper_limit": "上限",
|
||||
"lower_limit": "下限",
|
||||
"delay": "持续秒数",
|
||||
"highDelay": "上限持续秒数",
|
||||
"lowDelay": "下限持续秒数",
|
||||
"warning_method": "警示方式",
|
||||
"warning_time": "警示时间",
|
||||
"warning_value": "警示值",
|
||||
"operation": "功能",
|
||||
"alarm_settings": "异常设定",
|
||||
"time_setting": "时间设定",
|
||||
@ -128,7 +225,23 @@
|
||||
"notify_email": "email",
|
||||
"notify_items": "通知项目",
|
||||
"notify_list": "通知名单",
|
||||
"choose": "选择"
|
||||
"choose": "选择",
|
||||
"day_time": "星期/时间",
|
||||
"click_time_period": "请用滑鼠点击时间段",
|
||||
"clear": "清空",
|
||||
"sunday": "星期日",
|
||||
"monday": "星期一",
|
||||
"tuesday": "星期二",
|
||||
"wednesday": "星期三",
|
||||
"thursday": "星期四",
|
||||
"friday": "星期五",
|
||||
"saturday": "星期六",
|
||||
"schedule_name": "时段名称",
|
||||
"schedule_content": "时段内容",
|
||||
"reorganization": "MQTT 告警重整",
|
||||
"online": "在线",
|
||||
"offline": "离线",
|
||||
"alarm": "告警"
|
||||
},
|
||||
"operation": {
|
||||
"title": "运维管理",
|
||||
@ -142,13 +255,14 @@
|
||||
"start_time": "预计开始时间",
|
||||
"upload": "档案上传",
|
||||
"finish_time": "完成时间",
|
||||
"updated_time": "更新时间",
|
||||
"operation": "功能",
|
||||
"vendor": "厂商",
|
||||
"contact_person": "联络人",
|
||||
"phone": "电话",
|
||||
"email": "email",
|
||||
"created_at": "建立日期",
|
||||
"maintainance": "保养",
|
||||
"maintenance": "保养",
|
||||
"repair": "维修",
|
||||
"company_info": "厂商资料",
|
||||
"repair_item": "维修项目",
|
||||
@ -156,6 +270,8 @@
|
||||
"responsible_vendor": "负责厂商",
|
||||
"not_completed": "未完成",
|
||||
"completed": "已完成",
|
||||
"complete": "已完成",
|
||||
"incomplete": "未完成",
|
||||
"worker_id": "工作人员编号",
|
||||
"notice": "注意事项",
|
||||
"result_description": "结果描述",
|
||||
@ -181,14 +297,20 @@
|
||||
"index": "编号",
|
||||
"oriOrgName": "档案",
|
||||
"operation": "功能",
|
||||
"upload": "图资上传"
|
||||
"folder_path": "资料夹路径",
|
||||
"upload": "图资上传",
|
||||
"staging_area": "删除暂存区",
|
||||
"no_path": "无资料夹路径"
|
||||
},
|
||||
"assetManagement": {
|
||||
"title": "资产管理",
|
||||
"add_category": "新增类别",
|
||||
"add_system_category": "新增系统类别",
|
||||
"edit_system_category": "修改系统类别",
|
||||
"add_device_category": "新增设备类别",
|
||||
"edit_device_category": "修改设备类别",
|
||||
"system_name": "名称",
|
||||
"system_value": "代号",
|
||||
"system_parent": "所属大类",
|
||||
"system_parent": "所属系統",
|
||||
"device_number": "设备编号",
|
||||
"device_name": "设备名称",
|
||||
"asset_number": "资产编号",
|
||||
@ -216,7 +338,10 @@
|
||||
"associated_device": "关联设备",
|
||||
"choose": "选择",
|
||||
"index": "编号",
|
||||
"floor_plan": "平面图"
|
||||
"floor_plan": "平面图",
|
||||
"department": "部门",
|
||||
"department_name": "部门名称",
|
||||
"building": "栋别"
|
||||
},
|
||||
"accountManagement": {
|
||||
"account_title": "帐号管理",
|
||||
@ -236,7 +361,7 @@
|
||||
"phone": "手机",
|
||||
"created_at": "建立时间",
|
||||
"operation": "功能",
|
||||
"name_placeholder": "请输入使用者名称",
|
||||
"name_placeholder": "请输入使用者、帐号名称",
|
||||
"role_placeholder": "请输入角色名称",
|
||||
"change_password": "变更密码",
|
||||
"choose": "选择"
|
||||
@ -260,7 +385,44 @@
|
||||
"email_format": "请输入正确 Email 地址",
|
||||
"password_format": "密码长度至少8码,必须包含英文及数字",
|
||||
"start_time_placeholder": "请输入预计开始日期",
|
||||
"finish_time_placeholder": "请输入完成日期",
|
||||
"rename": "重新命名",
|
||||
"download": "下载"
|
||||
"download": "下载",
|
||||
"confirm": "确认",
|
||||
"restore": "复原",
|
||||
"stop_edit": "停止修改",
|
||||
"start_edit": "开始修改",
|
||||
"convert": "轉換"
|
||||
},
|
||||
"msg": {
|
||||
"sure_to_delete": "是否确认删除该项目?",
|
||||
"sure_to_delete_permanent": "是否确认永久删除该项目?",
|
||||
"delete_success": "删除成功",
|
||||
"delete_failed": "删除失败",
|
||||
"mqtt_refresh": "重新设定成功",
|
||||
"schema_name_required": "架构名称栏位必填",
|
||||
"incorrect_format":"格式不正确",
|
||||
"send_successfully":"送出成功",
|
||||
"edit_successfully":"修改成功"
|
||||
},
|
||||
"setting": {
|
||||
"electricity_meter": "电表",
|
||||
"MQTT_parse": "MQTT 解析",
|
||||
"schema": "架构",
|
||||
"point": "点位",
|
||||
"description": "描述",
|
||||
"IoT_point_name": "IoT 点位名称",
|
||||
"IoT_point_code": "IoT 点位代号",
|
||||
"number_of_decimal_places": "小数位数",
|
||||
"boolean_value": "布林值",
|
||||
"hide_point": "点位显示",
|
||||
"hide_switch": "switch 功能",
|
||||
"switch_on_message": "switch 开启时传送的讯息",
|
||||
"switch_off_message": "switch 关闭时传送的讯息",
|
||||
"schema_name": "架构名称",
|
||||
"IoT_point_structure": "IoT点位结构",
|
||||
"system_point_name": "系统点位名称",
|
||||
"json_format_text": "请贴上 JSON 格式数据",
|
||||
"json_click_text": "请在左侧输入JSON并点选转换按钮"
|
||||
}
|
||||
}
|
||||
|
@ -8,25 +8,56 @@
|
||||
"table": {
|
||||
"no_data": "表中數據為空",
|
||||
"in_otal": "筆資料",
|
||||
"skip_to": "跳至"
|
||||
"skip_to": "跳至",
|
||||
"serial_number": "序號",
|
||||
"name": "姓名",
|
||||
"time": "時間"
|
||||
},
|
||||
"upload": {
|
||||
"title": "選擇一個文件或拖放到這裡",
|
||||
"description": "檔案不超過 10MB"
|
||||
"description": "檔案不超過 10MB",
|
||||
"formats": "檔案格式"
|
||||
},
|
||||
"dashboard": {
|
||||
"yesterday_today": "昨天/今天",
|
||||
"elec_consumption_comparison": "用電量比較",
|
||||
"today_electricity_consumption": "今日用電量",
|
||||
"yesterday_electricity_consumption": "昨天用電量",
|
||||
"elec_consumption_comparison_trend": "用電量比較趨勢",
|
||||
"electricity_consumption": "用電量",
|
||||
"today_electricity_consumption": "今日用電量 ( kWH )",
|
||||
"yesterday_electricity_consumption": "昨天用電量 ( kWH )",
|
||||
"instant_power": "即時功率 ( kW )",
|
||||
"instant_contract_capacity_ratio": "契約容量佔比 ( % )",
|
||||
"this_last_week": "本週/上週",
|
||||
"thisweek_electricity_consumption": "本周用電量",
|
||||
"lastweek_electricity_consumption": "上週用電量"
|
||||
"lastweek_electricity_consumption": "上週用電量",
|
||||
"one_hour": "1小時",
|
||||
"four_hour": "4小時",
|
||||
"eight_hour": "8小時",
|
||||
"energy_ranking": "能耗排行",
|
||||
"last_30_days_energy_trend": "近30天能耗趨勢",
|
||||
"today_energy_consumption": "本日能耗",
|
||||
"this_month_energy_consumption": "本月能耗",
|
||||
"relative_energy_consumption": "環比能耗",
|
||||
"daily_relative_change": "日環比",
|
||||
"weekly_relative_change": "周環比",
|
||||
"monthly_relative_change": "月環比",
|
||||
"yearly_relative_change": "年環比",
|
||||
"today": "今日",
|
||||
"yesterday": "昨日",
|
||||
"this_week": "本周",
|
||||
"last_week": "上周",
|
||||
"this_month": "本月",
|
||||
"last_month": "上月",
|
||||
"this_year": "今年",
|
||||
"last_year": "去年",
|
||||
"work_order": "工單",
|
||||
"system_status": "系統狀態"
|
||||
},
|
||||
"history": {
|
||||
"title": "歷史資料",
|
||||
"building_name": "廠區",
|
||||
"device_name": "設備名稱",
|
||||
"system_category": "系統類別",
|
||||
"device_category": "設備類別",
|
||||
"category": "類別",
|
||||
"value": "數值",
|
||||
@ -52,6 +83,11 @@
|
||||
"green_elec": "綠電",
|
||||
"immediate_demand": "即時需量",
|
||||
"average_demand": "平均需量",
|
||||
"real_time_Trend": "即時趨勢",
|
||||
"contract_capacity": "契約容量",
|
||||
"alert_capacity": "警戒容量",
|
||||
"reset_value": "復歸值",
|
||||
"edit_automatic_demand": "編輯自動需量",
|
||||
"elec_bills": "今年電費累計(元)",
|
||||
"interval_elec_charges": "區間電費(元)",
|
||||
"year_carbon_emission": "今年碳排當量累計(公斤)",
|
||||
@ -61,12 +97,70 @@
|
||||
"monthly_elec_consumption": "每月用電分析",
|
||||
"monthly_carbon_emission_and_reduction": "每月碳排當量 (kgCO2e)",
|
||||
"monthly_bill_power": "每月計費度數 (kWh)",
|
||||
"interval_bill_degree": "區間計費度數"
|
||||
"interval_bill_degree": "區間計費度數",
|
||||
"peak": "尖峰",
|
||||
"semi_peak": "半尖峰",
|
||||
"off_peak": "離峰",
|
||||
"var_elec_cost": "流動電費",
|
||||
"fixed_elec_cost": "基本電費",
|
||||
"total_elec_cost": "總電費",
|
||||
"carbon_equivalent": "碳排當量",
|
||||
"edit_carbon_emission": "編輯碳排放係數",
|
||||
"carbon_emission_coefficient": "碳排放係數",
|
||||
"electricity_classification": "用電分類",
|
||||
"electricity_price": "電費每度單價",
|
||||
"floor": "樓層",
|
||||
"maximum": "最大值",
|
||||
"maximum_time": "最大值時間",
|
||||
"minimum": "最小值",
|
||||
"minimum_time": "最小值時間",
|
||||
"average_value": "平均值",
|
||||
"start_value": "起始值(kWh)",
|
||||
"end_value": "截止值(kWh)",
|
||||
"difference": "差值(kWh)",
|
||||
"power_consumption": "用電量(kWh)",
|
||||
"ranking": "排名",
|
||||
"subtotal": "小計",
|
||||
"unit_price": "單價",
|
||||
"total_amount": "金額總計",
|
||||
"elec_price_list": "電價表",
|
||||
"residential": "住宅型",
|
||||
"standard": "標準型",
|
||||
"simple_elec_price_two_stage": "簡易型時間電價二段式",
|
||||
"simple_elec_price_three_stage": "簡易型時間電價三段式",
|
||||
"classification": "分類",
|
||||
"summer_months": "夏月",
|
||||
"non_summer_months": "非夏月",
|
||||
"time_outside_summer_months": "夏月以外的時間",
|
||||
"basic_elec_charge": "基本電費",
|
||||
"charged_per_household": "按戶計收",
|
||||
"per_household_month": "每戶每月",
|
||||
"mon_to_friday": "週一~週五",
|
||||
"peak_hours": "尖峰時間",
|
||||
"semi_peak_hours": "半尖峰時間",
|
||||
"off_peak_hours": "離峰時間",
|
||||
"price_per_kwh": "每度",
|
||||
"all_day": "全日",
|
||||
"sat_sun_off_peak_days": "週六、週日及離峰日",
|
||||
"usage_over_2000kwh": "每月總度數超過2000度之部分",
|
||||
"add": "加",
|
||||
"standard_time_of_use_tariff_2_stage": "標準型時間電價二段式",
|
||||
"standard_time_of_use_tariff_3_stage": "標準型時間電價三段式",
|
||||
"single_phase": "單相",
|
||||
"three_phase": "三相",
|
||||
"frequent_contract": "經常契約",
|
||||
"per_kw_per_month": "每瓩每月",
|
||||
"non_summer_contract": "非夏日契約",
|
||||
"saturday_semi_peak_contract": "週六半尖峰契約",
|
||||
"off_peak_contract": "離峰契約",
|
||||
"variable_electricity_charge": "流動電費",
|
||||
"saturday": "週六",
|
||||
"sunday_and_off_peak_days": "週日及離峰日"
|
||||
},
|
||||
"alarm": {
|
||||
"title": "顯示警告",
|
||||
"notify": "異常通知",
|
||||
"number": "異常編號",
|
||||
"number": "異常ID",
|
||||
"category": "異常類別",
|
||||
"device_name": "設備名稱",
|
||||
"message": "異常訊息",
|
||||
@ -84,9 +178,10 @@
|
||||
"end_date": "結束日期",
|
||||
"building_and_floor": "棟別-樓層",
|
||||
"uuid": "異常ID",
|
||||
"alarmClass": "異常類別",
|
||||
"alarmClass": "告警條件",
|
||||
"device_name": "設備名稱",
|
||||
"device_number": "設備編號",
|
||||
"device_point_name": "點位名稱",
|
||||
"date": "發生日期",
|
||||
"time": "發生時間",
|
||||
"error_msg": "異常原因",
|
||||
@ -113,10 +208,12 @@
|
||||
"qualifications": "限定條件",
|
||||
"upper_limit": "上限",
|
||||
"lower_limit": "下限",
|
||||
"delay": "持續秒數",
|
||||
"highDelay": "上限持續秒數",
|
||||
"lowDelay": "下限持續秒數",
|
||||
"warning_method": "警示方式",
|
||||
"warning_time": "警示時間",
|
||||
"warning_value": "警示值",
|
||||
"operation": "功能",
|
||||
"alarm_settings": "異常設定",
|
||||
"time_setting": "時間設定",
|
||||
@ -128,7 +225,23 @@
|
||||
"notify_email": "email",
|
||||
"notify_items": "通知項目",
|
||||
"notify_list": "通知名單",
|
||||
"choose": "選擇"
|
||||
"choose": "選擇",
|
||||
"day_time": "星期/時間",
|
||||
"click_time_period": "請用滑鼠點擊時間段",
|
||||
"clear": "清空",
|
||||
"sunday": "星期日",
|
||||
"monday": "星期一",
|
||||
"tuesday": "星期二",
|
||||
"wednesday": "星期三",
|
||||
"thursday": "星期四",
|
||||
"friday": "星期五",
|
||||
"saturday": "星期六",
|
||||
"schedule_name": "時段名稱",
|
||||
"schedule_content": "時段內容",
|
||||
"reorganization": "MQTT 告警重整",
|
||||
"online": "在線",
|
||||
"offline": "離線",
|
||||
"alarm": "告警"
|
||||
},
|
||||
"operation": {
|
||||
"title": "運維管理",
|
||||
@ -142,13 +255,14 @@
|
||||
"start_time": "預計開始時間",
|
||||
"upload": "檔案上傳",
|
||||
"finish_time": "完成時間",
|
||||
"updated_time": "更新時間",
|
||||
"operation": "功能",
|
||||
"vendor": "廠商",
|
||||
"contact_person": "聯絡人",
|
||||
"phone": "電話",
|
||||
"email": "email",
|
||||
"created_at": "建立日期",
|
||||
"maintainance": "保養",
|
||||
"maintenance": "保養",
|
||||
"repair": "維修",
|
||||
"company_info": "廠商資料",
|
||||
"repair_item": "維修項目",
|
||||
@ -156,6 +270,8 @@
|
||||
"responsible_vendor": "負責廠商",
|
||||
"not_completed": "未完成",
|
||||
"completed": "已完成",
|
||||
"complete": "已完成",
|
||||
"incomplete": "未完成",
|
||||
"worker_id": "工作人員編號",
|
||||
"notice": "注意事項",
|
||||
"result_description": "結果描述",
|
||||
@ -181,14 +297,20 @@
|
||||
"index": "編號",
|
||||
"oriOrgName": "檔案",
|
||||
"operation": "功能",
|
||||
"upload": "圖資上傳"
|
||||
"folder_path": "資料夾路徑",
|
||||
"upload": "圖資上傳",
|
||||
"staging_area": "刪除暫存區",
|
||||
"no_path": "無資料夾路徑"
|
||||
},
|
||||
"assetManagement": {
|
||||
"title": "資產管理",
|
||||
"add_category": "新增類別",
|
||||
"add_system_category": "新增系統類別",
|
||||
"edit_system_category": "修改系統類別",
|
||||
"add_device_category": "新增設備類別",
|
||||
"edit_device_category": "修改設備類別",
|
||||
"system_name": "名稱",
|
||||
"system_value": "代號",
|
||||
"system_parent": "所屬大類",
|
||||
"system_parent": "所屬系統",
|
||||
"device_number": "設備編號",
|
||||
"device_name": "設備名稱",
|
||||
"asset_number": "資產編號",
|
||||
@ -216,7 +338,10 @@
|
||||
"associated_device": "關聯設備",
|
||||
"choose": "選擇",
|
||||
"index": "編號",
|
||||
"floor_plan": "平面圖"
|
||||
"floor_plan": "平面圖",
|
||||
"department": "部門",
|
||||
"department_name": "部門名稱",
|
||||
"building": "棟別"
|
||||
},
|
||||
"accountManagement": {
|
||||
"account_title": "帳號管理",
|
||||
@ -236,7 +361,7 @@
|
||||
"phone": "手機",
|
||||
"created_at": "建立時間",
|
||||
"operation": "功能",
|
||||
"name_placeholder": "請輸入使用者名稱",
|
||||
"name_placeholder": "請輸入使用者、帳號名稱",
|
||||
"role_placeholder": "請輸入角色名稱",
|
||||
"change_password": "變更密碼",
|
||||
"choose": "選擇"
|
||||
@ -260,7 +385,44 @@
|
||||
"email_format": "請輸入正確的 Email 地址",
|
||||
"password_format": "密碼長度至少8碼,必須包含英文及數字",
|
||||
"start_time_placeholder": "請輸入預計開始日期",
|
||||
"finish_time_placeholder": "請輸入完成日期",
|
||||
"rename": "重新命名",
|
||||
"download": "下載"
|
||||
"download": "下載",
|
||||
"confirm": "確認",
|
||||
"restore": "復原",
|
||||
"stop_edit": "停止修改",
|
||||
"start_edit": "開始修改",
|
||||
"convert": "轉換"
|
||||
},
|
||||
"msg": {
|
||||
"sure_to_delete": "是否確認刪除該項目?",
|
||||
"sure_to_delete_permanent": "是否確認永久刪除該項目?",
|
||||
"delete_success": "刪除成功",
|
||||
"delete_failed": "刪除失敗",
|
||||
"mqtt_refresh": "重新設定成功",
|
||||
"schema_name_required": "架構名稱欄位必填",
|
||||
"incorrect_format":"格式不正確",
|
||||
"send_successfully":"送出成功",
|
||||
"edit_successfully":"修改成功"
|
||||
},
|
||||
"setting": {
|
||||
"electricity_meter":"電表",
|
||||
"MQTT_parse": "MQTT 解析",
|
||||
"schema": "架構",
|
||||
"point": "點位",
|
||||
"description": "描述",
|
||||
"IoT_point_name": "IoT 點位名稱",
|
||||
"IoT_point_code": "IoT 點位代號",
|
||||
"number_of_decimal_places": "小數位數",
|
||||
"boolean_value": "布林值",
|
||||
"hide_point": "點位顯示",
|
||||
"hide_switch": "switch 功能",
|
||||
"switch_on_message": "switch 開啟時傳送的訊息",
|
||||
"switch_off_message": "switch 關閉時傳送的訊息",
|
||||
"schema_name": "架構名稱",
|
||||
"IoT_point_structure": "IoT點位結構",
|
||||
"system_point_name": "系統點位名稱",
|
||||
"json_format_text": "請貼上 JSON 格式數據",
|
||||
"json_click_text": "請在左側輸入JSON並點選轉換按鈕"
|
||||
}
|
||||
}
|
||||
|
@ -8,16 +8,56 @@
|
||||
"table": {
|
||||
"no_data": "No data",
|
||||
"in_otal": "items in total",
|
||||
"skip_to": "Skip to"
|
||||
"skip_to": "Skip to",
|
||||
"serial_number": "Serial Number",
|
||||
"name": "Name",
|
||||
"time": "Time"
|
||||
},
|
||||
"upload": {
|
||||
"title": "Select a file or drag and drop here",
|
||||
"description": "File size cannot exceed 10MB"
|
||||
"description": "File size cannot exceed 10MB",
|
||||
"formats": "File formats"
|
||||
},
|
||||
"dashboard": {
|
||||
"yesterday_today": "Yesterday / Today's",
|
||||
"elec_consumption_comparison": "Electricity Consumption Comparison",
|
||||
"elec_consumption_comparison_trend": "Electricity Consumption Comparison Trend",
|
||||
"electricity_consumption": "electricity consumption",
|
||||
"today_electricity_consumption": "Today's electricity consumption in kWH",
|
||||
"yesterday_electricity_consumption": "Yesterday's electricity consumption in kWH",
|
||||
"instant_power": "Instant power kW",
|
||||
"instant_contract_capacity_ratio": "Instant contract capacity ratio %",
|
||||
"this_last_week": "This Week's / Last Week's",
|
||||
"thisweek_electricity_consumption": "This week’s electricity consumption",
|
||||
"lastweek_electricity_consumption": "Last week’s electricity consumption",
|
||||
"one_hour": "1 hour",
|
||||
"four_hour": "4 hour",
|
||||
"eight_hour": "8 hour",
|
||||
"energy_ranking": "Energy consumption ranking",
|
||||
"last_30_days_energy_trend": "Energy consumption trend for the past 30 days",
|
||||
"today_energy_consumption": "Today",
|
||||
"this_month_energy_consumption": "This month",
|
||||
"relative_energy_consumption": "Energy consumption trend",
|
||||
"daily_relative_change": "Daily",
|
||||
"weekly_relative_change": "Weekly",
|
||||
"monthly_relative_change": "Monthly",
|
||||
"yearly_relative_change": "Yearly",
|
||||
"today": "Today",
|
||||
"yesterday": "Yesterday",
|
||||
"this_week": "This week",
|
||||
"last_week": "Last week",
|
||||
"this_month": "This month",
|
||||
"last_month": "Last month",
|
||||
"this_year": "This year",
|
||||
"last_year": "Last year",
|
||||
"work_order": "Work Order",
|
||||
"system_status": "System Status"
|
||||
},
|
||||
"history": {
|
||||
"title": "Historical Data",
|
||||
"building_name": "Building",
|
||||
"device_name": "Device Name",
|
||||
"system_category": "System Category",
|
||||
"device_category": "Device Category",
|
||||
"category": "Category",
|
||||
"value": "Value",
|
||||
@ -31,15 +71,6 @@
|
||||
"end_date": "End date",
|
||||
"end_time": "End time"
|
||||
},
|
||||
"dashboard": {
|
||||
"yesterday_today": "Yesterday / Today's",
|
||||
"elec_consumption_comparison": "Electricity Consumption Comparison",
|
||||
"today_electricity_consumption": "Today’s electricity consumption",
|
||||
"yesterday_electricity_consumption": "Yesterday’s electricity consumption",
|
||||
"this_last_week": "This Week's / Last Week's",
|
||||
"thisweek_electricity_consumption": "This week’s electricity consumption",
|
||||
"lastweek_electricity_consumption": "Last week’s electricity consumption"
|
||||
},
|
||||
"system": {
|
||||
"status": "Status",
|
||||
"details": "Details",
|
||||
@ -50,8 +81,13 @@
|
||||
"elec_consumption": "Real-time distribution of electricity consumption",
|
||||
"total_elec": "Total electricity consumption",
|
||||
"green_elec": "Green electricity",
|
||||
"immediate_demand": "immediate demand",
|
||||
"average_demand": "average demand",
|
||||
"immediate_demand": "Immediate demand",
|
||||
"average_demand": "Average demand",
|
||||
"real_time_Trend": "Real-time Trend",
|
||||
"contract_capacity": "Contract Capacity",
|
||||
"alert_capacity": "Alert Capacity",
|
||||
"reset_value": "Reset Value",
|
||||
"edit_automatic_demand": "Edit automatic demand",
|
||||
"elec_bills": "Total electricity bills this year (yuan)",
|
||||
"interval_elec_charges": "Interval electricity charges (yuan)",
|
||||
"year_carbon_emission": "Cumulative carbon emission equivalent this year (kg)",
|
||||
@ -61,7 +97,65 @@
|
||||
"monthly_elec_consumption": "Monthly electricity consumption analysis",
|
||||
"monthly_carbon_emission_and_reduction": "Monthly carbon emission equivalent (kgCO2e)",
|
||||
"monthly_bill_power": "Monthly billing power (kWh)",
|
||||
"interval_bill_degree": "Interval billing degree"
|
||||
"interval_bill_degree": "Interval billing degree",
|
||||
"peak": "Peak",
|
||||
"semi_peak": "Semi-Peak",
|
||||
"off_peak": "Off-Peak",
|
||||
"var_elec_cost": "Var. Elec. Cost",
|
||||
"fixed_elec_cost": "Fixed Elec. Cost",
|
||||
"total_elec_cost": "Total Elec. Cost",
|
||||
"carbon_equivalent": "Carbon Equivalent",
|
||||
"edit_carbon_emission": "Edit carbon emission coefficient",
|
||||
"carbon_emission_coefficient": "Carbon emission coefficient",
|
||||
"electricity_classification": "Electricity Classification",
|
||||
"electricity_price": "Electricity charge per unit price",
|
||||
"floor": "Floor",
|
||||
"maximum": "Maximum",
|
||||
"maximum_time": "Maximum time",
|
||||
"minimum": "Minimum value",
|
||||
"minimum_time": "Minimum time",
|
||||
"average_value": "Average value",
|
||||
"start_value": "Start value (kWh)",
|
||||
"end_value": "End value (kWh)",
|
||||
"difference": "Difference (kWh)",
|
||||
"power_consumption": "Power consumption (kWh)",
|
||||
"ranking": "Ranking",
|
||||
"subtotal": "Subtotal",
|
||||
"unit_price": "Unit price",
|
||||
"total_amount": "Total amount",
|
||||
"elec_price_list": "Electricity Price List",
|
||||
"residential": "Residential",
|
||||
"standard": "Standard",
|
||||
"simple_elec_price_two_stage": "Simple Time-of-Use Electricity Price (Two-Tier)",
|
||||
"simple_elec_price_three_stage": "Simple Time-of-Use Electricity Price (Three-Tier)",
|
||||
"classification": "Classification",
|
||||
"summer_months": "Summer Months",
|
||||
"non_summer_months": "Non-Summer Months",
|
||||
"time_outside_summer_months": "Time Outside Summer Months",
|
||||
"basic_elec_charge": "Basic Electricity Charge",
|
||||
"charged_per_household": "Charged Per Household",
|
||||
"per_household_month": "Per Household Per Month",
|
||||
"mon_to_friday": "Monday to Friday",
|
||||
"peak_hours": "Peak Hours",
|
||||
"semi_peak_hours": "Semi-Peak Hours",
|
||||
"off_peak_hours": "Off-Peak Hours",
|
||||
"price_per_kwh": "Price Per kWh",
|
||||
"all_day": "All Day",
|
||||
"sat_sun_off_peak_days": "Saturday, Sunday, and Off-Peak Days",
|
||||
"usage_over_2000kwh": "Usage Over 2000 kWh Per Month",
|
||||
"add": "Add",
|
||||
"standard_time_of_use_tariff_2_stage": "Standard Time-of-Use Tariff (Two-Tier)",
|
||||
"standard_time_of_use_tariff_3_stage": "Standard Time-of-Use Tariff (Three-Tier)",
|
||||
"single_phase": "Single Phase",
|
||||
"three_phase": "Three Phase",
|
||||
"frequent_contract": "Demand Charge",
|
||||
"per_kw_per_month": "Per kW Per Month",
|
||||
"non_summer_contract": "Non-Summer Demand Charge",
|
||||
"saturday_semi_peak_contract": "Saturday Semi-Peak Demand Charge",
|
||||
"off_peak_contract": "Off-Peak Demand Charge",
|
||||
"variable_electricity_charge": "Variable Electricity Charge",
|
||||
"saturday": "Saturday",
|
||||
"sunday_and_off_peak_days": "Sunday and Off-Peak Days"
|
||||
},
|
||||
"alarm": {
|
||||
"title": "Warning",
|
||||
@ -84,9 +178,10 @@
|
||||
"end_date": "End Date",
|
||||
"building_and_floor": "Building - Floor",
|
||||
"uuid": "Exception ID",
|
||||
"alarmClass": "Exception Category",
|
||||
"alarmClass": "Alarm Conditions",
|
||||
"device_name": "Device Name",
|
||||
"device_number": "Device Number",
|
||||
"device_point_name": "Point Name",
|
||||
"date": "Occurrence Date",
|
||||
"time": "Occurrence Time",
|
||||
"error_msg": "Abnormal Cause",
|
||||
@ -113,10 +208,12 @@
|
||||
"qualifications": "Qualifications",
|
||||
"upper_limit": "Upper Limit",
|
||||
"lower_limit": "Lower Limit",
|
||||
"delay": "Duration (s)",
|
||||
"highDelay": "Max Duration (s)",
|
||||
"lowDelay": "Min Duration (s)",
|
||||
"warning_method": "Warning Method",
|
||||
"warning_time": "Warning Time",
|
||||
"warning_value": "Warning Value",
|
||||
"operation": "Function",
|
||||
"alarm_settings": "Abnormal Alarm Settings",
|
||||
"time_setting": "Time Setting",
|
||||
@ -128,7 +225,23 @@
|
||||
"notify_email": "Email",
|
||||
"notify_items": "Notification Items",
|
||||
"notify_list": "Notification List",
|
||||
"choose": "Choose"
|
||||
"choose": "Choose",
|
||||
"day_time": "Week/Time",
|
||||
"click_time_period": "Please click the time period with your mouse",
|
||||
"clear": "Clear",
|
||||
"sunday": "Sunday",
|
||||
"monday": "Monday",
|
||||
"tuesday": "Tuesday",
|
||||
"wednesday": "Wednesday",
|
||||
"thursday": "Thursday",
|
||||
"friday": "Friday",
|
||||
"saturday": "Saturday",
|
||||
"schedule_name": "Time period name",
|
||||
"schedule_content": "Time period content",
|
||||
"reorganization": "MQTT Alarm Reorganization",
|
||||
"online": "Online",
|
||||
"offline": "Offline",
|
||||
"alarm": "Alarm"
|
||||
},
|
||||
"operation": {
|
||||
"title": "Operation And Maintenance Management",
|
||||
@ -142,13 +255,14 @@
|
||||
"start_time": "Estimated Start Time",
|
||||
"upload": "File Upload",
|
||||
"finish_time": "Completion Time",
|
||||
"updated_time": "Update Time",
|
||||
"operation": "Function",
|
||||
"vendor": "Company",
|
||||
"contact_person": "Contact Person",
|
||||
"phone": "Phone",
|
||||
"email": "Email",
|
||||
"created_at": "Creation Date",
|
||||
"maintenance": "Maintenance",
|
||||
"maintenance": "Upkeep",
|
||||
"repair": "Repair",
|
||||
"company_info": "Company Info",
|
||||
"repair_item": "Repair Item",
|
||||
@ -156,6 +270,8 @@
|
||||
"responsible_vendor": "Responsible Vendor",
|
||||
"not_completed": "Not Completed",
|
||||
"completed": "Completed",
|
||||
"complete": "Comp",
|
||||
"incomplete": "Inc",
|
||||
"worker_id": "Worker ID",
|
||||
"notice": "Notice",
|
||||
"result_description": "Result Description",
|
||||
@ -181,14 +297,20 @@
|
||||
"index": "Serial Number",
|
||||
"oriOrgName": "File",
|
||||
"operation": "Function",
|
||||
"upload": "Upload"
|
||||
"folder_path": "Folder Path",
|
||||
"upload": "Upload",
|
||||
"staging_area": "Staging Area",
|
||||
"no_path": "No path"
|
||||
},
|
||||
"assetManagement": {
|
||||
"title": "Asset Management",
|
||||
"add_category": "Add Category",
|
||||
"add_system_category": "Add system category",
|
||||
"edit_system_category": "Edit system category",
|
||||
"add_device_category": "Add device category",
|
||||
"edit_device_category": "Edit device category",
|
||||
"system_name": "Name",
|
||||
"system_value": "Code",
|
||||
"system_parent": "Category",
|
||||
"system_parent": "System category",
|
||||
"device_number": "Device Number",
|
||||
"device_name": "Device Name",
|
||||
"asset_number": "Asset Number",
|
||||
@ -216,7 +338,10 @@
|
||||
"associated_device": "Associated Devices",
|
||||
"choose": "Choose",
|
||||
"index": "Serial Number",
|
||||
"floor_plan": "Floor Plan"
|
||||
"floor_plan": "Floor Plan",
|
||||
"department": "Department",
|
||||
"department_name": "Department Name",
|
||||
"building": "Building"
|
||||
},
|
||||
"accountManagement": {
|
||||
"account_title": "Account Management",
|
||||
@ -236,8 +361,8 @@
|
||||
"phone": "Phone",
|
||||
"created_at": "Created Time",
|
||||
"operation": "Function",
|
||||
"name_placeholder": "Please enter user name",
|
||||
"role_placeholder": "Please enter the role name",
|
||||
"name_placeholder": "Please enter the user's name / account",
|
||||
"role_placeholder": "Please enter the role's name",
|
||||
"change_password": "Change Password",
|
||||
"choose": "Choose"
|
||||
},
|
||||
@ -254,13 +379,50 @@
|
||||
"submit": "Submit",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"deselect_all": "Deselect all",
|
||||
"select_all": "Select all",
|
||||
"deselect_all": "Deselect All",
|
||||
"select_all": "Select All",
|
||||
"phone_format": "Please enter the correct phone number format",
|
||||
"email_format": "Please enter correct email address",
|
||||
"password_format": "The password must be at least 8 characters long and must contain English and numbers.",
|
||||
"start_time_placeholder": "Please enter expected start date",
|
||||
"finish_time_placeholder": "Please enter completion date",
|
||||
"rename": "Rename",
|
||||
"download": "Download"
|
||||
"download": "Download",
|
||||
"confirm": "Confirm",
|
||||
"restore": "Restore",
|
||||
"stop_edit": "Stop editing",
|
||||
"start_edit": "Start editing",
|
||||
"convert": "Convert"
|
||||
},
|
||||
"msg": {
|
||||
"sure_to_delete": "Are you sure to delete this item?",
|
||||
"sure_to_delete_permanent": "Are you sure you want to permanently delete this item?",
|
||||
"delete_success": "Delete successfully",
|
||||
"delete_failed": "Delete failed",
|
||||
"mqtt_refresh": "MQTT reset successful",
|
||||
"schema_name_required": "The schema name field is required",
|
||||
"incorrect_format":"Incorrect format",
|
||||
"send_successfully":"Sent successfully",
|
||||
"edit_successfully":"Edited successfully"
|
||||
},
|
||||
"setting": {
|
||||
"electricity_meter": "Electricity Meter",
|
||||
"MQTT_parse": "MQTT Parse",
|
||||
"schema": "Schema",
|
||||
"point": "Point",
|
||||
"description": "Description",
|
||||
"IoT_point_name": "IoT Point Name",
|
||||
"IoT_point_code": "IoT Point Code",
|
||||
"number_of_decimal_places": "Number of Decimal Places",
|
||||
"boolean_value": "Boolean Value",
|
||||
"hide_point": "Point Display",
|
||||
"hide_switch": "Switch Function",
|
||||
"switch_on_message": "Switch On Message",
|
||||
"switch_off_message": "Switch Off Message",
|
||||
"schema_name": "Schema name",
|
||||
"IoT_point_structure": "IoT Point Structure",
|
||||
"system_point_name": "System Point Name",
|
||||
"json_format_text": "Please paste JSON format data",
|
||||
"json_click_text": "Please enter JSON on the left and click the conversion button"
|
||||
}
|
||||
}
|
||||
|
@ -61,4 +61,10 @@ export const AUTHPAGES = [
|
||||
pageName: "ProductSetting",
|
||||
navigate: "/productSetting",
|
||||
},
|
||||
{
|
||||
authCode: "PF11",
|
||||
icon: "cog",
|
||||
pageName: "Setting",
|
||||
navigate: "/Setting",
|
||||
},
|
||||
];
|
||||
|
@ -38,6 +38,7 @@ import {
|
||||
faFileExcel,
|
||||
faFileWord,
|
||||
faFilePowerpoint,
|
||||
faFileArchive,
|
||||
faFileAlt,
|
||||
faDatabase,
|
||||
faBuilding,
|
||||
@ -57,8 +58,14 @@ import {
|
||||
faEye,
|
||||
faEyeSlash,
|
||||
faGlobe,
|
||||
faDownload
|
||||
faDownload,
|
||||
faStream,
|
||||
faSave,
|
||||
faCrown,
|
||||
faClock,
|
||||
faCheckCircle
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faCircle,faPaperPlane } from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
/* add icons to the library */
|
||||
library.add(
|
||||
@ -97,6 +104,7 @@ library.add(
|
||||
faFileExcel,
|
||||
faFileWord,
|
||||
faFilePowerpoint,
|
||||
faFileArchive,
|
||||
faFileAlt,
|
||||
faDatabase,
|
||||
faBuilding,
|
||||
@ -116,7 +124,14 @@ library.add(
|
||||
faEye,
|
||||
faEyeSlash,
|
||||
faGlobe,
|
||||
faDownload
|
||||
faDownload,
|
||||
faStream,
|
||||
faSave,
|
||||
faCrown,
|
||||
faClock,
|
||||
faCheckCircle,
|
||||
faCircle,
|
||||
faPaperPlane
|
||||
);
|
||||
|
||||
export default library;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import useSelectedFloor from "@/hooks/useSelectedFloor";
|
||||
import { watch, ref, inject } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import useSystemShowData from "@/hooks/useSystemShowData";
|
||||
|
||||
function useForgeFloor() {
|
||||
const route = useRoute();
|
||||
@ -59,9 +60,11 @@ function useForgeFloor() {
|
||||
forgeViewer.value.hide(parseInt(allDbIdsStr[i]));
|
||||
}
|
||||
};
|
||||
|
||||
const { flatSubData } = useSystemShowData();
|
||||
const showDbIdFn = () => {
|
||||
hideDbIdFn();
|
||||
subscribeData.value.forEach((value, index) => {
|
||||
flatSubData.value.forEach((value, index) => {
|
||||
forgeViewer.value.show(value.forge_dbid);
|
||||
});
|
||||
|
||||
@ -83,7 +86,7 @@ function useForgeFloor() {
|
||||
forgeViewer.value?.fitToView([forgeViewer.value.model.getRootId()]);
|
||||
showDbIdFn();
|
||||
} else {
|
||||
hideDbIdFn();
|
||||
showDbIdFn();
|
||||
// forgeViewer.value.clearSelection();
|
||||
// forgeViewer.value.model.setAllVisibility(0);
|
||||
forgeViewer.value.impl.toggleGhosting(false);
|
||||
|
@ -34,12 +34,13 @@ export default function useForgeHeatmap() {
|
||||
const { flatSubData } = useSystemShowData();
|
||||
|
||||
const data = computed(() =>
|
||||
flatSubData.value?.map((d) => ({
|
||||
...d,
|
||||
...Object.fromEntries(
|
||||
d.points.map(({ point, value }) => [point, 0]) || []
|
||||
),
|
||||
}))
|
||||
flatSubData.value?.map((d) => {
|
||||
const pointsMap = d.points ? Object.fromEntries(d.points.map(({ point, value }) => [point, 0])) : {};
|
||||
return {
|
||||
...d,
|
||||
...pointsMap,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
watch(
|
||||
@ -55,7 +56,7 @@ export default function useForgeHeatmap() {
|
||||
);
|
||||
|
||||
const createHeatMap = async () => {
|
||||
if (!dataVizExtn.value) return;
|
||||
if (route.query?.gas === "all" || !route.query?.gas || !dataVizExtn.value) return;
|
||||
const heatMapName = `iot_heatmap_${route.query?.gas}`;
|
||||
console.log("createHeatMap", heatMapName);
|
||||
const {
|
||||
@ -67,8 +68,7 @@ export default function useForgeHeatmap() {
|
||||
const shadingGroup = new SurfaceShadingGroup(`${heatMapName}`);
|
||||
const rooms = new Map();
|
||||
|
||||
const roomSet = new Set(data.value.map(({ room_dbid }) => room_dbid));
|
||||
|
||||
const roomSet = new Set(data.value.filter(({ device_coordinate_3d }) => device_coordinate_3d).map(({ room_dbid }) => room_dbid));
|
||||
// 每個room是一個node
|
||||
[...roomSet].forEach((roomDbId) => {
|
||||
if (!roomDbId) {
|
||||
|
@ -1,20 +1,32 @@
|
||||
import { watch, inject, markRaw, ref, computed, provide } from "vue";
|
||||
import useAlarmStore from "@/stores/useAlarmStore";
|
||||
import hexToRgb from "@/util/hexToRgb";
|
||||
import useSystemShowData from "@/hooks/useSystemShowData"
|
||||
import useSystemShowData from "@/hooks/useSystemShowData";
|
||||
import useForgeHeatmap from "./useForgeHeatmap";
|
||||
import useForgeFloor from "./useForgeFloor";
|
||||
|
||||
export default function useForgeSprite() {
|
||||
const { subscribeData } = inject("system_deviceList");
|
||||
const { getCurrentInfoModalData, clearSelectedDeviceInfo } = inject(
|
||||
"system_selectedDevice"
|
||||
);
|
||||
const { subscribeData, realtimeData } = inject("system_deviceList");
|
||||
const { getCurrentInfoModalData, clearSelectedDeviceInfo, selected_dbid } =
|
||||
inject("system_selectedDevice");
|
||||
const forgeViewer = ref(null);
|
||||
const dataVizExtn = ref(null);
|
||||
let lastClickedDbId = null;
|
||||
|
||||
const { createHeatMap, updateViewExtension } = useForgeHeatmap();
|
||||
const { updateViewerFloor } = useForgeFloor();
|
||||
const { updateViewerFloor } = useForgeFloor();
|
||||
|
||||
const setCameraPosition = (position, target) => {
|
||||
// 使用 THREE.Vector3 定義位置與焦點
|
||||
const newPosition = new THREE.Vector3(position.x, position.y, position.z);
|
||||
const newTarget = new THREE.Vector3(target.x, target.y, target.z);
|
||||
|
||||
// 設定攝影機的新位置與焦點
|
||||
forgeViewer.value.navigation.setView(newPosition, newTarget);
|
||||
|
||||
// 確保 Home 視角
|
||||
forgeViewer.value.autocam.setCurrentViewAsHome(true);
|
||||
};
|
||||
|
||||
const updateDataVisualization = async (viewer) => {
|
||||
if (!forgeViewer.value) {
|
||||
@ -26,7 +38,7 @@ export default function useForgeSprite() {
|
||||
);
|
||||
dataVizExtn.value = markRaw(dataVisualization);
|
||||
updateViewExtension(markRaw(viewer), markRaw(dataVisualization));
|
||||
updateViewerFloor(markRaw(viewer), markRaw(dataVisualization))
|
||||
updateViewerFloor(markRaw(viewer), markRaw(dataVisualization));
|
||||
};
|
||||
|
||||
function onSpriteClicked(event) {
|
||||
@ -51,7 +63,24 @@ export default function useForgeSprite() {
|
||||
}
|
||||
}
|
||||
|
||||
const { flatSubData } = useSystemShowData()
|
||||
const { flatSubData } = useSystemShowData();
|
||||
|
||||
// 根據設備取得即時狀態顏色
|
||||
const getDeviceRealtimeColor = (d) => {
|
||||
if (d.full_name === "SmartSocket-AA001") return "#ff0000";
|
||||
if (
|
||||
d.full_name === "SmartSocket-AA003" ||
|
||||
d.full_name === "SmartSocket-AA004"
|
||||
)
|
||||
return "#888888";
|
||||
const realtimeDevice = realtimeData?.value?.find(
|
||||
(item) => item.device_number === d.device_number
|
||||
);
|
||||
const state = realtimeDevice?.state || "";
|
||||
if (state === "offnormal" || state === "")
|
||||
return d.device_close_color || "#999999";
|
||||
return d.device_normal_color || "#009100";
|
||||
};
|
||||
|
||||
// 創建 sprites
|
||||
const createSprites = async () => {
|
||||
@ -60,30 +89,27 @@ export default function useForgeSprite() {
|
||||
const DataVizCore = Autodesk.DataVisualization.Core;
|
||||
const viewableType = DataVizCore.ViewableType.SPRITE;
|
||||
let spriteColor = new THREE.Color(0xffffff);
|
||||
const BASEURL = import.meta.env.VITE_FORGE_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/hotspot.svg`;
|
||||
const style = new DataVizCore.ViewableStyle(
|
||||
viewableType,
|
||||
spriteColor,
|
||||
spriteIconUrl
|
||||
);
|
||||
const BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const spriteIconUrl = `${BASEURL}/dist/hotspot.svg`;
|
||||
const viewableData = new DataVizCore.ViewableData();
|
||||
viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels
|
||||
flatSubData.value?.forEach((d, index) => {
|
||||
if (d.device_coordinate_3d) {
|
||||
const position = d.device_coordinate_3d;
|
||||
style.color = new THREE.Color(hexToRgb(d.device_normal_color));
|
||||
// 每個都 new 一個 style
|
||||
const pointStyle = new DataVizCore.ViewableStyle(
|
||||
viewableType,
|
||||
new THREE.Color(hexToRgb(getDeviceRealtimeColor(d))),
|
||||
spriteIconUrl
|
||||
);
|
||||
const viewable = new DataVizCore.SpriteViewable(
|
||||
position,
|
||||
style,
|
||||
pointStyle,
|
||||
d.spriteDbId
|
||||
);
|
||||
viewableData.addViewable(viewable);
|
||||
}
|
||||
});
|
||||
// await viewableData.finish();
|
||||
// dataVizExtn.value.addViewables(viewableData);
|
||||
// console.log(dataVizExtn.value);
|
||||
viewableData.finish().then(
|
||||
() => {
|
||||
dataVizExtn.value.addViewables(viewableData);
|
||||
@ -95,6 +121,16 @@ export default function useForgeSprite() {
|
||||
);
|
||||
}
|
||||
};
|
||||
// 監聽 realtimeData 變化,重建 sprites
|
||||
watch(
|
||||
() => realtimeData?.value,
|
||||
() => {
|
||||
if (forgeViewer.value?.isLoadDone()) {
|
||||
createSprites();
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => flatSubData,
|
||||
@ -109,6 +145,19 @@ export default function useForgeSprite() {
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => selected_dbid,
|
||||
() => {
|
||||
if (forgeViewer.value?.isLoadDone()) {
|
||||
cardfitToView(selected_dbid.value);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
const forgeClickListener = () => {
|
||||
console.log("監聽forge");
|
||||
|
||||
@ -122,24 +171,38 @@ export default function useForgeSprite() {
|
||||
);
|
||||
};
|
||||
|
||||
const fitToView = () => {
|
||||
const { x, y, z } = JSON.parse(searchParams.value.camera_position);
|
||||
const newPosition = new THREE.Vector3(x, y, z); //!<<< 相机的新位置
|
||||
const cardfitToView = async ([forge_dbid, spriteDbId]) => {
|
||||
try {
|
||||
// 相機調整
|
||||
const nav = forgeViewer.value.navigation;
|
||||
const camera = nav.getCamera();
|
||||
forgeViewer.value.fitToView([forge_dbid], null, true);
|
||||
const direction = new THREE.Vector3();
|
||||
camera.getWorldDirection(direction);
|
||||
const distanceBack = 30;
|
||||
camera.position.add(direction.multiplyScalar(-distanceBack));
|
||||
const target = nav.getTarget();
|
||||
const fov = nav.getVerticalFov();
|
||||
nav.setRequestTransition(true, camera.position, target, fov);
|
||||
|
||||
const {
|
||||
x: x1,
|
||||
y: y1,
|
||||
z: z1,
|
||||
} = JSON.parse(searchParams.value.target_position); //!<<< 计算新焦点位置
|
||||
const newTarget = new THREE.Vector3(x1, y1, z1); //!<<< 焦點的新位置
|
||||
if (lastClickedDbId !== null && lastClickedDbId !== spriteDbId) {
|
||||
dataVizExtn.value.invalidateViewables([lastClickedDbId], (viewable) => {
|
||||
return {
|
||||
scale: 1.0, // 恢復為 scale 1
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
NOP_VIEWER.navigation.getCamera().setView({
|
||||
position: newPosition.clone(),
|
||||
target: newTarget.clone(),
|
||||
});
|
||||
setTimeout(() => {
|
||||
updateDbidPosition(NOP_VIEWER, subscribeData.value);
|
||||
}, 700);
|
||||
dataVizExtn.value.invalidateViewables([spriteDbId], (viewable) => {
|
||||
return {
|
||||
scale: 2.0, // 設置為 scale 2
|
||||
};
|
||||
});
|
||||
|
||||
lastClickedDbId = spriteDbId;
|
||||
} catch (error) {
|
||||
console.error("Error in cardfitToView:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const hideAllObjects = () => {
|
||||
@ -152,7 +215,7 @@ export default function useForgeSprite() {
|
||||
|
||||
const showSubSystemObjects = () => {
|
||||
hideAllObjects();
|
||||
subscribeData.value.forEach((value, index) => {
|
||||
flatSubData.value.forEach((value, index) => {
|
||||
forgeViewer.value.show(value.forge_dbid);
|
||||
});
|
||||
|
||||
@ -171,13 +234,13 @@ export default function useForgeSprite() {
|
||||
forgeViewer.value.tearDown();
|
||||
};
|
||||
|
||||
|
||||
|
||||
return {
|
||||
createSprites,
|
||||
setCameraPosition,
|
||||
updateDataVisualization,
|
||||
showSubSystemObjects,
|
||||
forgeClickListener,
|
||||
clear,
|
||||
cardfitToView,
|
||||
};
|
||||
}
|
||||
|
@ -1,381 +0,0 @@
|
||||
Authors ordered by first contribution
|
||||
A list of current team members is available at https://jqueryui.com/about
|
||||
|
||||
Paul Bakaus <paul.bakaus@gmail.com>
|
||||
Richard Worth <rdworth@gmail.com>
|
||||
Yehuda Katz <wycats@gmail.com>
|
||||
Sean Catchpole <sean@sunsean.com>
|
||||
John Resig <jeresig@gmail.com>
|
||||
Tane Piper <piper.tane@gmail.com>
|
||||
Dmitri Gaskin <dmitrig01@gmail.com>
|
||||
Klaus Hartl <klaus.hartl@gmail.com>
|
||||
Stefan Petre <stefan.petre@gmail.com>
|
||||
Gilles van den Hoven <gilles@webunity.nl>
|
||||
Micheil Bryan Smith <micheil@brandedcode.com>
|
||||
Jörn Zaefferer <joern.zaefferer@gmail.com>
|
||||
Marc Grabanski <m@marcgrabanski.com>
|
||||
Keith Wood <kbwood@iinet.com.au>
|
||||
Brandon Aaron <brandon.aaron@gmail.com>
|
||||
Scott González <scott.gonzalez@gmail.com>
|
||||
Eduardo Lundgren <eduardolundgren@gmail.com>
|
||||
Aaron Eisenberger <aaronchi@gmail.com>
|
||||
Joan Piedra <theneojp@gmail.com>
|
||||
Bruno Basto <b.basto@gmail.com>
|
||||
Remy Sharp <remy@leftlogic.com>
|
||||
Bohdan Ganicky <bohdan.ganicky@gmail.com>
|
||||
David Bolter <david.bolter@gmail.com>
|
||||
Chi Cheng <cloudream@gmail.com>
|
||||
Ca-Phun Ung <pazu2k@gmail.com>
|
||||
Ariel Flesler <aflesler@gmail.com>
|
||||
Maggie Wachs <maggie@filamentgroup.com>
|
||||
Scott Jehl <scottjehl@gmail.com>
|
||||
Todd Parker <todd@filamentgroup.com>
|
||||
Andrew Powell <andrew@shellscape.org>
|
||||
Brant Burnett <btburnett3@gmail.com>
|
||||
Douglas Neiner <doug@dougneiner.com>
|
||||
Paul Irish <paul.irish@gmail.com>
|
||||
Ralph Whitbeck <ralph.whitbeck@gmail.com>
|
||||
Thibault Duplessis <thibault.duplessis@gmail.com>
|
||||
Dominique Vincent <dominique.vincent@toitl.com>
|
||||
Jack Hsu <jack.hsu@gmail.com>
|
||||
Adam Sontag <ajpiano@ajpiano.com>
|
||||
Carl Fürstenberg <carl@excito.com>
|
||||
Kevin Dalman <development@allpro.net>
|
||||
Alberto Fernández Capel <afcapel@gmail.com>
|
||||
Jacek Jędrzejewski (https://jacek.jedrzejewski.name)
|
||||
Ting Kuei <ting@kuei.com>
|
||||
Samuel Cormier-Iijima <sam@chide.it>
|
||||
Jon Palmer <jonspalmer@gmail.com>
|
||||
Ben Hollis <bhollis@amazon.com>
|
||||
Justin MacCarthy <Justin@Rubystars.biz>
|
||||
Eyal Kobrigo <kobrigo@hotmail.com>
|
||||
Tiago Freire <tiago.freire@gmail.com>
|
||||
Diego Tres <diegotres@gmail.com>
|
||||
Holger Rüprich <holger@rueprich.de>
|
||||
Ziling Zhao <zilingzhao@gmail.com>
|
||||
Mike Alsup <malsup@gmail.com>
|
||||
Robson Braga Araujo <robsonbraga@gmail.com>
|
||||
Pierre-Henri Ausseil <ph.ausseil@gmail.com>
|
||||
Christopher McCulloh <cmcculloh@gmail.com>
|
||||
Andrew Newcomb <ext.github@preceptsoftware.co.uk>
|
||||
Lim Chee Aun <cheeaun@gmail.com>
|
||||
Jorge Barreiro <yortx.barry@gmail.com>
|
||||
Daniel Steigerwald <daniel@steigerwald.cz>
|
||||
John Firebaugh <john_firebaugh@bigfix.com>
|
||||
John Enters <github@darkdark.net>
|
||||
Andrey Kapitcyn <ru.m157y@gmail.com>
|
||||
Dmitry Petrov <dpetroff@gmail.com>
|
||||
Eric Hynds <eric@hynds.net>
|
||||
Chairat Sunthornwiphat <pipo@sixhead.com>
|
||||
Josh Varner <josh.varner@gmail.com>
|
||||
Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||
Jay Merrifield <fracmak@gmail.com>
|
||||
J. Ryan Stinnett <jryans@gmail.com>
|
||||
Peter Heiberg <peter@heiberg.se>
|
||||
Alex Dovenmuehle <adovenmuehle@gmail.com>
|
||||
Jamie Gegerson <git@jamiegegerson.com>
|
||||
Raymond Schwartz <skeetergraphics@gmail.com>
|
||||
Phillip Barnes <philbar@gmail.com>
|
||||
Kyle Wilkinson <kai@wikyd.org>
|
||||
Khaled AlHourani <me@khaledalhourani.com>
|
||||
Marian Rudzynski <mr@impaled.org>
|
||||
Jean-Francois Remy <jeff@melix.org>
|
||||
Doug Blood <dougblood@gmail.com>
|
||||
Filippo Cavallarin <filippo.cavallarin@codseq.it>
|
||||
Heiko Henning <heiko@thehennings.ch>
|
||||
Aliaksandr Rahalevich <saksmlz@gmail.com>
|
||||
Mario Visic <mario@mariovisic.com>
|
||||
Xavi Ramirez <xavi.rmz@gmail.com>
|
||||
Max Schnur <max.schnur@gmail.com>
|
||||
Saji Nediyanchath <saji89@gmail.com>
|
||||
Corey Frang <gnarf37@gmail.com>
|
||||
Aaron Peterson <aaronp123@yahoo.com>
|
||||
Ivan Peters <ivan@ivanpeters.com>
|
||||
Mohamed Cherif Bouchelaghem <cherifbouchelaghem@yahoo.fr>
|
||||
Marcos Sousa <falecomigo@marcossousa.com>
|
||||
Michael DellaNoce <mdellanoce@mailtrust.com>
|
||||
George Marshall <echosx@gmail.com>
|
||||
Tobias Brunner <tobias@strongswan.org>
|
||||
Martin Solli <msolli@gmail.com>
|
||||
David Petersen <public@petersendidit.com>
|
||||
Dan Heberden <danheberden@gmail.com>
|
||||
William Kevin Manire <williamkmanire@gmail.com>
|
||||
Gilmore Davidson <gilmoreorless@gmail.com>
|
||||
Michael Wu <michaelmwu@gmail.com>
|
||||
Adam Parod <mystic414@gmail.com>
|
||||
Guillaume Gautreau <guillaume+github@ghusse.com>
|
||||
Marcel Toele <EleotleCram@gmail.com>
|
||||
Dan Streetman <ddstreet@ieee.org>
|
||||
Matt Hoskins <matt@nipltd.com>
|
||||
Giovanni Giacobbi <giovanni@giacobbi.net>
|
||||
Kyle Florence <kyle.florence@gmail.com>
|
||||
Pavol Hluchý <lopo@losys.sk>
|
||||
Hans Hillen <hans.hillen@gmail.com>
|
||||
Mark Johnson <virgofx@live.com>
|
||||
Trey Hunner <treyhunner@gmail.com>
|
||||
Shane Whittet <whittet@gmail.com>
|
||||
Edward A Faulkner <ef@alum.mit.edu>
|
||||
Adam Baratz <adam@adambaratz.com>
|
||||
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
||||
Eike Send <eike.send@gmail.com>
|
||||
Kris Borchers <kris.borchers@gmail.com>
|
||||
Eddie Monge <eddie@eddiemonge.com>
|
||||
Israel Tsadok <itsadok@gmail.com>
|
||||
Carson McDonald <carson@ioncannon.net>
|
||||
Jason Davies <jason@jasondavies.com>
|
||||
Garrison Locke <gplocke@gmail.com>
|
||||
David Murdoch <david@davidmurdoch.com>
|
||||
Benjamin Scott Boyle <benjamins.boyle@gmail.com>
|
||||
Jesse Baird <jebaird@gmail.com>
|
||||
Jonathan Vingiano <jvingiano@gmail.com>
|
||||
Dylan Just <dev@ephox.com>
|
||||
Hiroshi Tomita <tomykaira@gmail.com>
|
||||
Glenn Goodrich <glenn.goodrich@gmail.com>
|
||||
Tarafder Ashek-E-Elahi <mail.ashek@gmail.com>
|
||||
Ryan Neufeld <ryan@neufeldmail.com>
|
||||
Marc Neuwirth <marc.neuwirth@gmail.com>
|
||||
Philip Graham <philip.robert.graham@gmail.com>
|
||||
Benjamin Sterling <benjamin.sterling@kenzomedia.com>
|
||||
Wesley Walser <waw325@gmail.com>
|
||||
Kouhei Sutou <kou@clear-code.com>
|
||||
Karl Kirch <karlkrch@gmail.com>
|
||||
Chris Kelly <ckdake@ckdake.com>
|
||||
Jason Oster <jay@kodewerx.org>
|
||||
Felix Nagel <info@felixnagel.com>
|
||||
Alexander Polomoshnov <alex.polomoshnov@gmail.com>
|
||||
David Leal <dgleal@gmail.com>
|
||||
Igor Milla <igor.fsp.milla@gmail.com>
|
||||
Dave Methvin <dave.methvin@gmail.com>
|
||||
Florian Gutmann <f.gutmann@chronimo.com>
|
||||
Marwan Al Jubeh <marwan.aljubeh@gmail.com>
|
||||
Milan Broum <midlis@googlemail.com>
|
||||
Sebastian Sauer <info@dynpages.de>
|
||||
Gaëtan Muller <m.gaetan89@gmail.com>
|
||||
Michel Weimerskirch <michel@weimerskirch.net>
|
||||
William Griffiths <william@ycymro.com>
|
||||
Stojce Slavkovski <stojce@gmail.com>
|
||||
David Soms <david.soms@gmail.com>
|
||||
David De Sloovere <david.desloovere@outlook.com>
|
||||
Michael P. Jung <michael.jung@terreon.de>
|
||||
Shannon Pekary <spekary@gmail.com>
|
||||
Dan Wellman <danwellman@hotmail.com>
|
||||
Matthew Edward Hutton <meh@corefiling.co.uk>
|
||||
James Khoury <james@jameskhoury.com>
|
||||
Rob Loach <robloach@gmail.com>
|
||||
Alberto Monteiro <betimbrasil@gmail.com>
|
||||
Alex Rhea <alex.rhea@gmail.com>
|
||||
Krzysztof Rosiński <rozwell69@gmail.com>
|
||||
Ryan Olton <oltonr@gmail.com>
|
||||
Genie <386@mail.com>
|
||||
Rick Waldron <waldron.rick@gmail.com>
|
||||
Ian Simpson <spoonlikesham@gmail.com>
|
||||
Lev Kitsis <spam4lev@gmail.com>
|
||||
TJ VanToll <tj.vantoll@gmail.com>
|
||||
Justin Domnitz <jdomnitz@gmail.com>
|
||||
Douglas Cerna <douglascerna@yahoo.com>
|
||||
Bert ter Heide <bertjh@hotmail.com>
|
||||
Jasvir Nagra <jasvir@gmail.com>
|
||||
Yuriy Khabarov <13real008@gmail.com>
|
||||
Harri Kilpiö <harri.kilpio@gmail.com>
|
||||
Lado Lomidze <lado.lomidze@gmail.com>
|
||||
Amir E. Aharoni <amir.aharoni@mail.huji.ac.il>
|
||||
Simon Sattes <simon.sattes@gmail.com>
|
||||
Jo Liss <joliss42@gmail.com>
|
||||
Guntupalli Karunakar <karunakarg@yahoo.com>
|
||||
Shahyar Ghobadpour <shahyar@gmail.com>
|
||||
Lukasz Lipinski <uzza17@gmail.com>
|
||||
Timo Tijhof <krinklemail@gmail.com>
|
||||
Jason Moon <jmoon@socialcast.com>
|
||||
Martin Frost <martinf55@hotmail.com>
|
||||
Eneko Illarramendi <eneko@illarra.com>
|
||||
EungJun Yi <semtlenori@gmail.com>
|
||||
Courtland Allen <courtlandallen@gmail.com>
|
||||
Viktar Varvanovich <non4eg@gmail.com>
|
||||
Danny Trunk <dtrunk90@gmail.com>
|
||||
Pavel Stetina <pavel.stetina@nangu.tv>
|
||||
Michael Stay <metaweta@gmail.com>
|
||||
Steven Roussey <sroussey@gmail.com>
|
||||
Michael Hollis <hollis21@gmail.com>
|
||||
Lee Rowlands <lee.rowlands@previousnext.com.au>
|
||||
Timmy Willison <timmywillisn@gmail.com>
|
||||
Karl Swedberg <kswedberg@gmail.com>
|
||||
Baoju Yuan <the_guy_1987@hotmail.com>
|
||||
Maciej Mroziński <maciej.k.mrozinski@gmail.com>
|
||||
Luis Dalmolin <luis.nh@gmail.com>
|
||||
Mark Aaron Shirley <maspwr@gmail.com>
|
||||
Martin Hoch <martin@fidion.de>
|
||||
Jiayi Yang <tr870829@gmail.com>
|
||||
Philipp Benjamin Köppchen <xgxtpbk@gws.ms>
|
||||
Sindre Sorhus <sindresorhus@gmail.com>
|
||||
Bernhard Sirlinger <bernhard.sirlinger@tele2.de>
|
||||
Jared A. Scheel <jared@jaredscheel.com>
|
||||
Rafael Xavier de Souza <rxaviers@gmail.com>
|
||||
John Chen <zhang.z.chen@intel.com>
|
||||
Robert Beuligmann <robertbeuligmann@gmail.com>
|
||||
Dale Kocian <dale.kocian@gmail.com>
|
||||
Mike Sherov <mike.sherov@gmail.com>
|
||||
Andrew Couch <andy@couchand.com>
|
||||
Marc-Andre Lafortune <github@marc-andre.ca>
|
||||
Nate Eagle <nate.eagle@teamaol.com>
|
||||
David Souther <davidsouther@gmail.com>
|
||||
Mathias Stenbom <mathias@stenbom.com>
|
||||
Sergey Kartashov <ebishkek@yandex.ru>
|
||||
Avinash R <nashpapa@gmail.com>
|
||||
Ethan Romba <ethanromba@gmail.com>
|
||||
Cory Gackenheimer <cory.gack@gmail.com>
|
||||
Juan Pablo Kaniefsky <jpkaniefsky@gmail.com>
|
||||
Roman Salnikov <bardt.dz@gmail.com>
|
||||
Anika Henke <anika@selfthinker.org>
|
||||
Samuel Bovée <samycookie2000@yahoo.fr>
|
||||
Fabrício Matté <ult_combo@hotmail.com>
|
||||
Viktor Kojouharov <vkojouharov@gmail.com>
|
||||
Pawel Maruszczyk (http://hrabstwo.net)
|
||||
Pavel Selitskas <p.selitskas@gmail.com>
|
||||
Bjørn Johansen <post@bjornjohansen.no>
|
||||
Matthieu Penant <thieum22@hotmail.com>
|
||||
Dominic Barnes <dominic@dbarnes.info>
|
||||
David Sullivan <david.sullivan@gmail.com>
|
||||
Thomas Jaggi <thomas@responsive.ch>
|
||||
Vahid Sohrabloo <vahid4134@gmail.com>
|
||||
Travis Carden <travis.carden@gmail.com>
|
||||
Bruno M. Custódio <bruno@brunomcustodio.com>
|
||||
Nathanael Silverman <nathanael.silverman@gmail.com>
|
||||
Christian Wenz <christian@wenz.org>
|
||||
Steve Urmston <steve@urm.st>
|
||||
Zaven Muradyan <megalivoithos@gmail.com>
|
||||
Woody Gilk <shadowhand@deviantart.com>
|
||||
Zbigniew Motyka <zbigniew.motyka@gmail.com>
|
||||
Suhail Alkowaileet <xsoh.k7@gmail.com>
|
||||
Toshi MARUYAMA <marutosijp2@yahoo.co.jp>
|
||||
David Hansen <hansede@gmail.com>
|
||||
Brian Grinstead <briangrinstead@gmail.com>
|
||||
Christian Klammer <christian314159@gmail.com>
|
||||
Steven Luscher <jquerycla@steveluscher.com>
|
||||
Gan Eng Chin <engchin.gan@gmail.com>
|
||||
Gabriel Schulhof <gabriel.schulhof@intel.com>
|
||||
Alexander Schmitz <arschmitz@gmail.com>
|
||||
Vilhjálmur Skúlason <vis@dmm.is>
|
||||
Siebrand Mazeland <siebrand@kitano.nl>
|
||||
Mohsen Ekhtiari <mohsenekhtiari@yahoo.com>
|
||||
Pere Orga <gotrunks@gmail.com>
|
||||
Jasper de Groot <mail@ugomobi.com>
|
||||
Stephane Deschamps <stephane.deschamps@gmail.com>
|
||||
Jyoti Deka <dekajp@gmail.com>
|
||||
Andrei Picus <office.nightcrawler@gmail.com>
|
||||
Ondrej Novy <novy@ondrej.org>
|
||||
Jacob McCutcheon <jacob.mccutcheon@gmail.com>
|
||||
Monika Piotrowicz <monika.piotrowicz@gmail.com>
|
||||
Imants Horsts <imants.horsts@inbox.lv>
|
||||
Eric Dahl <eric.c.dahl@gmail.com>
|
||||
Dave Stein <dave@behance.com>
|
||||
Dylan Barrell <dylan@barrell.com>
|
||||
Daniel DeGroff <djdegroff@gmail.com>
|
||||
Michael Wiencek <mwtuea@gmail.com>
|
||||
Thomas Meyer <meyertee@gmail.com>
|
||||
Ruslan Yakhyaev <ruslan@ruslan.io>
|
||||
Brian J. Dowling <bjd-dev@simplicity.net>
|
||||
Ben Higgins <ben@extrahop.com>
|
||||
Yermo Lamers <yml@yml.com>
|
||||
Patrick Stapleton <github@gdi2290.com>
|
||||
Trisha Crowley <trisha.crowley@gmail.com>
|
||||
Usman Akeju <akeju00+github@gmail.com>
|
||||
Rodrigo Menezes <rod333@gmail.com>
|
||||
Jacques Perrault <jacques_perrault@us.ibm.com>
|
||||
Frederik Elvhage <frederik.elvhage@googlemail.com>
|
||||
Will Holley <willholley@gmail.com>
|
||||
Uri Gilad <antishok@gmail.com>
|
||||
Richard Gibson <richard.gibson@gmail.com>
|
||||
Simen Bekkhus <sbekkhus91@gmail.com>
|
||||
Chen Eshchar <eshcharc@gmail.com>
|
||||
Bruno Pérel <brunoperel@gmail.com>
|
||||
Mohammed Alshehri <m@dralshehri.com>
|
||||
Lisa Seacat DeLuca <ldeluca@us.ibm.com>
|
||||
Anne-Gaelle Colom <coloma@westminster.ac.uk>
|
||||
Adam Foster <slimfoster@gmail.com>
|
||||
Luke Page <luke.a.page@gmail.com>
|
||||
Daniel Owens <daniel@matchstickmixup.com>
|
||||
Michael Orchard <morchard@scottlogic.co.uk>
|
||||
Marcus Warren <marcus@envoke.com>
|
||||
Nils Heuermann <nils@world-of-scripts.de>
|
||||
Marco Ziech <marco@ziech.net>
|
||||
Patricia Juarez <patrixd@gmail.com>
|
||||
Ben Mosher <me@benmosher.com>
|
||||
Ablay Keldibek <atomio.ak@gmail.com>
|
||||
Thomas Applencourt <thomas.applencourt@irsamc.ups-tlse.fr>
|
||||
Jiabao Wu <jiabao.foss@gmail.com>
|
||||
Eric Lee Carraway <github@ericcarraway.com>
|
||||
Victor Homyakov <vkhomyackov@gmail.com>
|
||||
Myeongjin Lee <aranet100@gmail.com>
|
||||
Liran Sharir <lsharir@gmail.com>
|
||||
Weston Ruter <weston@xwp.co>
|
||||
Mani Mishra <manimishra902@gmail.com>
|
||||
Hannah Methvin <hannahmethvin@gmail.com>
|
||||
Leonardo Balter <leonardo.balter@gmail.com>
|
||||
Benjamin Albert <benjamin_a5@yahoo.com>
|
||||
Michał Gołębiowski-Owczarek <m.goleb@gmail.com>
|
||||
Alyosha Pushak <alyosha.pushak@gmail.com>
|
||||
Fahad Ahmad <fahadahmad41@hotmail.com>
|
||||
Matt Brundage <github@mattbrundage.com>
|
||||
Francesc Baeta <francesc.baeta@gmail.com>
|
||||
Piotr Baran <piotros@wp.pl>
|
||||
Mukul Hase <mukulhase@gmail.com>
|
||||
Konstantin Dinev <kdinev@mail.bw.edu>
|
||||
Rand Scullard <rand@randscullard.com>
|
||||
Dan Strohl <dan@wjcg.net>
|
||||
Maksim Ryzhikov <rv.maksim@gmail.com>
|
||||
Amine HADDAD <haddad@allegorie.tv>
|
||||
Amanpreet Singh <apsdehal@gmail.com>
|
||||
Alexey Balchunas <bleshik@gmail.com>
|
||||
Peter Kehl <peter.kehl@gmail.com>
|
||||
Peter Dave Hello <hsu@peterdavehello.org>
|
||||
Johannes Schäfer <johnschaefer@gmx.de>
|
||||
Ville Skyttä <ville.skytta@iki.fi>
|
||||
Ryan Oriecuia <ryan.oriecuia@visioncritical.com>
|
||||
Sergei Ratnikov <sergeir82@gmail.com>
|
||||
milk54 <milk851@gmail.com>
|
||||
Evelyn Masso <evoutofambit@gmail.com>
|
||||
Robin <mail@robin-fowler.com>
|
||||
Simon Asika <asika32764@gmail.com>
|
||||
Kevin Cupp <kevin.cupp@gmail.com>
|
||||
Jeremy Mickelson <Jeremy.Mickelson@gmail.com>
|
||||
Kyle Rosenberg <kyle.rosenberg@gmail.com>
|
||||
Petri Partio <petri.partio@gmail.com>
|
||||
pallxk <github@pallxk.com>
|
||||
Luke Brookhart <luke@onjax.com>
|
||||
claudi <hirt-claudia@gmx.de>
|
||||
Eirik Sletteberg <eiriksletteberg@gmail.com>
|
||||
Albert Johansson <albert@intervaro.se>
|
||||
A. Wells <borgboyone@users.noreply.github.com>
|
||||
Robert Brignull <robertbrignull@gmail.com>
|
||||
Horus68 <pauloizidoro@gmail.com>
|
||||
Maksymenkov Eugene <foatei@gmail.com>
|
||||
OskarNS <soerensen.oskar@gmail.com>
|
||||
Gez Quinn <holla@gezquinn.design>
|
||||
jigar gala <jigar.gala140291@gmail.com>
|
||||
Florian Wegscheider <flo.wegscheider@gmail.com>
|
||||
Fatér Zsolt <fater.zsolt@gmail.com>
|
||||
Szabolcs Szabolcsi-Toth <nec@shell8.net>
|
||||
Jérémy Munsch <github@jeremydev.ovh>
|
||||
Hrvoje Novosel <hrvoje.novosel@gmail.com>
|
||||
Paul Capron <PaulCapron@users.noreply.github.com>
|
||||
Micah Miller <mikhey@runbox.com>
|
||||
sakshi87 <53863764+sakshi87@users.noreply.github.com>
|
||||
Mikolaj Wolicki <wolicki.mikolaj@gmail.com>
|
||||
Patrick McKay <patrick.mckay@vumc.org>
|
||||
c-lambert <58025159+c-lambert@users.noreply.github.com>
|
||||
Josep Sanz <josepsanzcamp@gmail.com>
|
||||
Ben Mullins <benm@umich.edu>
|
||||
Christian Oliff <christianoliff@pm.me>
|
||||
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
|
||||
Adam Lidén Hällgren <adamlh92@gmail.com>
|
||||
James Hinderks <hinderks@gmail.com>
|
||||
Denny Septian Panggabean <97607754+ddevsr@users.noreply.github.com>
|
||||
Matías Cánepa <matias.canepa@gmail.com>
|
||||
Ashish Kurmi <100655670+boahc077@users.noreply.github.com>
|
||||
DeerBear <andrea.raimondi@gmail.com>
|
||||
Дилян Палаузов <dpa-github@aegee.org>
|
||||
Kenneth DeBacker <kcdebacker@gmail.com>
|
||||
Timo Tijhof <krinkle@fastmail.com>
|
||||
Timmy Willison <timmywil@users.noreply.github.com>
|
||||
divdeploy <166095818+divdeploy@users.noreply.github.com>
|
||||
mark van tilburg <markvantilburg@gmail.com>
|
@ -1,43 +0,0 @@
|
||||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals. For exact contribution history, see the revision history
|
||||
available at https://github.com/jquery/jquery-ui
|
||||
|
||||
The following license applies to all parts of this software except as
|
||||
documented below:
|
||||
|
||||
====
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
Copyright and related rights for sample code are waived via CC0. Sample
|
||||
code is defined as all source code contained within the demos directory.
|
||||
|
||||
CC0: http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
====
|
||||
|
||||
All files located in the node_modules and external directories are
|
||||
externally maintained libraries used by this software which have their
|
||||
own licenses; we recommend you read them, as their terms may differ from
|
||||
the terms above.
|
10716
src/lib/jquery-ui/external/jquery/jquery.js
vendored
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 6.4 KiB |
@ -1,503 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery UI Example Page</title>
|
||||
<link href="jquery-ui.css" rel="stylesheet">
|
||||
<style>
|
||||
body{
|
||||
font-family: "Trebuchet MS", sans-serif;
|
||||
margin: 50px;
|
||||
}
|
||||
.demoHeaders {
|
||||
margin-top: 2em;
|
||||
}
|
||||
#dialog-link {
|
||||
padding: .4em 1em .4em 20px;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
}
|
||||
#dialog-link span.ui-icon {
|
||||
margin: 0 5px 0 0;
|
||||
position: absolute;
|
||||
left: .2em;
|
||||
top: 50%;
|
||||
margin-top: -8px;
|
||||
}
|
||||
#icons {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#icons li {
|
||||
margin: 2px;
|
||||
position: relative;
|
||||
padding: 4px 0;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
list-style: none;
|
||||
}
|
||||
#icons span.ui-icon {
|
||||
float: left;
|
||||
margin: 0 4px;
|
||||
}
|
||||
.fakewindowcontain .ui-widget-overlay {
|
||||
position: absolute;
|
||||
}
|
||||
select {
|
||||
width: 200px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Welcome to jQuery UI!</h1>
|
||||
|
||||
<div class="ui-widget">
|
||||
<p>This page demonstrates the widgets and theme you selected in Download Builder. Please make sure you are using them with a compatible jQuery version.</p>
|
||||
</div>
|
||||
|
||||
<h1>YOUR COMPONENTS:</h1>
|
||||
|
||||
<!-- Accordion -->
|
||||
<h2 class="demoHeaders">Accordion</h2>
|
||||
<div id="accordion">
|
||||
<h3>First</h3>
|
||||
<div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>
|
||||
<h3>Second</h3>
|
||||
<div>Phasellus mattis tincidunt nibh.</div>
|
||||
<h3>Third</h3>
|
||||
<div>Nam dui erat, auctor a, dignissim quis.</div>
|
||||
</div>
|
||||
|
||||
<!-- Autocomplete -->
|
||||
<h2 class="demoHeaders">Autocomplete</h2>
|
||||
<div>
|
||||
<input id="autocomplete" title="type "a"">
|
||||
</div>
|
||||
|
||||
<!-- Button -->
|
||||
<h2 class="demoHeaders">Button</h2>
|
||||
<button id="button">A button element</button>
|
||||
<button id="button-icon">An icon-only button</button>
|
||||
|
||||
<!-- Checkboxradio -->
|
||||
<h2 class="demoHeaders">Checkboxradio</h2>
|
||||
<form style="margin-top: 1em;">
|
||||
<div id="radioset">
|
||||
<input type="radio" id="radio1" name="radio"><label for="radio1">Choice 1</label>
|
||||
<input type="radio" id="radio2" name="radio" checked="checked"><label for="radio2">Choice 2</label>
|
||||
<input type="radio" id="radio3" name="radio"><label for="radio3">Choice 3</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Controlgroup -->
|
||||
<h2 class="demoHeaders">Controlgroup</h2>
|
||||
<fieldset>
|
||||
<legend>Rental Car</legend>
|
||||
<div id="controlgroup">
|
||||
<select id="car-type">
|
||||
<option>Compact car</option>
|
||||
<option>Midsize car</option>
|
||||
<option>Full size car</option>
|
||||
<option>SUV</option>
|
||||
<option>Luxury</option>
|
||||
<option>Truck</option>
|
||||
<option>Van</option>
|
||||
</select>
|
||||
<label for="transmission-standard">Standard</label>
|
||||
<input type="radio" name="transmission" id="transmission-standard">
|
||||
<label for="transmission-automatic">Automatic</label>
|
||||
<input type="radio" name="transmission" id="transmission-automatic">
|
||||
<label for="insurance">Insurance</label>
|
||||
<input type="checkbox" name="insurance" id="insurance">
|
||||
<label for="horizontal-spinner" class="ui-controlgroup-label"># of cars</label>
|
||||
<input id="horizontal-spinner" class="ui-spinner-input">
|
||||
<button>Book Now!</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- Tabs -->
|
||||
<h2 class="demoHeaders">Tabs</h2>
|
||||
<div id="tabs">
|
||||
<ul>
|
||||
<li><a href="#tabs-1">First</a></li>
|
||||
<li><a href="#tabs-2">Second</a></li>
|
||||
<li><a href="#tabs-3">Third</a></li>
|
||||
</ul>
|
||||
<div id="tabs-1">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
|
||||
<div id="tabs-2">Phasellus mattis tincidunt nibh. Cras orci urna, blandit id, pretium vel, aliquet ornare, felis. Maecenas scelerisque sem non nisl. Fusce sed lorem in enim dictum bibendum.</div>
|
||||
<div id="tabs-3">Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.</div>
|
||||
</div>
|
||||
|
||||
<h2 class="demoHeaders">Dialog</h2>
|
||||
<p>
|
||||
<button id="dialog-link" class="ui-button ui-corner-all ui-widget">
|
||||
<span class="ui-icon ui-icon-newwin"></span>Open Dialog
|
||||
</button>
|
||||
</p>
|
||||
|
||||
<h2 class="demoHeaders">Overlay and Shadow Classes</h2>
|
||||
<div style="position: relative; width: 96%; height: 200px; padding:1% 2%; overflow:hidden;" class="fakewindowcontain">
|
||||
<p>Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. </p><p>Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. </p><p>Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. </p><p>Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. </p>
|
||||
|
||||
<!-- ui-dialog -->
|
||||
<div class="ui-widget-overlay ui-front"></div>
|
||||
<div style="position: absolute; width: 320px; left: 50px; top: 30px; padding: 1.2em" class="ui-widget ui-front ui-widget-content ui-corner-all ui-widget-shadow">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ui-dialog -->
|
||||
<div id="dialog" title="Dialog Title">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<h2 class="demoHeaders">Framework Icons (content color preview)</h2>
|
||||
<ul id="icons" class="ui-widget ui-helper-clearfix">
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-n"><span class="ui-icon ui-icon-caret-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-ne"><span class="ui-icon ui-icon-caret-1-ne"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-e"><span class="ui-icon ui-icon-caret-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-se"><span class="ui-icon ui-icon-caret-1-se"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-s"><span class="ui-icon ui-icon-caret-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-sw"><span class="ui-icon ui-icon-caret-1-sw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-w"><span class="ui-icon ui-icon-caret-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-nw"><span class="ui-icon ui-icon-caret-1-nw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-2-n-s"><span class="ui-icon ui-icon-caret-2-n-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-2-e-w"><span class="ui-icon ui-icon-caret-2-e-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-n"><span class="ui-icon ui-icon-triangle-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-ne"><span class="ui-icon ui-icon-triangle-1-ne"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-e"><span class="ui-icon ui-icon-triangle-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-se"><span class="ui-icon ui-icon-triangle-1-se"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-s"><span class="ui-icon ui-icon-triangle-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-sw"><span class="ui-icon ui-icon-triangle-1-sw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-w"><span class="ui-icon ui-icon-triangle-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-nw"><span class="ui-icon ui-icon-triangle-1-nw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-2-n-s"><span class="ui-icon ui-icon-triangle-2-n-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-2-e-w"><span class="ui-icon ui-icon-triangle-2-e-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-n"><span class="ui-icon ui-icon-arrow-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-ne"><span class="ui-icon ui-icon-arrow-1-ne"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-e"><span class="ui-icon ui-icon-arrow-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-se"><span class="ui-icon ui-icon-arrow-1-se"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-s"><span class="ui-icon ui-icon-arrow-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-sw"><span class="ui-icon ui-icon-arrow-1-sw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-w"><span class="ui-icon ui-icon-arrow-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-nw"><span class="ui-icon ui-icon-arrow-1-nw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-n-s"><span class="ui-icon ui-icon-arrow-2-n-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-ne-sw"><span class="ui-icon ui-icon-arrow-2-ne-sw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-e-w"><span class="ui-icon ui-icon-arrow-2-e-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-se-nw"><span class="ui-icon ui-icon-arrow-2-se-nw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-n"><span class="ui-icon ui-icon-arrowstop-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-e"><span class="ui-icon ui-icon-arrowstop-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-s"><span class="ui-icon ui-icon-arrowstop-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-w"><span class="ui-icon ui-icon-arrowstop-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-n"><span class="ui-icon ui-icon-arrowthick-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-ne"><span class="ui-icon ui-icon-arrowthick-1-ne"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-e"><span class="ui-icon ui-icon-arrowthick-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-se"><span class="ui-icon ui-icon-arrowthick-1-se"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-s"><span class="ui-icon ui-icon-arrowthick-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-sw"><span class="ui-icon ui-icon-arrowthick-1-sw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-w"><span class="ui-icon ui-icon-arrowthick-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-nw"><span class="ui-icon ui-icon-arrowthick-1-nw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-n-s"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-ne-sw"><span class="ui-icon ui-icon-arrowthick-2-ne-sw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-e-w"><span class="ui-icon ui-icon-arrowthick-2-e-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-se-nw"><span class="ui-icon ui-icon-arrowthick-2-se-nw"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-n"><span class="ui-icon ui-icon-arrowthickstop-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-e"><span class="ui-icon ui-icon-arrowthickstop-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-s"><span class="ui-icon ui-icon-arrowthickstop-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-w"><span class="ui-icon ui-icon-arrowthickstop-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-w"><span class="ui-icon ui-icon-arrowreturnthick-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-n"><span class="ui-icon ui-icon-arrowreturnthick-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-e"><span class="ui-icon ui-icon-arrowreturnthick-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-s"><span class="ui-icon ui-icon-arrowreturnthick-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-w"><span class="ui-icon ui-icon-arrowreturn-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-n"><span class="ui-icon ui-icon-arrowreturn-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-e"><span class="ui-icon ui-icon-arrowreturn-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-s"><span class="ui-icon ui-icon-arrowreturn-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-w"><span class="ui-icon ui-icon-arrowrefresh-1-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-n"><span class="ui-icon ui-icon-arrowrefresh-1-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-e"><span class="ui-icon ui-icon-arrowrefresh-1-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-s"><span class="ui-icon ui-icon-arrowrefresh-1-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-4"><span class="ui-icon ui-icon-arrow-4"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-4-diag"><span class="ui-icon ui-icon-arrow-4-diag"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-extlink"><span class="ui-icon ui-icon-extlink"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-newwin"><span class="ui-icon ui-icon-newwin"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-refresh"><span class="ui-icon ui-icon-refresh"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-shuffle"><span class="ui-icon ui-icon-shuffle"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-transfer-e-w"><span class="ui-icon ui-icon-transfer-e-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-transferthick-e-w"><span class="ui-icon ui-icon-transferthick-e-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-folder-collapsed"><span class="ui-icon ui-icon-folder-collapsed"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-folder-open"><span class="ui-icon ui-icon-folder-open"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-document"><span class="ui-icon ui-icon-document"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-document-b"><span class="ui-icon ui-icon-document-b"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-note"><span class="ui-icon ui-icon-note"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-mail-open"><span class="ui-icon ui-icon-mail-open"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-suitcase"><span class="ui-icon ui-icon-suitcase"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-comment"><span class="ui-icon ui-icon-comment"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-person"><span class="ui-icon ui-icon-person"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-print"><span class="ui-icon ui-icon-print"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-trash"><span class="ui-icon ui-icon-trash"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-locked"><span class="ui-icon ui-icon-locked"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-unlocked"><span class="ui-icon ui-icon-unlocked"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-bookmark"><span class="ui-icon ui-icon-bookmark"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-tag"><span class="ui-icon ui-icon-tag"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-home"><span class="ui-icon ui-icon-home"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-flag"><span class="ui-icon ui-icon-flag"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-calculator"><span class="ui-icon ui-icon-calculator"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-cart"><span class="ui-icon ui-icon-cart"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-pencil"><span class="ui-icon ui-icon-pencil"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-clock"><span class="ui-icon ui-icon-clock"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-disk"><span class="ui-icon ui-icon-disk"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-calendar"><span class="ui-icon ui-icon-calendar"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-zoomin"><span class="ui-icon ui-icon-zoomin"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-zoomout"><span class="ui-icon ui-icon-zoomout"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-search"><span class="ui-icon ui-icon-search"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-wrench"><span class="ui-icon ui-icon-wrench"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-gear"><span class="ui-icon ui-icon-gear"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-heart"><span class="ui-icon ui-icon-heart"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-star"><span class="ui-icon ui-icon-star"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-link"><span class="ui-icon ui-icon-link"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-cancel"><span class="ui-icon ui-icon-cancel"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-plus"><span class="ui-icon ui-icon-plus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-minus"><span class="ui-icon ui-icon-minus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-minusthick"><span class="ui-icon ui-icon-minusthick"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-close"><span class="ui-icon ui-icon-close"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-closethick"><span class="ui-icon ui-icon-closethick"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-key"><span class="ui-icon ui-icon-key"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-lightbulb"><span class="ui-icon ui-icon-lightbulb"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-scissors"><span class="ui-icon ui-icon-scissors"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-clipboard"><span class="ui-icon ui-icon-clipboard"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-copy"><span class="ui-icon ui-icon-copy"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-contact"><span class="ui-icon ui-icon-contact"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-image"><span class="ui-icon ui-icon-image"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-video"><span class="ui-icon ui-icon-video"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-script"><span class="ui-icon ui-icon-script"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-alert"><span class="ui-icon ui-icon-alert"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-info"><span class="ui-icon ui-icon-info"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-notice"><span class="ui-icon ui-icon-notice"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-help"><span class="ui-icon ui-icon-help"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-bullet"><span class="ui-icon ui-icon-bullet"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-radio-off"><span class="ui-icon ui-icon-radio-off"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-radio-on"><span class="ui-icon ui-icon-radio-on"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-pin-w"><span class="ui-icon ui-icon-pin-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-pin-s"><span class="ui-icon ui-icon-pin-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-play"><span class="ui-icon ui-icon-play"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-pause"><span class="ui-icon ui-icon-pause"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-next"><span class="ui-icon ui-icon-seek-next"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-prev"><span class="ui-icon ui-icon-seek-prev"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-end"><span class="ui-icon ui-icon-seek-end"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-first"><span class="ui-icon ui-icon-seek-first"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-stop"><span class="ui-icon ui-icon-stop"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-eject"><span class="ui-icon ui-icon-eject"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-volume-off"><span class="ui-icon ui-icon-volume-off"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-volume-on"><span class="ui-icon ui-icon-volume-on"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-power"><span class="ui-icon ui-icon-power"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-signal-diag"><span class="ui-icon ui-icon-signal-diag"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-signal"><span class="ui-icon ui-icon-signal"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-0"><span class="ui-icon ui-icon-battery-0"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-1"><span class="ui-icon ui-icon-battery-1"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-2"><span class="ui-icon ui-icon-battery-2"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-3"><span class="ui-icon ui-icon-battery-3"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-plus"><span class="ui-icon ui-icon-circle-plus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-minus"><span class="ui-icon ui-icon-circle-minus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-close"><span class="ui-icon ui-icon-circle-close"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-e"><span class="ui-icon ui-icon-circle-triangle-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-s"><span class="ui-icon ui-icon-circle-triangle-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-w"><span class="ui-icon ui-icon-circle-triangle-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-n"><span class="ui-icon ui-icon-circle-triangle-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-e"><span class="ui-icon ui-icon-circle-arrow-e"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-s"><span class="ui-icon ui-icon-circle-arrow-s"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-w"><span class="ui-icon ui-icon-circle-arrow-w"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-n"><span class="ui-icon ui-icon-circle-arrow-n"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-zoomin"><span class="ui-icon ui-icon-circle-zoomin"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-zoomout"><span class="ui-icon ui-icon-circle-zoomout"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-check"><span class="ui-icon ui-icon-circle-check"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-plus"><span class="ui-icon ui-icon-circlesmall-plus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-minus"><span class="ui-icon ui-icon-circlesmall-minus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-close"><span class="ui-icon ui-icon-circlesmall-close"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-plus"><span class="ui-icon ui-icon-squaresmall-plus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-minus"><span class="ui-icon ui-icon-squaresmall-minus"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-close"><span class="ui-icon ui-icon-squaresmall-close"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-dotted-vertical"><span class="ui-icon ui-icon-grip-dotted-vertical"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-dotted-horizontal"><span class="ui-icon ui-icon-grip-dotted-horizontal"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-solid-vertical"><span class="ui-icon ui-icon-grip-solid-vertical"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-solid-horizontal"><span class="ui-icon ui-icon-grip-solid-horizontal"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-gripsmall-diagonal-se"><span class="ui-icon ui-icon-gripsmall-diagonal-se"></span></li>
|
||||
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-diagonal-se"><span class="ui-icon ui-icon-grip-diagonal-se"></span></li>
|
||||
</ul>
|
||||
|
||||
<!-- Slider -->
|
||||
<h2 class="demoHeaders">Slider</h2>
|
||||
<div id="slider"></div>
|
||||
|
||||
<!-- Datepicker -->
|
||||
<h2 class="demoHeaders">Datepicker</h2>
|
||||
<div id="datepicker"></div>
|
||||
|
||||
<!-- Progressbar -->
|
||||
<h2 class="demoHeaders">Progressbar</h2>
|
||||
<div id="progressbar"></div>
|
||||
|
||||
<!-- Progressbar -->
|
||||
<h2 class="demoHeaders">Selectmenu</h2>
|
||||
<select id="selectmenu">
|
||||
<option>Slower</option>
|
||||
<option>Slow</option>
|
||||
<option selected="selected">Medium</option>
|
||||
<option>Fast</option>
|
||||
<option>Faster</option>
|
||||
</select>
|
||||
|
||||
<!-- Spinner -->
|
||||
<h2 class="demoHeaders">Spinner</h2>
|
||||
<input id="spinner">
|
||||
|
||||
<!-- Menu -->
|
||||
<h2 class="demoHeaders">Menu</h2>
|
||||
<ul style="width:100px;" id="menu">
|
||||
<li><div>Item 1</div></li>
|
||||
<li><div>Item 2</div></li>
|
||||
<li><div>Item 3</div>
|
||||
<ul>
|
||||
<li><div>Item 3-1</div></li>
|
||||
<li><div>Item 3-2</div></li>
|
||||
<li><div>Item 3-3</div></li>
|
||||
<li><div>Item 3-4</div></li>
|
||||
<li><div>Item 3-5</div></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><div>Item 4</div></li>
|
||||
<li><div>Item 5</div></li>
|
||||
</ul>
|
||||
|
||||
<!-- Tooltip -->
|
||||
<h2 class="demoHeaders">Tooltip</h2>
|
||||
<p id="tooltip">
|
||||
<a href="#" title="That's what this widget is">Tooltips</a> can be attached to any element. When you hover
|
||||
the element with your mouse, the title attribute is displayed in a little box next to the element, just like a native tooltip.
|
||||
</p>
|
||||
|
||||
<!-- Highlight / Error -->
|
||||
<h2 class="demoHeaders">Highlight / Error</h2>
|
||||
<div class="ui-widget">
|
||||
<div class="ui-state-highlight ui-corner-all" style="margin-top: 20px; padding: 0 .7em;">
|
||||
<p><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>
|
||||
<strong>Hey!</strong> Sample ui-state-highlight style.</p>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="ui-widget">
|
||||
<div class="ui-state-error ui-corner-all" style="padding: 0 .7em;">
|
||||
<p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>
|
||||
<strong>Alert:</strong> Sample ui-state-error style.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="external/jquery/jquery.js"></script>
|
||||
<script src="jquery-ui.js"></script>
|
||||
<script>
|
||||
$( "#accordion" ).accordion();
|
||||
|
||||
var availableTags = [
|
||||
"ActionScript",
|
||||
"AppleScript",
|
||||
"Asp",
|
||||
"BASIC",
|
||||
"C",
|
||||
"C++",
|
||||
"Clojure",
|
||||
"COBOL",
|
||||
"ColdFusion",
|
||||
"Erlang",
|
||||
"Fortran",
|
||||
"Groovy",
|
||||
"Haskell",
|
||||
"Java",
|
||||
"JavaScript",
|
||||
"Lisp",
|
||||
"Perl",
|
||||
"PHP",
|
||||
"Python",
|
||||
"Ruby",
|
||||
"Scala",
|
||||
"Scheme"
|
||||
];
|
||||
$( "#autocomplete" ).autocomplete({
|
||||
source: availableTags
|
||||
});
|
||||
|
||||
$( "#button" ).button();
|
||||
$( "#button-icon" ).button({
|
||||
icon: "ui-icon-gear",
|
||||
showLabel: false
|
||||
});
|
||||
|
||||
$( "#radioset" ).buttonset();
|
||||
|
||||
$( "#controlgroup" ).controlgroup();
|
||||
|
||||
$( "#tabs" ).tabs();
|
||||
|
||||
$( "#dialog" ).dialog({
|
||||
autoOpen: false,
|
||||
width: 400,
|
||||
buttons: [
|
||||
{
|
||||
text: "Ok",
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: "Cancel",
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Link to open the dialog
|
||||
$( "#dialog-link" ).click(function( event ) {
|
||||
$( "#dialog" ).dialog( "open" );
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
$( "#datepicker" ).datepicker({
|
||||
inline: true
|
||||
});
|
||||
|
||||
$( "#slider" ).slider({
|
||||
range: true,
|
||||
values: [ 17, 67 ]
|
||||
});
|
||||
|
||||
$( "#progressbar" ).progressbar({
|
||||
value: 20
|
||||
});
|
||||
|
||||
$( "#spinner" ).spinner();
|
||||
|
||||
$( "#menu" ).menu();
|
||||
|
||||
$( "#tooltip" ).tooltip();
|
||||
|
||||
$( "#selectmenu" ).selectmenu();
|
||||
|
||||
// Hover states on the static widgets
|
||||
$( "#dialog-link, #icons li" ).hover(
|
||||
function() {
|
||||
$( this ).addClass( "ui-state-hover" );
|
||||
},
|
||||
function() {
|
||||
$( this ).removeClass( "ui-state-hover" );
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1315
src/lib/jquery-ui/jquery-ui.css
vendored
19070
src/lib/jquery-ui/jquery-ui.js
vendored
7
src/lib/jquery-ui/jquery-ui.min.css
vendored
6
src/lib/jquery-ui/jquery-ui.min.js
vendored
886
src/lib/jquery-ui/jquery-ui.structure.css
vendored
@ -1,886 +0,0 @@
|
||||
/*!
|
||||
* jQuery UI CSS Framework 1.13.3
|
||||
* https://jqueryui.com
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* https://api.jqueryui.com/category/theming/
|
||||
*/
|
||||
.ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
/* Layout helpers
|
||||
----------------------------------*/
|
||||
.ui-helper-hidden {
|
||||
display: none;
|
||||
}
|
||||
.ui-helper-hidden-accessible {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
.ui-helper-reset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
line-height: 1.3;
|
||||
text-decoration: none;
|
||||
font-size: 100%;
|
||||
list-style: none;
|
||||
}
|
||||
.ui-helper-clearfix:before,
|
||||
.ui-helper-clearfix:after {
|
||||
content: "";
|
||||
display: table;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.ui-helper-clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
.ui-helper-zfix {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
-ms-filter: "alpha(opacity=0)"; /* support: IE8 */
|
||||
}
|
||||
|
||||
.ui-front {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-disabled {
|
||||
cursor: default !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
.ui-icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-top: -.25em;
|
||||
position: relative;
|
||||
text-indent: -99999px;
|
||||
overflow: hidden;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ui-widget-icon-block {
|
||||
left: 50%;
|
||||
margin-left: -8px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.ui-resizable {
|
||||
position: relative;
|
||||
}
|
||||
.ui-resizable-handle {
|
||||
position: absolute;
|
||||
font-size: 0.1px;
|
||||
display: block;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.ui-resizable-disabled .ui-resizable-handle,
|
||||
.ui-resizable-autohide .ui-resizable-handle {
|
||||
display: none;
|
||||
}
|
||||
.ui-resizable-n {
|
||||
cursor: n-resize;
|
||||
height: 7px;
|
||||
width: 100%;
|
||||
top: -5px;
|
||||
left: 0;
|
||||
}
|
||||
.ui-resizable-s {
|
||||
cursor: s-resize;
|
||||
height: 7px;
|
||||
width: 100%;
|
||||
bottom: -5px;
|
||||
left: 0;
|
||||
}
|
||||
.ui-resizable-e {
|
||||
cursor: e-resize;
|
||||
width: 7px;
|
||||
right: -5px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.ui-resizable-w {
|
||||
cursor: w-resize;
|
||||
width: 7px;
|
||||
left: -5px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.ui-resizable-se {
|
||||
cursor: se-resize;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
}
|
||||
.ui-resizable-sw {
|
||||
cursor: sw-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
left: -5px;
|
||||
bottom: -5px;
|
||||
}
|
||||
.ui-resizable-nw {
|
||||
cursor: nw-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
left: -5px;
|
||||
top: -5px;
|
||||
}
|
||||
.ui-resizable-ne {
|
||||
cursor: ne-resize;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
right: -5px;
|
||||
top: -5px;
|
||||
}
|
||||
.ui-selectable {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.ui-selectable-helper {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
border: 1px dotted black;
|
||||
}
|
||||
.ui-sortable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.ui-accordion .ui-accordion-header {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
margin: 2px 0 0 0;
|
||||
padding: .5em .5em .5em .7em;
|
||||
font-size: 100%;
|
||||
}
|
||||
.ui-accordion .ui-accordion-content {
|
||||
padding: 1em 2.2em;
|
||||
border-top: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
.ui-autocomplete {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: default;
|
||||
}
|
||||
.ui-menu {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: block;
|
||||
outline: 0;
|
||||
}
|
||||
.ui-menu .ui-menu {
|
||||
position: absolute;
|
||||
}
|
||||
.ui-menu .ui-menu-item {
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
/* support: IE10, see #8844 */
|
||||
list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
|
||||
}
|
||||
.ui-menu .ui-menu-item-wrapper {
|
||||
position: relative;
|
||||
padding: 3px 1em 3px .4em;
|
||||
}
|
||||
.ui-menu .ui-menu-divider {
|
||||
margin: 5px 0;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
.ui-menu .ui-state-focus,
|
||||
.ui-menu .ui-state-active {
|
||||
margin: -1px;
|
||||
}
|
||||
|
||||
/* icon support */
|
||||
.ui-menu-icons {
|
||||
position: relative;
|
||||
}
|
||||
.ui-menu-icons .ui-menu-item-wrapper {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
/* left-aligned */
|
||||
.ui-menu .ui-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: .2em;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
/* right-aligned */
|
||||
.ui-menu .ui-menu-icon {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
.ui-button {
|
||||
padding: .4em 1em;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
margin-right: .1em;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
/* Support: IE <= 11 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.ui-button,
|
||||
.ui-button:link,
|
||||
.ui-button:visited,
|
||||
.ui-button:hover,
|
||||
.ui-button:active {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* to make room for the icon, a width needs to be set here */
|
||||
.ui-button-icon-only {
|
||||
width: 2em;
|
||||
box-sizing: border-box;
|
||||
text-indent: -9999px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* no icon support for input elements */
|
||||
input.ui-button.ui-button-icon-only {
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
/* button icon element(s) */
|
||||
.ui-button-icon-only .ui-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -8px;
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
.ui-button.ui-icon-notext .ui-icon {
|
||||
padding: 0;
|
||||
width: 2.1em;
|
||||
height: 2.1em;
|
||||
text-indent: -9999px;
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
input.ui-button.ui-icon-notext .ui-icon {
|
||||
width: auto;
|
||||
height: auto;
|
||||
text-indent: 0;
|
||||
white-space: normal;
|
||||
padding: .4em 1em;
|
||||
}
|
||||
|
||||
/* workarounds */
|
||||
/* Support: Firefox 5 - 40 */
|
||||
input.ui-button::-moz-focus-inner,
|
||||
button.ui-button::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.ui-controlgroup {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
.ui-controlgroup > .ui-controlgroup-item {
|
||||
float: left;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.ui-controlgroup > .ui-controlgroup-item:focus,
|
||||
.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {
|
||||
z-index: 9999;
|
||||
}
|
||||
.ui-controlgroup-vertical > .ui-controlgroup-item {
|
||||
display: block;
|
||||
float: none;
|
||||
width: 100%;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
text-align: left;
|
||||
}
|
||||
.ui-controlgroup-vertical .ui-controlgroup-item {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.ui-controlgroup .ui-controlgroup-label {
|
||||
padding: .4em 1em;
|
||||
}
|
||||
.ui-controlgroup .ui-controlgroup-label span {
|
||||
font-size: 80%;
|
||||
}
|
||||
.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {
|
||||
border-left: none;
|
||||
}
|
||||
.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {
|
||||
border-top: none;
|
||||
}
|
||||
.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {
|
||||
border-right: none;
|
||||
}
|
||||
.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Spinner specific style fixes */
|
||||
.ui-controlgroup-vertical .ui-spinner-input {
|
||||
|
||||
/* Support: IE8 only, Android < 4.4 only */
|
||||
width: 75%;
|
||||
width: calc( 100% - 2.4em );
|
||||
}
|
||||
.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
||||
.ui-checkboxradio-label .ui-icon-background {
|
||||
box-shadow: inset 1px 1px 1px #ccc;
|
||||
border-radius: .12em;
|
||||
border: none;
|
||||
}
|
||||
.ui-checkboxradio-radio-label .ui-icon-background {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 1em;
|
||||
overflow: visible;
|
||||
border: none;
|
||||
}
|
||||
.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,
|
||||
.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {
|
||||
background-image: none;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-width: 4px;
|
||||
border-style: solid;
|
||||
}
|
||||
.ui-checkboxradio-disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
.ui-datepicker {
|
||||
width: 17em;
|
||||
padding: .2em .2em 0;
|
||||
display: none;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-header {
|
||||
position: relative;
|
||||
padding: .2em 0;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-prev,
|
||||
.ui-datepicker .ui-datepicker-next {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
width: 1.8em;
|
||||
height: 1.8em;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-prev-hover,
|
||||
.ui-datepicker .ui-datepicker-next-hover {
|
||||
top: 1px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-prev {
|
||||
left: 2px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-next {
|
||||
right: 2px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-prev-hover {
|
||||
left: 1px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-next-hover {
|
||||
right: 1px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-prev span,
|
||||
.ui-datepicker .ui-datepicker-next span {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -8px;
|
||||
top: 50%;
|
||||
margin-top: -8px;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-title {
|
||||
margin: 0 2.3em;
|
||||
line-height: 1.8em;
|
||||
text-align: center;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-title select {
|
||||
font-size: 1em;
|
||||
margin: 1px 0;
|
||||
}
|
||||
.ui-datepicker select.ui-datepicker-month,
|
||||
.ui-datepicker select.ui-datepicker-year {
|
||||
width: 45%;
|
||||
}
|
||||
.ui-datepicker table {
|
||||
width: 100%;
|
||||
font-size: .9em;
|
||||
border-collapse: collapse;
|
||||
margin: 0 0 .4em;
|
||||
}
|
||||
.ui-datepicker th {
|
||||
padding: .7em .3em;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border: 0;
|
||||
}
|
||||
.ui-datepicker td {
|
||||
border: 0;
|
||||
padding: 1px;
|
||||
}
|
||||
.ui-datepicker td span,
|
||||
.ui-datepicker td a {
|
||||
display: block;
|
||||
padding: .2em;
|
||||
text-align: right;
|
||||
text-decoration: none;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-buttonpane {
|
||||
background-image: none;
|
||||
margin: .7em 0 0 0;
|
||||
padding: 0 .2em;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-buttonpane button {
|
||||
float: right;
|
||||
margin: .5em .2em .4em;
|
||||
cursor: pointer;
|
||||
padding: .2em .6em .3em .6em;
|
||||
width: auto;
|
||||
overflow: visible;
|
||||
}
|
||||
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* with multiple calendars */
|
||||
.ui-datepicker.ui-datepicker-multi {
|
||||
width: auto;
|
||||
}
|
||||
.ui-datepicker-multi .ui-datepicker-group {
|
||||
float: left;
|
||||
}
|
||||
.ui-datepicker-multi .ui-datepicker-group table {
|
||||
width: 95%;
|
||||
margin: 0 auto .4em;
|
||||
}
|
||||
.ui-datepicker-multi-2 .ui-datepicker-group {
|
||||
width: 50%;
|
||||
}
|
||||
.ui-datepicker-multi-3 .ui-datepicker-group {
|
||||
width: 33.3%;
|
||||
}
|
||||
.ui-datepicker-multi-4 .ui-datepicker-group {
|
||||
width: 25%;
|
||||
}
|
||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
|
||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
|
||||
border-left-width: 0;
|
||||
}
|
||||
.ui-datepicker-multi .ui-datepicker-buttonpane {
|
||||
clear: left;
|
||||
}
|
||||
.ui-datepicker-row-break {
|
||||
clear: both;
|
||||
width: 100%;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
/* RTL support */
|
||||
.ui-datepicker-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-prev {
|
||||
right: 2px;
|
||||
left: auto;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-next {
|
||||
left: 2px;
|
||||
right: auto;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-prev:hover {
|
||||
right: 1px;
|
||||
left: auto;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-next:hover {
|
||||
left: 1px;
|
||||
right: auto;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane {
|
||||
clear: right;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button {
|
||||
float: left;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
|
||||
.ui-datepicker-rtl .ui-datepicker-group {
|
||||
float: right;
|
||||
}
|
||||
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
|
||||
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
|
||||
border-right-width: 0;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
.ui-datepicker .ui-icon {
|
||||
display: block;
|
||||
text-indent: -99999px;
|
||||
overflow: hidden;
|
||||
background-repeat: no-repeat;
|
||||
left: .5em;
|
||||
top: .3em;
|
||||
}
|
||||
.ui-dialog {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: .2em;
|
||||
outline: 0;
|
||||
}
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: .4em 1em;
|
||||
position: relative;
|
||||
}
|
||||
.ui-dialog .ui-dialog-title {
|
||||
float: left;
|
||||
margin: .1em 0;
|
||||
white-space: nowrap;
|
||||
width: 90%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.ui-dialog .ui-dialog-titlebar-close {
|
||||
position: absolute;
|
||||
right: .3em;
|
||||
top: 50%;
|
||||
width: 20px;
|
||||
margin: -10px 0 0 0;
|
||||
padding: 1px;
|
||||
height: 20px;
|
||||
}
|
||||
.ui-dialog .ui-dialog-content {
|
||||
position: relative;
|
||||
border: 0;
|
||||
padding: .5em 1em;
|
||||
background: none;
|
||||
overflow: auto;
|
||||
}
|
||||
.ui-dialog .ui-dialog-buttonpane {
|
||||
text-align: left;
|
||||
border-width: 1px 0 0 0;
|
||||
background-image: none;
|
||||
margin-top: .5em;
|
||||
padding: .3em 1em .5em .4em;
|
||||
}
|
||||
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
|
||||
float: right;
|
||||
}
|
||||
.ui-dialog .ui-dialog-buttonpane button {
|
||||
margin: .5em .4em .5em 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui-dialog .ui-resizable-n {
|
||||
height: 2px;
|
||||
top: 0;
|
||||
}
|
||||
.ui-dialog .ui-resizable-e {
|
||||
width: 2px;
|
||||
right: 0;
|
||||
}
|
||||
.ui-dialog .ui-resizable-s {
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
}
|
||||
.ui-dialog .ui-resizable-w {
|
||||
width: 2px;
|
||||
left: 0;
|
||||
}
|
||||
.ui-dialog .ui-resizable-se,
|
||||
.ui-dialog .ui-resizable-sw,
|
||||
.ui-dialog .ui-resizable-ne,
|
||||
.ui-dialog .ui-resizable-nw {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
.ui-dialog .ui-resizable-se {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.ui-dialog .ui-resizable-sw {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.ui-dialog .ui-resizable-ne {
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
.ui-dialog .ui-resizable-nw {
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.ui-draggable .ui-dialog-titlebar {
|
||||
cursor: move;
|
||||
}
|
||||
.ui-progressbar {
|
||||
height: 2em;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
.ui-progressbar .ui-progressbar-value {
|
||||
margin: -1px;
|
||||
height: 100%;
|
||||
}
|
||||
.ui-progressbar .ui-progressbar-overlay {
|
||||
background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
|
||||
height: 100%;
|
||||
-ms-filter: "alpha(opacity=25)"; /* support: IE8 */
|
||||
opacity: 0.25;
|
||||
}
|
||||
.ui-progressbar-indeterminate .ui-progressbar-value {
|
||||
background-image: none;
|
||||
}
|
||||
.ui-selectmenu-menu {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
}
|
||||
.ui-selectmenu-menu .ui-menu {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
line-height: 1.5;
|
||||
padding: 2px 0.4em;
|
||||
margin: 0.5em 0 0 0;
|
||||
height: auto;
|
||||
border: 0;
|
||||
}
|
||||
.ui-selectmenu-open {
|
||||
display: block;
|
||||
}
|
||||
.ui-selectmenu-text {
|
||||
display: block;
|
||||
margin-right: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.ui-selectmenu-button.ui-button {
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
width: 14em;
|
||||
}
|
||||
.ui-selectmenu-icon.ui-icon {
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui-slider {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
.ui-slider .ui-slider-handle {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
cursor: pointer;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.ui-slider .ui-slider-range {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
font-size: .7em;
|
||||
display: block;
|
||||
border: 0;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
/* support: IE8 - See #6727 */
|
||||
.ui-slider.ui-state-disabled .ui-slider-handle,
|
||||
.ui-slider.ui-state-disabled .ui-slider-range {
|
||||
filter: inherit;
|
||||
}
|
||||
|
||||
.ui-slider-horizontal {
|
||||
height: .8em;
|
||||
}
|
||||
.ui-slider-horizontal .ui-slider-handle {
|
||||
top: -.3em;
|
||||
margin-left: -.6em;
|
||||
}
|
||||
.ui-slider-horizontal .ui-slider-range {
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.ui-slider-horizontal .ui-slider-range-min {
|
||||
left: 0;
|
||||
}
|
||||
.ui-slider-horizontal .ui-slider-range-max {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.ui-slider-vertical {
|
||||
width: .8em;
|
||||
height: 100px;
|
||||
}
|
||||
.ui-slider-vertical .ui-slider-handle {
|
||||
left: -.3em;
|
||||
margin-left: 0;
|
||||
margin-bottom: -.6em;
|
||||
}
|
||||
.ui-slider-vertical .ui-slider-range {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.ui-slider-vertical .ui-slider-range-min {
|
||||
bottom: 0;
|
||||
}
|
||||
.ui-slider-vertical .ui-slider-range-max {
|
||||
top: 0;
|
||||
}
|
||||
.ui-spinner {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.ui-spinner-input {
|
||||
border: none;
|
||||
background: none;
|
||||
color: inherit;
|
||||
padding: .222em 0;
|
||||
margin: .2em 0;
|
||||
vertical-align: middle;
|
||||
margin-left: .4em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
.ui-spinner-button {
|
||||
width: 1.6em;
|
||||
height: 50%;
|
||||
font-size: .5em;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
right: 0;
|
||||
}
|
||||
/* more specificity required here to override default borders */
|
||||
.ui-spinner a.ui-spinner-button {
|
||||
border-top-style: none;
|
||||
border-bottom-style: none;
|
||||
border-right-style: none;
|
||||
}
|
||||
.ui-spinner-up {
|
||||
top: 0;
|
||||
}
|
||||
.ui-spinner-down {
|
||||
bottom: 0;
|
||||
}
|
||||
.ui-tabs {
|
||||
position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||
padding: .2em;
|
||||
}
|
||||
.ui-tabs .ui-tabs-nav {
|
||||
margin: 0;
|
||||
padding: .2em .2em 0;
|
||||
}
|
||||
.ui-tabs .ui-tabs-nav li {
|
||||
list-style: none;
|
||||
float: left;
|
||||
position: relative;
|
||||
top: 0;
|
||||
margin: 1px .2em 0 0;
|
||||
border-bottom-width: 0;
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
|
||||
float: left;
|
||||
padding: .5em 1em;
|
||||
text-decoration: none;
|
||||
}
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active {
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
|
||||
.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
|
||||
cursor: text;
|
||||
}
|
||||
.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui-tabs .ui-tabs-panel {
|
||||
display: block;
|
||||
border-width: 0;
|
||||
padding: 1em 1.4em;
|
||||
background: none;
|
||||
}
|
||||
.ui-tooltip {
|
||||
padding: 8px;
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
max-width: 300px;
|
||||
}
|
||||
body .ui-tooltip {
|
||||
border-width: 2px;
|
||||
}
|
446
src/lib/jquery-ui/jquery-ui.theme.css
vendored
@ -1,446 +0,0 @@
|
||||
/*!
|
||||
* jQuery UI CSS Framework 1.13.3
|
||||
* https://jqueryui.com
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* https://api.jqueryui.com/category/theming/
|
||||
*
|
||||
* To view and modify this theme, visit https://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px
|
||||
*/
|
||||
|
||||
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget {
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui-widget .ui-widget {
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui-widget input,
|
||||
.ui-widget select,
|
||||
.ui-widget textarea,
|
||||
.ui-widget button {
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui-widget.ui-widget-content {
|
||||
border: 1px solid #c5c5c5;
|
||||
}
|
||||
.ui-widget-content {
|
||||
border: 1px solid #dddddd;
|
||||
background: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
.ui-widget-content a {
|
||||
color: #333333;
|
||||
}
|
||||
.ui-widget-header {
|
||||
border: 1px solid #dddddd;
|
||||
background: #e9e9e9;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui-widget-header a {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.ui-state-default,
|
||||
.ui-widget-content .ui-state-default,
|
||||
.ui-widget-header .ui-state-default,
|
||||
.ui-button,
|
||||
|
||||
/* We use html here because we need a greater specificity to make sure disabled
|
||||
works properly when clicked or hovered */
|
||||
html .ui-button.ui-state-disabled:hover,
|
||||
html .ui-button.ui-state-disabled:active {
|
||||
border: 1px solid #c5c5c5;
|
||||
background: #f6f6f6;
|
||||
font-weight: normal;
|
||||
color: #454545;
|
||||
}
|
||||
.ui-state-default a,
|
||||
.ui-state-default a:link,
|
||||
.ui-state-default a:visited,
|
||||
a.ui-button,
|
||||
a:link.ui-button,
|
||||
a:visited.ui-button,
|
||||
.ui-button {
|
||||
color: #454545;
|
||||
text-decoration: none;
|
||||
}
|
||||
.ui-state-hover,
|
||||
.ui-widget-content .ui-state-hover,
|
||||
.ui-widget-header .ui-state-hover,
|
||||
.ui-state-focus,
|
||||
.ui-widget-content .ui-state-focus,
|
||||
.ui-widget-header .ui-state-focus,
|
||||
.ui-button:hover,
|
||||
.ui-button:focus {
|
||||
border: 1px solid #cccccc;
|
||||
background: #ededed;
|
||||
font-weight: normal;
|
||||
color: #2b2b2b;
|
||||
}
|
||||
.ui-state-hover a,
|
||||
.ui-state-hover a:hover,
|
||||
.ui-state-hover a:link,
|
||||
.ui-state-hover a:visited,
|
||||
.ui-state-focus a,
|
||||
.ui-state-focus a:hover,
|
||||
.ui-state-focus a:link,
|
||||
.ui-state-focus a:visited,
|
||||
a.ui-button:hover,
|
||||
a.ui-button:focus {
|
||||
color: #2b2b2b;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ui-visual-focus {
|
||||
box-shadow: 0 0 3px 1px rgb(94, 158, 214);
|
||||
}
|
||||
.ui-state-active,
|
||||
.ui-widget-content .ui-state-active,
|
||||
.ui-widget-header .ui-state-active,
|
||||
a.ui-button:active,
|
||||
.ui-button:active,
|
||||
.ui-button.ui-state-active:hover {
|
||||
border: 1px solid #003eff;
|
||||
background: #007fff;
|
||||
font-weight: normal;
|
||||
color: #ffffff;
|
||||
}
|
||||
.ui-icon-background,
|
||||
.ui-state-active .ui-icon-background {
|
||||
border: #003eff;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.ui-state-active a,
|
||||
.ui-state-active a:link,
|
||||
.ui-state-active a:visited {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-highlight,
|
||||
.ui-widget-content .ui-state-highlight,
|
||||
.ui-widget-header .ui-state-highlight {
|
||||
border: 1px solid #dad55e;
|
||||
background: #fffa90;
|
||||
color: #777620;
|
||||
}
|
||||
.ui-state-checked {
|
||||
border: 1px solid #dad55e;
|
||||
background: #fffa90;
|
||||
}
|
||||
.ui-state-highlight a,
|
||||
.ui-widget-content .ui-state-highlight a,
|
||||
.ui-widget-header .ui-state-highlight a {
|
||||
color: #777620;
|
||||
}
|
||||
.ui-state-error,
|
||||
.ui-widget-content .ui-state-error,
|
||||
.ui-widget-header .ui-state-error {
|
||||
border: 1px solid #f1a899;
|
||||
background: #fddfdf;
|
||||
color: #5f3f3f;
|
||||
}
|
||||
.ui-state-error a,
|
||||
.ui-widget-content .ui-state-error a,
|
||||
.ui-widget-header .ui-state-error a {
|
||||
color: #5f3f3f;
|
||||
}
|
||||
.ui-state-error-text,
|
||||
.ui-widget-content .ui-state-error-text,
|
||||
.ui-widget-header .ui-state-error-text {
|
||||
color: #5f3f3f;
|
||||
}
|
||||
.ui-priority-primary,
|
||||
.ui-widget-content .ui-priority-primary,
|
||||
.ui-widget-header .ui-priority-primary {
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui-priority-secondary,
|
||||
.ui-widget-content .ui-priority-secondary,
|
||||
.ui-widget-header .ui-priority-secondary {
|
||||
opacity: .7;
|
||||
-ms-filter: "alpha(opacity=70)"; /* support: IE8 */
|
||||
font-weight: normal;
|
||||
}
|
||||
.ui-state-disabled,
|
||||
.ui-widget-content .ui-state-disabled,
|
||||
.ui-widget-header .ui-state-disabled {
|
||||
opacity: .35;
|
||||
-ms-filter: "alpha(opacity=35)"; /* support: IE8 */
|
||||
background-image: none;
|
||||
}
|
||||
.ui-state-disabled .ui-icon {
|
||||
-ms-filter: "alpha(opacity=35)"; /* support: IE8 - See #6059 */
|
||||
}
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.ui-icon,
|
||||
.ui-widget-content .ui-icon {
|
||||
background-image: url("images/ui-icons_444444_256x240.png");
|
||||
}
|
||||
.ui-widget-header .ui-icon {
|
||||
background-image: url("images/ui-icons_444444_256x240.png");
|
||||
}
|
||||
.ui-state-hover .ui-icon,
|
||||
.ui-state-focus .ui-icon,
|
||||
.ui-button:hover .ui-icon,
|
||||
.ui-button:focus .ui-icon {
|
||||
background-image: url("images/ui-icons_555555_256x240.png");
|
||||
}
|
||||
.ui-state-active .ui-icon,
|
||||
.ui-button:active .ui-icon {
|
||||
background-image: url("images/ui-icons_ffffff_256x240.png");
|
||||
}
|
||||
.ui-state-highlight .ui-icon,
|
||||
.ui-button .ui-state-highlight.ui-icon {
|
||||
background-image: url("images/ui-icons_777620_256x240.png");
|
||||
}
|
||||
.ui-state-error .ui-icon,
|
||||
.ui-state-error-text .ui-icon {
|
||||
background-image: url("images/ui-icons_cc0000_256x240.png");
|
||||
}
|
||||
.ui-button .ui-icon {
|
||||
background-image: url("images/ui-icons_777777_256x240.png");
|
||||
}
|
||||
|
||||
/* positioning */
|
||||
/* Three classes needed to override `.ui-button:hover .ui-icon` */
|
||||
.ui-icon-blank.ui-icon-blank.ui-icon-blank {
|
||||
background-image: none;
|
||||
}
|
||||
.ui-icon-caret-1-n { background-position: 0 0; }
|
||||
.ui-icon-caret-1-ne { background-position: -16px 0; }
|
||||
.ui-icon-caret-1-e { background-position: -32px 0; }
|
||||
.ui-icon-caret-1-se { background-position: -48px 0; }
|
||||
.ui-icon-caret-1-s { background-position: -65px 0; }
|
||||
.ui-icon-caret-1-sw { background-position: -80px 0; }
|
||||
.ui-icon-caret-1-w { background-position: -96px 0; }
|
||||
.ui-icon-caret-1-nw { background-position: -112px 0; }
|
||||
.ui-icon-caret-2-n-s { background-position: -128px 0; }
|
||||
.ui-icon-caret-2-e-w { background-position: -144px 0; }
|
||||
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
||||
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
||||
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
||||
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
||||
.ui-icon-triangle-1-s { background-position: -65px -16px; }
|
||||
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
||||
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
||||
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
||||
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
||||
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
||||
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
||||
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
||||
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
||||
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
||||
.ui-icon-arrow-1-s { background-position: -65px -32px; }
|
||||
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
||||
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
||||
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
||||
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
||||
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
||||
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
||||
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
||||
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
||||
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
||||
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
||||
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
||||
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
|
||||
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
||||
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
||||
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
||||
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
||||
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
||||
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
||||
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
||||
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
||||
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
||||
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
||||
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
||||
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
||||
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
||||
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
||||
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
||||
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
||||
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
||||
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
||||
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
||||
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
||||
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
||||
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
||||
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
||||
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
||||
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
||||
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
||||
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
||||
.ui-icon-extlink { background-position: -32px -80px; }
|
||||
.ui-icon-newwin { background-position: -48px -80px; }
|
||||
.ui-icon-refresh { background-position: -64px -80px; }
|
||||
.ui-icon-shuffle { background-position: -80px -80px; }
|
||||
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
||||
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
||||
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
||||
.ui-icon-folder-open { background-position: -16px -96px; }
|
||||
.ui-icon-document { background-position: -32px -96px; }
|
||||
.ui-icon-document-b { background-position: -48px -96px; }
|
||||
.ui-icon-note { background-position: -64px -96px; }
|
||||
.ui-icon-mail-closed { background-position: -80px -96px; }
|
||||
.ui-icon-mail-open { background-position: -96px -96px; }
|
||||
.ui-icon-suitcase { background-position: -112px -96px; }
|
||||
.ui-icon-comment { background-position: -128px -96px; }
|
||||
.ui-icon-person { background-position: -144px -96px; }
|
||||
.ui-icon-print { background-position: -160px -96px; }
|
||||
.ui-icon-trash { background-position: -176px -96px; }
|
||||
.ui-icon-locked { background-position: -192px -96px; }
|
||||
.ui-icon-unlocked { background-position: -208px -96px; }
|
||||
.ui-icon-bookmark { background-position: -224px -96px; }
|
||||
.ui-icon-tag { background-position: -240px -96px; }
|
||||
.ui-icon-home { background-position: 0 -112px; }
|
||||
.ui-icon-flag { background-position: -16px -112px; }
|
||||
.ui-icon-calendar { background-position: -32px -112px; }
|
||||
.ui-icon-cart { background-position: -48px -112px; }
|
||||
.ui-icon-pencil { background-position: -64px -112px; }
|
||||
.ui-icon-clock { background-position: -80px -112px; }
|
||||
.ui-icon-disk { background-position: -96px -112px; }
|
||||
.ui-icon-calculator { background-position: -112px -112px; }
|
||||
.ui-icon-zoomin { background-position: -128px -112px; }
|
||||
.ui-icon-zoomout { background-position: -144px -112px; }
|
||||
.ui-icon-search { background-position: -160px -112px; }
|
||||
.ui-icon-wrench { background-position: -176px -112px; }
|
||||
.ui-icon-gear { background-position: -192px -112px; }
|
||||
.ui-icon-heart { background-position: -208px -112px; }
|
||||
.ui-icon-star { background-position: -224px -112px; }
|
||||
.ui-icon-link { background-position: -240px -112px; }
|
||||
.ui-icon-cancel { background-position: 0 -128px; }
|
||||
.ui-icon-plus { background-position: -16px -128px; }
|
||||
.ui-icon-plusthick { background-position: -32px -128px; }
|
||||
.ui-icon-minus { background-position: -48px -128px; }
|
||||
.ui-icon-minusthick { background-position: -64px -128px; }
|
||||
.ui-icon-close { background-position: -80px -128px; }
|
||||
.ui-icon-closethick { background-position: -96px -128px; }
|
||||
.ui-icon-key { background-position: -112px -128px; }
|
||||
.ui-icon-lightbulb { background-position: -128px -128px; }
|
||||
.ui-icon-scissors { background-position: -144px -128px; }
|
||||
.ui-icon-clipboard { background-position: -160px -128px; }
|
||||
.ui-icon-copy { background-position: -176px -128px; }
|
||||
.ui-icon-contact { background-position: -192px -128px; }
|
||||
.ui-icon-image { background-position: -208px -128px; }
|
||||
.ui-icon-video { background-position: -224px -128px; }
|
||||
.ui-icon-script { background-position: -240px -128px; }
|
||||
.ui-icon-alert { background-position: 0 -144px; }
|
||||
.ui-icon-info { background-position: -16px -144px; }
|
||||
.ui-icon-notice { background-position: -32px -144px; }
|
||||
.ui-icon-help { background-position: -48px -144px; }
|
||||
.ui-icon-check { background-position: -64px -144px; }
|
||||
.ui-icon-bullet { background-position: -80px -144px; }
|
||||
.ui-icon-radio-on { background-position: -96px -144px; }
|
||||
.ui-icon-radio-off { background-position: -112px -144px; }
|
||||
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||
.ui-icon-play { background-position: 0 -160px; }
|
||||
.ui-icon-pause { background-position: -16px -160px; }
|
||||
.ui-icon-seek-next { background-position: -32px -160px; }
|
||||
.ui-icon-seek-prev { background-position: -48px -160px; }
|
||||
.ui-icon-seek-end { background-position: -64px -160px; }
|
||||
.ui-icon-seek-start { background-position: -80px -160px; }
|
||||
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
||||
.ui-icon-seek-first { background-position: -80px -160px; }
|
||||
.ui-icon-stop { background-position: -96px -160px; }
|
||||
.ui-icon-eject { background-position: -112px -160px; }
|
||||
.ui-icon-volume-off { background-position: -128px -160px; }
|
||||
.ui-icon-volume-on { background-position: -144px -160px; }
|
||||
.ui-icon-power { background-position: 0 -176px; }
|
||||
.ui-icon-signal-diag { background-position: -16px -176px; }
|
||||
.ui-icon-signal { background-position: -32px -176px; }
|
||||
.ui-icon-battery-0 { background-position: -48px -176px; }
|
||||
.ui-icon-battery-1 { background-position: -64px -176px; }
|
||||
.ui-icon-battery-2 { background-position: -80px -176px; }
|
||||
.ui-icon-battery-3 { background-position: -96px -176px; }
|
||||
.ui-icon-circle-plus { background-position: 0 -192px; }
|
||||
.ui-icon-circle-minus { background-position: -16px -192px; }
|
||||
.ui-icon-circle-close { background-position: -32px -192px; }
|
||||
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
||||
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
||||
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
||||
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
||||
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
||||
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
||||
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
||||
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
||||
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
||||
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
||||
.ui-icon-circle-check { background-position: -208px -192px; }
|
||||
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
||||
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
||||
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
||||
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
||||
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
||||
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
||||
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
||||
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
||||
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
||||
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
||||
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
||||
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
||||
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-left,
|
||||
.ui-corner-tl {
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-right,
|
||||
.ui-corner-tr {
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-left,
|
||||
.ui-corner-bl {
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-right,
|
||||
.ui-corner-br {
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay {
|
||||
background: #aaaaaa;
|
||||
opacity: .3;
|
||||
-ms-filter: "alpha(opacity=30)"; /* support: IE8 */
|
||||
}
|
||||
.ui-widget-shadow {
|
||||
-webkit-box-shadow: 0px 0px 5px #666666;
|
||||
box-shadow: 0px 0px 5px #666666;
|
||||
}
|
5
src/lib/jquery-ui/jquery-ui.theme.min.css
vendored
@ -1,84 +0,0 @@
|
||||
{
|
||||
"name": "jquery-ui",
|
||||
"title": "jQuery UI",
|
||||
"description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.",
|
||||
"version": "1.13.3",
|
||||
"homepage": "https://jqueryui.com",
|
||||
"author": {
|
||||
"name": "OpenJS Foundation and other contributors",
|
||||
"url": "https://github.com/jquery/jquery-ui/blob/1.13.3/AUTHORS.txt"
|
||||
},
|
||||
"main": "ui/widget.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Jörn Zaefferer",
|
||||
"email": "joern.zaefferer@gmail.com",
|
||||
"url": "https://bassistance.de"
|
||||
},
|
||||
{
|
||||
"name": "Mike Sherov",
|
||||
"email": "mike.sherov@gmail.com",
|
||||
"url": "https://mike.sherov.com"
|
||||
},
|
||||
{
|
||||
"name": "TJ VanToll",
|
||||
"email": "tj.vantoll@gmail.com",
|
||||
"url": "https://www.tjvantoll.com"
|
||||
},
|
||||
{
|
||||
"name": "Felix Nagel",
|
||||
"email": "info@felixnagel.com",
|
||||
"url": "https://www.felixnagel.com"
|
||||
},
|
||||
{
|
||||
"name": "Alex Schmitz",
|
||||
"email": "arschmitz@gmail.com",
|
||||
"url": "https://github.com/arschmitz"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/jquery/jquery-ui.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/jquery/jquery-ui/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "grunt build",
|
||||
"lint": "grunt lint",
|
||||
"test:server": "node tests/runner/server.js",
|
||||
"test:unit": "node tests/runner/command.js",
|
||||
"test": "grunt && npm run test:unit -- -h"
|
||||
},
|
||||
"dependencies": {
|
||||
"jquery": ">=1.8.0 <4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"body-parser": "1.20.2",
|
||||
"browserstack-local": "1.5.5",
|
||||
"commitplease": "3.2.0",
|
||||
"diff": "5.2.0",
|
||||
"eslint-config-jquery": "3.0.2",
|
||||
"exit-hook": "4.0.0",
|
||||
"express": "4.19.2",
|
||||
"express-body-parser-error-handler": "1.0.7",
|
||||
"grunt": "1.6.1",
|
||||
"grunt-bowercopy": "1.2.5",
|
||||
"grunt-cli": "1.4.3",
|
||||
"grunt-compare-size": "0.4.2",
|
||||
"grunt-contrib-concat": "2.1.0",
|
||||
"grunt-contrib-csslint": "2.0.0",
|
||||
"grunt-contrib-requirejs": "1.0.0",
|
||||
"grunt-contrib-uglify": "5.2.2",
|
||||
"grunt-eslint": "24.0.1",
|
||||
"grunt-git-authors": "3.2.0",
|
||||
"grunt-html": "16.0.0",
|
||||
"load-grunt-tasks": "5.1.0",
|
||||
"rimraf": "4.4.1",
|
||||
"selenium-webdriver": "4.18.1",
|
||||
"testswarm": "1.1.2",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"keywords": []
|
||||
}
|
@ -17,7 +17,6 @@ import "virtual:svg-icons-register";
|
||||
// 引入项目中的全部全局组件
|
||||
import SvgIcon from "@/components/svgIcon.vue";
|
||||
import library from "./fontawsomeIconRegister";
|
||||
import "flag-icons/css/flag-icons.min.css";
|
||||
|
||||
/* import font awesome icon component */
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
|
@ -8,6 +8,7 @@ import AssetManagement from "@/views/AssetManagement/AssetManagement.vue";
|
||||
import AlertManagement from "@/views/alert/AlertManagement.vue";
|
||||
import ProductSetting from "@/views/productSetting/ProductSetting.vue";
|
||||
import EnergyManagement from "@/views/energyManagement/EnergyManagement.vue";
|
||||
import SettingManagement from "@/views/setting/SettingManagement.vue";
|
||||
import Login from "@/views/login/Login.vue";
|
||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||
import useGetCookie from "@/hooks/useGetCookie";
|
||||
@ -80,10 +81,15 @@ const router = createRouter({
|
||||
component: ProductSetting,
|
||||
},
|
||||
{
|
||||
path: "/energyManagement",
|
||||
path: "/energyManagement/:main_system_id/:sub_system_id/:type",
|
||||
name: "energyManagement",
|
||||
component: EnergyManagement,
|
||||
},
|
||||
{
|
||||
path: "/setting/:main_system_id/:sub_system_id/:type",
|
||||
name: "setting",
|
||||
component: SettingManagement,
|
||||
},
|
||||
{
|
||||
path: "/mytestfile/mjm",
|
||||
name: "mytestfile",
|
||||
@ -99,22 +105,19 @@ router.beforeEach(async (to, from, next) => {
|
||||
const authRequired = !publicPages.includes(to.path);
|
||||
const auth = useUserInfoStore();
|
||||
const token = useGetCookie("JWT-Authorization");
|
||||
|
||||
if (to.path === "/logout") {
|
||||
document.cookie = "JWT-Authorization=";
|
||||
auth.user.token = "";
|
||||
window.location.reload();
|
||||
next({ path: "/login" });
|
||||
}
|
||||
const user_name = useGetCookie("user_name");
|
||||
|
||||
if ((authRequired && !token) || to.path === "/") {
|
||||
auth.user.token = "";
|
||||
next({ path: "/login" });
|
||||
} else if (!authRequired) {
|
||||
document.cookie = "JWT-Authorization=";
|
||||
document.cookie = "JWT-Authorization=; Max-Age=0";
|
||||
document.cookie = "user_name=; Max-Age=0";
|
||||
auth.user.token = "";
|
||||
auth.user.user_name = "";
|
||||
} else {
|
||||
auth.user.token = token;
|
||||
auth.user.user_name = user_name;
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
@ -1,17 +1,22 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import { ref, computed, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { getBuildings } from "@/apis/building";
|
||||
import { getDashboard2D3D } from "@/apis/dashboard";
|
||||
import { getAssetFloorList, getDepartmentList } from "@/apis/asset";
|
||||
|
||||
const useBuildingStore = defineStore("buildingInfo", () => {
|
||||
// 所有棟別
|
||||
// 狀態定義
|
||||
const buildings = ref([]);
|
||||
|
||||
const selectedBuilding = ref(null);
|
||||
|
||||
// 所有大小類系統
|
||||
const floorList = ref([]);
|
||||
const deptList = ref([]);
|
||||
const mainSubSys = ref([]);
|
||||
// 控制顯示2D/3D切換與內容
|
||||
const showForgeArea = ref(true);
|
||||
const previewImageExt = ref("");
|
||||
|
||||
// 所有大類
|
||||
// 計算屬性
|
||||
const mainSys = computed(() =>
|
||||
mainSubSys.value.map(({ main_system_tag, full_name }) => ({
|
||||
main_system_tag,
|
||||
@ -21,7 +26,6 @@ const useBuildingStore = defineStore("buildingInfo", () => {
|
||||
|
||||
const subSys = computed(() => {
|
||||
let subPages = [];
|
||||
|
||||
mainSubSys.value.forEach(({ main_system_tag, history_Sub_systems }) => {
|
||||
subPages = [
|
||||
...subPages,
|
||||
@ -32,7 +36,6 @@ const useBuildingStore = defineStore("buildingInfo", () => {
|
||||
})),
|
||||
];
|
||||
});
|
||||
|
||||
return subPages;
|
||||
});
|
||||
|
||||
@ -44,14 +47,89 @@ const useBuildingStore = defineStore("buildingInfo", () => {
|
||||
return null;
|
||||
});
|
||||
|
||||
// 獲取所有建築物
|
||||
const fetchBuildings = async () => {
|
||||
// const res = await getBuildings();
|
||||
buildings.value = JSON.parse(localStorage.getItem("CviBuildingList")) || [];
|
||||
const storedBuilding = JSON.parse(localStorage.getItem("CviBuilding"));
|
||||
if (buildings.value.length > 0) {
|
||||
selectedBuilding.value = storedBuilding || buildings.value[0]; // 預設選第一個建築
|
||||
} else {
|
||||
selectedBuilding.value = null; // 如果沒有建築物,清空選擇
|
||||
}
|
||||
};
|
||||
|
||||
// 獲取樓層資料
|
||||
const fetchFloorList = async (building_guid) => {
|
||||
const res = await getAssetFloorList(building_guid);
|
||||
floorList.value =
|
||||
res.data[0]?.floors.map((d) => ({
|
||||
...d,
|
||||
title: d.full_name,
|
||||
key: d.floor_guid,
|
||||
})) || [];
|
||||
};
|
||||
|
||||
// 獲取部門資料
|
||||
const fetchDepartmentList = async () => {
|
||||
const res = await getDepartmentList();
|
||||
deptList.value =
|
||||
res.data.map((d) => ({
|
||||
...d,
|
||||
title: d.name,
|
||||
key: d.id,
|
||||
})) || [];
|
||||
};
|
||||
|
||||
// 獲取2D、3D顯示與否
|
||||
const fetchDashboard2D3D = async (BuildingId) => {
|
||||
const res = await getDashboard2D3D(BuildingId);
|
||||
showForgeArea.value = res.data.is3DEnabled;
|
||||
previewImageExt.value = res.data.previewImageExt || "";
|
||||
};
|
||||
|
||||
// 清除localStorage建築物
|
||||
const deleteBuilding = () => {
|
||||
localStorage.removeItem("CviBuildingList");
|
||||
localStorage.removeItem("CviBuilding");
|
||||
buildings.value = [];
|
||||
selectedBuilding.value = null;
|
||||
};
|
||||
|
||||
// 當 selectedBuilding 改變時,更新 floorList 和 deptList
|
||||
watch(selectedBuilding, async (newBuilding) => {
|
||||
if (newBuilding) {
|
||||
localStorage.setItem("CviBuilding", JSON.stringify(newBuilding));
|
||||
await Promise.all([
|
||||
fetchFloorList(newBuilding.building_guid),
|
||||
fetchDepartmentList(),
|
||||
fetchDashboard2D3D(newBuilding.building_guid),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化資料
|
||||
const initialize = async () => {
|
||||
await fetchBuildings();
|
||||
};
|
||||
|
||||
return {
|
||||
buildings,
|
||||
selectedBuilding,
|
||||
floorList,
|
||||
deptList,
|
||||
mainSubSys,
|
||||
mainSys,
|
||||
subSys,
|
||||
selectedSystem,
|
||||
showForgeArea,
|
||||
previewImageExt,
|
||||
deleteBuilding,
|
||||
fetchBuildings,
|
||||
fetchFloorList,
|
||||
fetchDepartmentList,
|
||||
fetchDashboard2D3D,
|
||||
initialize,
|
||||
};
|
||||
});
|
||||
|
||||
export default useBuildingStore;
|
||||
|
@ -5,6 +5,7 @@ const useUserInfoStore = defineStore("userInfo", () => {
|
||||
const user = ref({
|
||||
token: "",
|
||||
expires: 0,
|
||||
user_name:"",
|
||||
});
|
||||
|
||||
const auth_page = ref([]);
|
||||
|
@ -2,70 +2,80 @@ import useGetCookie from "@/hooks/useGetCookie";
|
||||
import axios from "axios";
|
||||
const BASEURL = import.meta.env.VITE_API_BASEURL;
|
||||
|
||||
// --- 請求攔截器的共用邏輯 ---
|
||||
const requestInterceptor = (config) => {
|
||||
// 確保 headers 物件存在
|
||||
if (!config.headers) {
|
||||
config.headers = {};
|
||||
}
|
||||
|
||||
// 1. 取得並附加最新的 Token
|
||||
const token = useGetCookie("JWT-Authorization");
|
||||
if (token) {
|
||||
// 正確做法:修改屬性,而不是覆蓋整個物件
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
// 2. 取得並附加選定的建築物 GUID
|
||||
const storedBuilding = localStorage.getItem("CviBuilding");
|
||||
if (storedBuilding) {
|
||||
try {
|
||||
const buildingObject = JSON.parse(storedBuilding);
|
||||
if (buildingObject && buildingObject.building_guid) {
|
||||
// 與後端約定好要用哪個標頭,這裡使用 'X-Building-GUID' 作為範例
|
||||
config.headers["X-Building-GUID"] = buildingObject.building_guid;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("解析 localStorage 中的 CviBuilding 失敗:", e);
|
||||
}
|
||||
}
|
||||
return config;
|
||||
};
|
||||
|
||||
const requestErrorInterceptor = (error) => {
|
||||
return Promise.reject(error);
|
||||
};
|
||||
|
||||
|
||||
// --- 一般 API 實例 ---
|
||||
const instance = axios.create({
|
||||
baseURL: BASEURL,
|
||||
timeout: -1,
|
||||
headers: { Authorization: `Bearer ${useGetCookie("JWT-Authorization")}` },
|
||||
timeout: 10000, // 建議設定超時
|
||||
// 移除靜態 headers
|
||||
});
|
||||
|
||||
// Add a request interceptor
|
||||
instance.interceptors.request.use(
|
||||
function (config) {
|
||||
// Do something before request is sent
|
||||
const token = useGetCookie("JWT-Authorization");
|
||||
config.headers = {
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 使用共用的攔截器
|
||||
instance.interceptors.request.use(requestInterceptor, requestErrorInterceptor);
|
||||
|
||||
// Add a response interceptor
|
||||
instance.interceptors.response.use(
|
||||
function (response) {
|
||||
// Any status code that lie within the range of 2xx cause this function to trigger
|
||||
// Do something with response data
|
||||
const { status, data, headers } = response;
|
||||
const { data } = response;
|
||||
|
||||
return {
|
||||
...data,
|
||||
};
|
||||
return { ...data };
|
||||
},
|
||||
function (error) {
|
||||
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
||||
// Do something with response error
|
||||
if (response && response.status === 401) {
|
||||
window.location.href = "/logout";
|
||||
if (error.response && error.response.status === 401) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// --- 檔案處理 API 實例 ---
|
||||
export const fileInstance = axios.create({
|
||||
baseURL: BASEURL,
|
||||
timeout: -1,
|
||||
headers: { Authorization: `Bearer ${useGetCookie("JWT-Authorization")}` },
|
||||
// 移除靜態 headers
|
||||
});
|
||||
|
||||
// Add a request interceptor
|
||||
fileInstance.interceptors.request.use(
|
||||
function (config) {
|
||||
// Do something before request is sent
|
||||
const token = useGetCookie("JWT-Authorization");
|
||||
config.headers = {
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 使用共用的攔截器
|
||||
fileInstance.interceptors.request.use(requestInterceptor, requestErrorInterceptor);
|
||||
|
||||
// Add a response interceptor
|
||||
fileInstance.interceptors.response.use(
|
||||
|
@ -1,12 +1,64 @@
|
||||
<script setup>
|
||||
import { ref, provide, onMounted, watch, computed } from "vue";
|
||||
import AssetMainList from "./components/AssetMainList.vue";
|
||||
import AssetSubList from "./components/AssetSubList.vue";
|
||||
import AssetTable from "./components/AssetTable.vue";
|
||||
import { getOperationCompanyList } from "@/apis/operation";
|
||||
import { getIOTSchema, getElecTypeList } from "@/apis/asset";
|
||||
import useSearchParam from "@/hooks/useSearchParam";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const storeBuild = useBuildingStore();
|
||||
const { searchParams, changeParams } = useSearchParam();
|
||||
const companyOptions = ref([]);
|
||||
const iotSchemaOptions = ref([]);
|
||||
const elecTypeOptions = ref([]);
|
||||
const getCompany = async () => {
|
||||
const res = await getOperationCompanyList();
|
||||
companyOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
const getIOTSchemaOptions = async (id) => {
|
||||
const res = await getIOTSchema(Number(id));
|
||||
iotSchemaOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
const getElecType = async () => {
|
||||
const res = await getElecTypeList();
|
||||
elecTypeOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
|
||||
const departmentList = computed(() => storeBuild.deptList);
|
||||
const floors = computed(() => storeBuild.floorList);
|
||||
|
||||
onMounted(() => {
|
||||
getCompany();
|
||||
getElecType();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => searchParams.value.subSys_id,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
getIOTSchemaOptions(newValue);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
provide("asset_modal_options", {
|
||||
companyOptions,
|
||||
iotSchemaOptions,
|
||||
elecTypeOptions,
|
||||
departmentList,
|
||||
floors,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1 class="text-2xl font-extrabold mb-2">
|
||||
{{ $t("assetManagement.title") }}
|
||||
</h1>
|
||||
<AssetMainList />
|
||||
<AssetSubList />
|
||||
<AssetTable />
|
||||
</template>
|
||||
|
134
src/views/AssetManagement/components/AssetMainList.vue
Normal file
@ -0,0 +1,134 @@
|
||||
<script setup>
|
||||
import { getAssetMainList, deleteAssetMainItem } from "@/apis/asset";
|
||||
import AssetMainListAddModal from "./AssetMainListAddModal.vue";
|
||||
import { ref, onMounted, watch, inject } from "vue";
|
||||
import useSearchParam from "@/hooks/useSearchParam";
|
||||
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { searchParams, changeParams } = useSearchParam();
|
||||
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
|
||||
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||
const isEditMode = ref(false);
|
||||
const formState = ref({
|
||||
id: 0,
|
||||
system_key: "",
|
||||
system_value: "",
|
||||
});
|
||||
|
||||
const getMainSystems = async () => {
|
||||
const res = await getAssetMainList(store.selectedBuilding.building_guid);
|
||||
const cate = res.data.map((d, index) => ({
|
||||
...d,
|
||||
title: d.system_key,
|
||||
key: d.id,
|
||||
active: searchParams.value?.mainSys_id
|
||||
? parseInt(searchParams.value?.mainSys_id) === d.id
|
||||
: index === 0,
|
||||
}));
|
||||
setItems(cate);
|
||||
};
|
||||
|
||||
const openModal = () => {
|
||||
asset_add_main_item.showModal();
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
formState.value = {
|
||||
id: 0,
|
||||
system_key: "",
|
||||
system_value: "",
|
||||
};
|
||||
asset_add_main_item.close();
|
||||
};
|
||||
|
||||
const edit = (item) => {
|
||||
formState.value = { ...item };
|
||||
openModal();
|
||||
};
|
||||
|
||||
const deleteItem = async (id) => {
|
||||
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||
await cancelToastOpen();
|
||||
const res = await deleteAssetMainItem(id);
|
||||
if (res.isSuccess) {
|
||||
openToast("success", t("msg.delete_success"));
|
||||
getMainSystems();
|
||||
} else {
|
||||
openToast("error", res.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => store.selectedBuilding,
|
||||
(newBuilding) => {
|
||||
if (newBuilding) {
|
||||
getMainSystems();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(selectedBtn, (newValue) => {
|
||||
changeParams({
|
||||
mainSys_id: newValue.key,
|
||||
subSys_id: null,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold ps-2 whitespace-nowrap">
|
||||
{{ $t("history.system_category") }} :
|
||||
</h2>
|
||||
<AssetMainListAddModal
|
||||
:openModal="openModal"
|
||||
:onCancel="onCancel"
|
||||
:getData="getMainSystems"
|
||||
:formState="formState"
|
||||
/>
|
||||
<!-- <button
|
||||
@click.stop.prevent="isEditMode = !isEditMode"
|
||||
class="btn btn-sm btn-outline-success"
|
||||
>
|
||||
{{ isEditMode ? t("button.stop_edit") : t("button.start_edit") }}
|
||||
</button> -->
|
||||
</div>
|
||||
<ButtonConnectedGroup
|
||||
:items="items"
|
||||
:onclick="
|
||||
(e, item) => {
|
||||
if (!isEditMode) {
|
||||
changeActiveBtn(item);
|
||||
}
|
||||
}
|
||||
"
|
||||
:className="`flex w-full mt-2`"
|
||||
size="sm"
|
||||
color="info"
|
||||
>
|
||||
<template #buttonContent="{ item }">
|
||||
<span class="text-base">{{ item.title }}</span>
|
||||
<template v-if="isEditMode">
|
||||
<span
|
||||
class="ml-2 text-base text-warning"
|
||||
@click.stop.prevent="() => edit(item)"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'pencil-alt']"></FontAwesomeIcon>
|
||||
</span>
|
||||
<span
|
||||
class="text-base mx-1 text-error"
|
||||
@click.stop.prevent="() => deleteItem(item.id)"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'trash-alt']" />
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</ButtonConnectedGroup>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
106
src/views/AssetManagement/components/AssetMainListAddModal.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<script setup>
|
||||
import { ref, defineProps, inject } from "vue";
|
||||
import * as yup from "yup";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import { postAssetMainList } from "@/apis/asset";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import useSearchParam from "@/hooks/useSearchParam";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const storeBuild = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { openToast } = inject("app_toast");
|
||||
const { searchParams, changeParams } = useSearchParam();
|
||||
const props = defineProps({
|
||||
openModal: Function,
|
||||
onCancel: Function,
|
||||
getData: Function,
|
||||
formState: Object,
|
||||
isEdit: Boolean,
|
||||
});
|
||||
|
||||
let subSysSchema = yup.object({
|
||||
system_key: yup.string().required(t("button.required")), // 名稱
|
||||
system_value: yup.string().required(t("button.required")), // 代稱
|
||||
});
|
||||
|
||||
const { formErrorMsg, handleSubmit, handleErrorReset } =
|
||||
useFormErrorMessage(subSysSchema);
|
||||
|
||||
const onOk = async () => {
|
||||
const value = await handleSubmit(subSysSchema, props.formState);
|
||||
|
||||
const res = await postAssetMainList({
|
||||
...props.formState,
|
||||
id: props.formState ? props.formState.id : 0,
|
||||
building_guid:storeBuild.selectedBuilding?.building_guid || null,
|
||||
});
|
||||
|
||||
if (res.isSuccess) {
|
||||
props.getData();
|
||||
onReset();
|
||||
} else {
|
||||
openToast("error", res.msg);
|
||||
}
|
||||
};
|
||||
|
||||
const onReset = () => {
|
||||
handleErrorReset(); // 重置錯誤訊息
|
||||
props.onCancel(); // 調用父層的 onCancel
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <button class="btn btn-sm btn-success" @click.stop.prevent="openModal">
|
||||
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||
</button> -->
|
||||
<Modal
|
||||
id="asset_add_main_item"
|
||||
:title="
|
||||
props.formState?.id
|
||||
? t('assetManagement.edit_system_category')
|
||||
: t('assetManagement.add_system_category')
|
||||
"
|
||||
:onCancel="onReset"
|
||||
:width="300"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form" class="mt-5 flex flex-col items-center">
|
||||
<Input name="system_key" :value="formState">
|
||||
<template #topLeft>{{ $t("assetManagement.system_name") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.system_key }}
|
||||
</span></template
|
||||
>
|
||||
</Input>
|
||||
<Input name="system_value" :value="formState" :readonly="Boolean(props.formState?.id)">
|
||||
<template #topLeft>{{ $t("assetManagement.system_value") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.system_value }}
|
||||
</span></template
|
||||
>
|
||||
</Input>
|
||||
</form>
|
||||
</template>
|
||||
<template #modalAction>
|
||||
<button
|
||||
type="reset"
|
||||
class="btn btn-outline-success mr-2"
|
||||
@click.prevent="onReset"
|
||||
>
|
||||
{{ $t("button.cancel") }}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-outline-success"
|
||||
@click.prevent="onOk"
|
||||
>
|
||||
{{ $t("button.submit") }}
|
||||
</button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -1,15 +1,17 @@
|
||||
<script setup>
|
||||
import { getAssetSubList, deleteAssetSubItem } from "@/apis/asset";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { ref, onMounted, watch, inject } from "vue";
|
||||
import useSearchParam from "@/hooks/useSearchParam";
|
||||
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||
import AssetSubListAddModal from "./AssetSubListAddModal.vue";
|
||||
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const { searchParams, changeParams } = useSearchParam();
|
||||
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
|
||||
|
||||
const getSubSystems = async () => {
|
||||
const res = await getAssetSubList();
|
||||
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||
const isEditMode = ref(false);
|
||||
const getSubSystems = async (id) => {
|
||||
const res = await getAssetSubList(id);
|
||||
const sub = res.data.map((d, index) => ({
|
||||
...d,
|
||||
title: d.system_key,
|
||||
@ -21,60 +23,115 @@ const getSubSystems = async () => {
|
||||
setItems(sub);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getSubSystems();
|
||||
});
|
||||
onMounted(() => {});
|
||||
|
||||
watch(selectedBtn, (newValue) => {
|
||||
changeParams({ subSys_id: newValue.key });
|
||||
if (newValue && newValue.key) {
|
||||
changeParams({
|
||||
...searchParams.value,
|
||||
subSys_id: newValue.key,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const editRecord = ref(null);
|
||||
// 編輯 modal
|
||||
const openModal = () => {
|
||||
asset_add_sub_item.showModal();
|
||||
};
|
||||
const onCancel = () => {
|
||||
editRecord.value = null;
|
||||
asset_add_sub_item.close();
|
||||
};
|
||||
watch(
|
||||
() => searchParams,
|
||||
(newValue) => {
|
||||
if (newValue.value.mainSys_id && !newValue.value.subSys_id) {
|
||||
getSubSystems(parseInt(newValue.value.mainSys_id));
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
const formState = ref({
|
||||
id: 0,
|
||||
system_key: "",
|
||||
system_value: "",
|
||||
system_parent_id: 0,
|
||||
file: [],
|
||||
});
|
||||
|
||||
const edit = (item) => {
|
||||
editRecord.value = item;
|
||||
openModal();
|
||||
|
||||
|
||||
const openModal = (item) => {
|
||||
if (item.id) {
|
||||
formState.value = { ...item };
|
||||
|
||||
if (item.device_image) {
|
||||
const subFile = item
|
||||
? {
|
||||
name: item.device_image,
|
||||
src: item.device_image,
|
||||
ext: item.device_image?.split(".")[1],
|
||||
}
|
||||
: {};
|
||||
formState.value.file = [subFile];
|
||||
}
|
||||
} else {
|
||||
formState.value = {
|
||||
id: 0,
|
||||
system_key: "",
|
||||
system_value: "",
|
||||
system_parent_id: 0,
|
||||
file: [],
|
||||
};
|
||||
}
|
||||
asset_add_sub_item.showModal();
|
||||
};
|
||||
|
||||
const deleteItem = async (id) => {
|
||||
deleteAssetSubItem(id);
|
||||
getSubSystems();
|
||||
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||
await cancelToastOpen();
|
||||
const res = await deleteAssetSubItem(id);
|
||||
if (res.isSuccess) {
|
||||
openToast("success", t("msg.delete_success"));
|
||||
getSubSystems(parseInt(searchParams.value.mainSys_id));
|
||||
} else {
|
||||
openToast("error", res.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-4">
|
||||
<!-- <AssetSubListAddModal
|
||||
:openModal="openModal"
|
||||
:onCancel="onCancel"
|
||||
:getData="getSubList"
|
||||
:editRecord="editRecord"
|
||||
/> -->
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold ps-2 whitespace-nowrap">
|
||||
{{ $t("history.device_category") }} :
|
||||
</h2>
|
||||
<AssetSubListAddModal
|
||||
:openModal="openModal"
|
||||
:getData="getSubSystems"
|
||||
:formState="formState"
|
||||
/>
|
||||
<button
|
||||
@click.stop.prevent="isEditMode = !isEditMode"
|
||||
class="btn btn-sm btn-outline-success mr-3"
|
||||
>
|
||||
{{ isEditMode ? t("button.stop_edit") : t("button.start_edit") }}
|
||||
</button>
|
||||
</div>
|
||||
<ButtonConnectedGroup
|
||||
:items="items"
|
||||
:onclick="
|
||||
(e, item) => {
|
||||
changeActiveBtn(item);
|
||||
if (!isEditMode) {
|
||||
changeActiveBtn(item);
|
||||
}
|
||||
}
|
||||
"
|
||||
:className="`flex w-full mt-4`"
|
||||
:className="`flex w-full mt-2`"
|
||||
size="sm"
|
||||
color="info"
|
||||
>
|
||||
<template #buttonContent="{ item }">
|
||||
<span class="text-base">{{ item.title }}</span>
|
||||
<!-- <template v-if="!item.is_IOT">
|
||||
<template v-if="isEditMode">
|
||||
<span
|
||||
class="ml-2 text-base text-warning"
|
||||
@click.stop.prevent="() => edit(item)"
|
||||
@click.stop.prevent="() => openModal(item)"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'pencil-alt']"></FontAwesomeIcon>
|
||||
</span>
|
||||
@ -84,7 +141,7 @@ const deleteItem = async (id) => {
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'trash-alt']" />
|
||||
</span>
|
||||
</template> -->
|
||||
</template>
|
||||
</template>
|
||||
</ButtonConnectedGroup>
|
||||
</div>
|
||||
|
@ -2,19 +2,28 @@
|
||||
import { ref, defineProps, onMounted, watch } from "vue";
|
||||
import * as yup from "yup";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import useSearchParam from "@/hooks/useSearchParam";
|
||||
import { getAssetMainList, postAssetSubList } from "@/apis/asset";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { searchParams, changeParams } = useSearchParam();
|
||||
const props = defineProps({
|
||||
openModal: Function,
|
||||
onCancel: Function,
|
||||
getData: Function,
|
||||
editRecord: Object,
|
||||
formState: Object,
|
||||
});
|
||||
|
||||
const form = ref(null);
|
||||
const mainSystem = ref([]);
|
||||
|
||||
const updateFileList = (files) => {
|
||||
console.log("file", files);
|
||||
props.formState.file = files;
|
||||
};
|
||||
|
||||
const getMainSystems = async () => {
|
||||
const res = await getAssetMainList();
|
||||
const res = await getAssetMainList(store.selectedBuilding.building_guid);
|
||||
mainSystem.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
|
||||
@ -22,66 +31,72 @@ let subSysSchema = yup.object({
|
||||
system_key: yup.string().required(t("button.required")), // 名稱
|
||||
system_value: yup.string().required(t("button.required")), // 代稱
|
||||
system_parent_id: yup.number().required(t("button.required")), // 大類id
|
||||
file: yup.array(),
|
||||
});
|
||||
|
||||
const { formErrorMsg, handleSubmit, handleErrorReset } =
|
||||
useFormErrorMessage(subSysSchema);
|
||||
|
||||
const formState = ref({
|
||||
system_key: "",
|
||||
system_value: "",
|
||||
system_parent_id: 0,
|
||||
});
|
||||
|
||||
const resetForm = () => {
|
||||
formState.value = {
|
||||
const onCancel = () => {
|
||||
props.formState = {
|
||||
id: 0,
|
||||
system_key: "",
|
||||
system_value: "",
|
||||
system_parent_id: 0,
|
||||
file: [],
|
||||
};
|
||||
asset_add_sub_item.close();
|
||||
updateFileList([]);
|
||||
handleErrorReset();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getMainSystems();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.editRecord,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
formState.value = newValue;
|
||||
} else {
|
||||
resetForm();
|
||||
() => store.selectedBuilding,
|
||||
(newBuilding) => {
|
||||
if (newBuilding) {
|
||||
getMainSystems();
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const onOk = async () => {
|
||||
// 編輯
|
||||
const value = await handleSubmit(subSysSchema, formState.value);
|
||||
const value = await handleSubmit(subSysSchema, props.formState);
|
||||
console.log("props.formState", props.formState);
|
||||
|
||||
const res = await postAssetSubList({
|
||||
...formState.value,
|
||||
id: props.editRecord ? props.editRecord.id : 0,
|
||||
});
|
||||
const formData = new FormData(form.value);
|
||||
formData.delete("file");
|
||||
formData.append("id", props.formState.id);
|
||||
|
||||
if (props.formState.file[0]) {
|
||||
formData.append("file", props.formState.file[0]);
|
||||
}
|
||||
if (props.formState.Device_image) {
|
||||
formData.append("Device_image", props.formState.Device_image);
|
||||
}
|
||||
|
||||
const res = await postAssetSubList(formData);
|
||||
if (res.isSuccess) {
|
||||
props.getData();
|
||||
props.onCancel();
|
||||
props.getData(parseInt(searchParams.value.mainSys_id));
|
||||
onCancel();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="btn btn-sm btn-success mr-3" @click.stop.prevent="openModal">
|
||||
<button class="btn btn-sm btn-success" @click.stop.prevent="openModal">
|
||||
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||
</button>
|
||||
<Modal
|
||||
id="asset_add_sub_item"
|
||||
:title="t('assetManagement.add_category')"
|
||||
:open="open"
|
||||
:title="
|
||||
props.formState?.id
|
||||
? t('assetManagement.edit_device_category')
|
||||
: t('assetManagement.add_device_category')
|
||||
"
|
||||
:onCancel="onCancel"
|
||||
width="300"
|
||||
:width="300"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form" class="mt-5 flex flex-col items-center">
|
||||
@ -93,7 +108,11 @@ const onOk = async () => {
|
||||
</span></template
|
||||
>
|
||||
</Input>
|
||||
<Input name="system_value" :value="formState">
|
||||
<Input
|
||||
name="system_value"
|
||||
:value="formState"
|
||||
:readonly="Boolean(props.formState?.id)"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.system_value") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
@ -104,10 +123,11 @@ const onOk = async () => {
|
||||
<Select
|
||||
:options="mainSystem"
|
||||
Attribute="system_key"
|
||||
class="mr-5"
|
||||
class=""
|
||||
name="system_parent_id"
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info"
|
||||
:disabled="Boolean(props.formState?.id)"
|
||||
>
|
||||
<template #topLeft>{{
|
||||
$t("assetManagement.system_parent")
|
||||
@ -118,6 +138,14 @@ const onOk = async () => {
|
||||
</span></template
|
||||
>
|
||||
</Select>
|
||||
<Upload
|
||||
name="file"
|
||||
:fileList="formState.file || []"
|
||||
:getFileList="updateFileList"
|
||||
:multiple="false"
|
||||
>
|
||||
<template #topLeft>{{ $t("operation.upload_file") }}</template>
|
||||
</Upload>
|
||||
</form>
|
||||
</template>
|
||||
<template #modalAction>
|
||||
|
@ -4,48 +4,39 @@ import { onMounted, ref, watch, inject, provide, computed } from "vue";
|
||||
import useSearchParam from "@/hooks/useSearchParam";
|
||||
import AssetTableAddModal from "./AssetTableAddModal.vue";
|
||||
import { getOperationCompanyList } from "@/apis/operation";
|
||||
import { getAssetFloorList } from "@/apis/asset";
|
||||
import { postMQTTRefresh } from "@/apis/alert";
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const { openToast } = inject("app_toast");
|
||||
|
||||
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||
const { companyOptions, departmentList, floors } = inject(
|
||||
"asset_modal_options"
|
||||
);
|
||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const { searchParams, changeParams } = useSearchParam();
|
||||
|
||||
const companyOptions = ref([]);
|
||||
const getCompany = async () => {
|
||||
const res = await getOperationCompanyList();
|
||||
companyOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
|
||||
const floors = ref([]);
|
||||
const totalCoordinates = ref({});
|
||||
const getFloors = async () => {
|
||||
const res = await getAssetFloorList();
|
||||
floors.value = res.data[0]?.floors.map((d) => ({ ...d, key: d.floor_guid }));
|
||||
};
|
||||
|
||||
const tableData = ref([]);
|
||||
const getAssetData = async () => {
|
||||
totalCoordinates.value = {}; // 在獲取新數據之前清空 totalCoordinates
|
||||
const res = await getAssetList(searchParams.value?.subSys_id);
|
||||
if (res.isSuccess) {
|
||||
// 將 device_coordinate 推入對應樓層的座標陣列
|
||||
res.data.forEach(d => {
|
||||
res.data.forEach((d) => {
|
||||
const floorGuid = d.floor_guid;
|
||||
if (!totalCoordinates.value[floorGuid]) {
|
||||
totalCoordinates.value[floorGuid] = [];
|
||||
}
|
||||
totalCoordinates.value[floorGuid].push(d.device_coordinate);
|
||||
});
|
||||
|
||||
tableData.value = res.data.map((d) => ({
|
||||
...d,
|
||||
key: d.id,
|
||||
floor: floors.value.find(({ floor_guid }) => d.floor_guid === floor_guid)
|
||||
?.full_name,
|
||||
company: companyOptions.value.find(({ id }) => d.operation_id === id),
|
||||
department: departmentList.value.find(({ id }) => d.department_id === id)
|
||||
?.name,
|
||||
buying_date: d?.buying_date
|
||||
? dayjs(d?.buying_date).format("YYYY-MM-DD")
|
||||
: "",
|
||||
@ -56,18 +47,25 @@ const getAssetData = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const refreshMQTT = async () => {
|
||||
const res = await postMQTTRefresh();
|
||||
if (res.isSuccess) {
|
||||
openToast("success", t("msg.mqtt_refresh"));
|
||||
} else {
|
||||
openToast("error", res.msg, "#outliers_add_table_item");
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getCompany();
|
||||
await getFloors();
|
||||
getAssetData();
|
||||
});
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
title: t("assetManagement.device_number"),
|
||||
key: "device_number",
|
||||
class: "break-all",
|
||||
},
|
||||
// {
|
||||
// title: t("assetManagement.device_number"),
|
||||
// key: "device_number",
|
||||
// class: "break-all",
|
||||
// },
|
||||
{
|
||||
title: t("assetManagement.device_name"),
|
||||
key: "full_name",
|
||||
@ -84,6 +82,11 @@ const columns = computed(() => [
|
||||
filter: true,
|
||||
sort: true,
|
||||
},
|
||||
{
|
||||
title: t("assetManagement.department"),
|
||||
key: "department",
|
||||
filter: true,
|
||||
},
|
||||
{
|
||||
title: t("assetManagement.device_coordinate"),
|
||||
key: "device_coordinate",
|
||||
@ -122,6 +125,8 @@ watch(
|
||||
(newValue) => {
|
||||
if (newValue.value?.subSys_id) {
|
||||
getAssetData();
|
||||
} else {
|
||||
tableData.value = [];
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -164,10 +169,16 @@ const edit = async (id) => {
|
||||
};
|
||||
|
||||
const remove = async (id) => {
|
||||
const res = await deleteAssetItem(id);
|
||||
if (res.isSuccess) {
|
||||
getAssetData();
|
||||
}
|
||||
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||
await cancelToastOpen();
|
||||
const res = await deleteAssetItem(id);
|
||||
if (res.isSuccess) {
|
||||
getAssetData();
|
||||
openToast("success", t("msg.delete_success"));
|
||||
} else {
|
||||
openToast("error", res.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
provide("asset_table_data", {
|
||||
@ -176,14 +187,21 @@ provide("asset_table_data", {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-start items-center mt-10">
|
||||
<h3 class="text-xl mr-5">{{ $t("assetManagement.device_list") }}</h3>
|
||||
<AssetTableAddModal
|
||||
:openModal="openModal"
|
||||
:onCancel="onCancel"
|
||||
:editRecord="editRecord"
|
||||
:getData="getAssetData"
|
||||
/>
|
||||
<div class="flex justify-between items-center mt-10">
|
||||
<div class="flex">
|
||||
<h3 class="text-xl mr-5">{{ $t("assetManagement.device_list") }}</h3>
|
||||
<AssetTableAddModal
|
||||
:openModal="openModal"
|
||||
:onCancel="onCancel"
|
||||
:editRecord="editRecord"
|
||||
:getData="getAssetData"
|
||||
/>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-add" @click.prevent="refreshMQTT">
|
||||
<font-awesome-icon :icon="['fas', 'cog']" />{{
|
||||
$t("alert.reorganization")
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
<Table :columns="columns" :dataSource="tableData" class="mt-3">
|
||||
<template #bodyCell="{ record, column, index }">
|
||||
@ -197,7 +215,7 @@ provide("asset_table_data", {
|
||||
<template v-else-if="column.key === 'oriFile'">
|
||||
<span v-if="record.oriFile.length === 0"></span>
|
||||
<template v-else>
|
||||
<span class="flex">
|
||||
<span class="flex flex-wrap gap-1">
|
||||
<a
|
||||
v-for="file in record.oriFile"
|
||||
:href="`${FILE_BASEURL}/${file?.file_url}`"
|
||||
|
@ -102,19 +102,18 @@ const closeModal = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="btn btn-sm btn-add mr-3" @click.stop.prevent="openModal">
|
||||
<button class="btn btn-sm btn-add mr-3" @click.stop.prevent="openModal" :disabled="!searchParams.subSys_id">
|
||||
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||
</button>
|
||||
<Modal
|
||||
id="asset_add_table_item"
|
||||
:title="editRecord?.main_id ? $t('assetManagement.edit_device') : $t('assetManagement.add_device')"
|
||||
:open="open"
|
||||
:onCancel="closeModal"
|
||||
width="1600"
|
||||
:width="1600"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form" class="grid grid-cols-5 gap-5">
|
||||
<div class="grid grid-cols-2 col-span-2">
|
||||
<div class="grid grid-cols-2 col-span-2 items-end">
|
||||
<AssetTableModalLeft :current_component_key="current_component_key" />
|
||||
</div>
|
||||
<div class="col-span-3">
|
||||
|
@ -2,21 +2,19 @@
|
||||
import { ref, inject, onBeforeMount, onMounted, watch } from "vue";
|
||||
import * as yup from "yup";
|
||||
import "yup-phone-lite";
|
||||
import AssetTableModalLeftInfoIoT from "./AssetTableModalLeftInfoIoT.vue";
|
||||
import AssetTableModalLeftInfoGraph from "./AssetTableModalLeftInfoGraph.vue";
|
||||
import { getOperationCompanyList } from "@/apis/operation";
|
||||
import useSearchParam from "@/hooks/useSearchParam";
|
||||
import OperationTableModal from "@/views/operation/components/OperationTableModal.vue";
|
||||
import AssetTableModalLeftInfoMQTT from "./AssetTableModalLeftInfoMQTT.vue";
|
||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
|
||||
const { searchParams, changeParams } = useSearchParam();
|
||||
const { updateLeftFields, formErrorMsg, formState } = inject(
|
||||
"asset_table_modal_form"
|
||||
);
|
||||
|
||||
const { companyOptions, iotSchemaOptions, elecTypeOptions, departmentList } = inject("asset_modal_options");
|
||||
const store = useUserInfoStore();
|
||||
let schema = {
|
||||
full_name: yup.string().nullable(true),
|
||||
operate_text: yup.string().nullable(true),
|
||||
@ -28,6 +26,15 @@ let schema = {
|
||||
.number()
|
||||
.transform((value) => (Number.isNaN(value) ? null : value))
|
||||
.nullable(true),
|
||||
response_schema_id: yup
|
||||
.number()
|
||||
.transform((value) => (Number.isNaN(value) ? null : value))
|
||||
.nullable(true),
|
||||
department_id: yup
|
||||
.number()
|
||||
.transform((value) => (Number.isNaN(value) ? null : value))
|
||||
.nullable(true),
|
||||
topic: yup.string().nullable(true),
|
||||
asset_number: yup.string().nullable(true),
|
||||
sub_device: yup.array().nullable(true),
|
||||
oriFile: yup.array().nullable(true),
|
||||
@ -41,7 +48,11 @@ onBeforeMount(() => {
|
||||
brand: "",
|
||||
device_model: "",
|
||||
operation_id: 0,
|
||||
response_schema_id: 0,
|
||||
department_id: 0,
|
||||
elec_type_id: null,
|
||||
asset_number: "",
|
||||
topic: "",
|
||||
sub_device: [],
|
||||
oriFile: [],
|
||||
buying_date: "",
|
||||
@ -80,28 +91,20 @@ watch(formState, (newValue) => {
|
||||
}
|
||||
});
|
||||
|
||||
const updateFileList = (files) => {
|
||||
formState.value = { ...formState.value, oriFile: files };
|
||||
};
|
||||
|
||||
const companyOptions = ref([]);
|
||||
const getCompany = async () => {
|
||||
const res = await getOperationCompanyList();
|
||||
companyOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
onMounted(() => {
|
||||
getCompany();
|
||||
});
|
||||
|
||||
const openCompanyAddModal = () => {
|
||||
changeParams({ ...searchParams.value, work_type: 3 }); // 開啟company Add modal
|
||||
operation_action_item.showModal();
|
||||
};
|
||||
watch(
|
||||
() => iotSchemaOptions.value,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
formState.value.response_schema_id = newVal[0].id;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- information -->
|
||||
<Input :value="formState" width="270" name="full_name">
|
||||
<Input :value="formState" width="290" name="full_name">
|
||||
<template #topLeft>{{ $t("assetManagement.device_name") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
@ -109,15 +112,23 @@ const openCompanyAddModal = () => {
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
<Input :value="formState" width="270" name="operate_text">
|
||||
<template #topLeft>Mac</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.operate_text }}
|
||||
</span></template
|
||||
></Input
|
||||
<div class="flex items-center w-72">
|
||||
<Select
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info"
|
||||
name="department_id"
|
||||
Attribute="name"
|
||||
:options="departmentList"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.department") }}</template>
|
||||
</Select>
|
||||
</div>
|
||||
<Input
|
||||
:value="formState"
|
||||
width="290"
|
||||
name="device_number"
|
||||
v-if="store.user.user_name == 'webUser'"
|
||||
>
|
||||
<Input :value="formState" width="270" name="device_number">
|
||||
<template #topLeft
|
||||
>Tag_Name ({{ $t("assetManagement.fill_text") }})</template
|
||||
>
|
||||
@ -127,28 +138,31 @@ const openCompanyAddModal = () => {
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
<!-- <Input :value="formState" width="270" name="floor_guid">
|
||||
<template #topLeft>設備位置(樓層 / 區域)</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.floor_guid }}
|
||||
</span></template
|
||||
></Input
|
||||
> -->
|
||||
<Input
|
||||
:value="formState"
|
||||
width="270"
|
||||
name="device_coordinate"
|
||||
:disabled="true"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.device_coordinate") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.device_coordinate }}
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
<Input :value="formState" width="270" name="asset_number">
|
||||
<div class="flex items-center w-72">
|
||||
<Select
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info"
|
||||
name="response_schema_id"
|
||||
Attribute="name"
|
||||
:options="iotSchemaOptions"
|
||||
:required="true"
|
||||
>
|
||||
<template #topLeft>IoT</template>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="flex items-center w-72" v-if="searchParams.mainSys_id==26">
|
||||
<Select
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info"
|
||||
name="elec_type_id"
|
||||
Attribute="name"
|
||||
:options="elecTypeOptions"
|
||||
:required="true"
|
||||
>
|
||||
<template #topLeft>{{$t("energy.electricity_classification")}}</template>
|
||||
</Select>
|
||||
</div>
|
||||
<Input :value="formState" width="290" name="asset_number">
|
||||
<template #topLeft>{{ $t("assetManagement.asset_number") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
@ -156,7 +170,7 @@ const openCompanyAddModal = () => {
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
<DateGroup :items="buying_date" width="270" :withLine="false">
|
||||
<DateGroup :items="buying_date" width="290" :withLine="false">
|
||||
<template #topLeft>{{ $t("assetManagement.buying_date") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
@ -164,7 +178,7 @@ const openCompanyAddModal = () => {
|
||||
</span></template
|
||||
>
|
||||
</DateGroup>
|
||||
<Input :value="formState" width="270" name="brand">
|
||||
<Input :value="formState" width="290" name="brand">
|
||||
<template #topLeft>{{ $t("assetManagement.brand") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
@ -172,7 +186,7 @@ const openCompanyAddModal = () => {
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
<Input :value="formState" width="270" name="device_model">
|
||||
<Input :value="formState" width="290" name="device_model">
|
||||
<template #topLeft>{{ $t("assetManagement.modal") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
@ -180,7 +194,7 @@ const openCompanyAddModal = () => {
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
<div class="flex items-center col-span-2">
|
||||
<div class="flex items-center w-72">
|
||||
<Select
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info"
|
||||
@ -191,28 +205,8 @@ const openCompanyAddModal = () => {
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.company") }}</template>
|
||||
</Select>
|
||||
<OperationTableModal type="asset" />
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-add ml-2 mt-7"
|
||||
@click="openCompanyAddModal"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'plus']" />
|
||||
{{ $t("button.add") }}
|
||||
</button>
|
||||
</div>
|
||||
<AssetTableModalLeftInfoGraph />
|
||||
<!-- <Upload
|
||||
name="oriFile"
|
||||
:fileList="formState.oriFile"
|
||||
:getFileList="updateFileList"
|
||||
:multiple="true"
|
||||
class="col-span-2"
|
||||
:baseUrl="FILE_BASEURL"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.oriFile") }}</template>
|
||||
</Upload> -->
|
||||
<AssetTableModalLeftInfoIoT />
|
||||
<AssetTableModalLeftInfoMQTT />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -0,0 +1,161 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, inject, onBeforeMount, watch, computed } from "vue";
|
||||
import {
|
||||
getDepartmentList,
|
||||
postDepartmentList,
|
||||
deleteDepartmentItem,
|
||||
} from "@/apis/asset";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import * as yup from "yup";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||
const { formState } = inject("asset_table_modal_form");
|
||||
|
||||
const selectedOption = ref("add");
|
||||
|
||||
const DeptFormState = ref({ id: 0, name: "" });
|
||||
const departmentList = ref([]);
|
||||
|
||||
const getDepartment = async () => {
|
||||
const res = await getDepartmentList();
|
||||
departmentList.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDepartment();
|
||||
});
|
||||
|
||||
// modal
|
||||
const openModal = () => {
|
||||
if (selectedOption.value === "add") {
|
||||
DeptFormState.value = {
|
||||
id: 0,
|
||||
name: "",
|
||||
};
|
||||
} else if (selectedOption.value === "edit") {
|
||||
const dept = departmentList.value.find(
|
||||
(d) => d.id === formState.value.department_id
|
||||
);
|
||||
if (dept) {
|
||||
DeptFormState.value = {
|
||||
id: dept.id,
|
||||
name: dept.name,
|
||||
};
|
||||
}
|
||||
}
|
||||
asset_add_dept.showModal();
|
||||
};
|
||||
|
||||
const form = ref(null);
|
||||
|
||||
const deptScheme = yup.object({
|
||||
name: yup.string().required(t("button.required")),
|
||||
});
|
||||
|
||||
const { formErrorMsg, handleSubmit, handleErrorReset, updateScheme } =
|
||||
useFormErrorMessage(deptScheme);
|
||||
const onOk = async () => {
|
||||
const value = await handleSubmit(deptScheme, DeptFormState.value);
|
||||
|
||||
const res = await postDepartmentList(value);
|
||||
if (res.isSuccess) {
|
||||
getDepartment();
|
||||
onCancel();
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
openToast(
|
||||
"warning",
|
||||
t("msg.sure_to_delete"),
|
||||
"#asset_add_table_item",
|
||||
async () => {
|
||||
await cancelToastOpen();
|
||||
const res = await deleteDepartmentItem(formState.value.department_id);
|
||||
if (res.isSuccess) {
|
||||
getDepartment();
|
||||
openToast("success", t("msg.delete_success"), "#asset_add_table_item");
|
||||
} else {
|
||||
openToast("error", res.msg, "#asset_add_table_item");
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
DeptFormState.value = {
|
||||
id: 0,
|
||||
name: "",
|
||||
};
|
||||
asset_add_dept.close();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div className="join w-72 mb-4">
|
||||
<Select
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info rounded-r-none"
|
||||
name="department_id"
|
||||
Attribute="name"
|
||||
:options="departmentList"
|
||||
:isBottomLabelExist="false"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.department") }}</template>
|
||||
</Select>
|
||||
<select
|
||||
v-model="selectedOption"
|
||||
className="select border-info focus-within:border-info join-item mt-11"
|
||||
>
|
||||
<option value="add" selected>{{ $t("button.add") }}</option>
|
||||
<option value="edit">{{ $t("button.edit") }}</option>
|
||||
<option value="delete">{{ $t("button.delete") }}</option>
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success join-item mt-11"
|
||||
@click="selectedOption === 'delete' ? onDelete() : openModal()"
|
||||
:aria-label="$t('button.submit')"
|
||||
>
|
||||
{{ $t("button.submit") }}
|
||||
</button>
|
||||
</div>
|
||||
<Modal
|
||||
id="asset_add_dept"
|
||||
:title="t('assetManagement.department')"
|
||||
:onCancel="onCancel"
|
||||
:width="400"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form">
|
||||
<Input :value="DeptFormState" width="270" name="name">
|
||||
<template #topLeft>{{
|
||||
$t("assetManagement.department_name")
|
||||
}}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.name }}
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
</form>
|
||||
</template>
|
||||
<template #modalAction>
|
||||
<button
|
||||
type="reset"
|
||||
class="btn btn-outline-success mr-2"
|
||||
@click.prevent="onCancel"
|
||||
>
|
||||
{{ $t("button.cancel") }}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-outline-success" @click="onOk">
|
||||
{{ $t("button.submit") }}
|
||||
</button>
|
||||
</template></Modal
|
||||
>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -138,7 +138,7 @@ onMounted(async () => {
|
||||
id="asset_add_graph_item"
|
||||
:title="t('graphManagement.title')"
|
||||
:onCancel="onCancel"
|
||||
width="500"
|
||||
:width="500"
|
||||
>
|
||||
<template #modalContent>
|
||||
<ul class="menu bg-base-200 rounded-box text-lg w-full mt-3">
|
||||
|
@ -44,6 +44,7 @@ const modalColumns = computed(() => [
|
||||
{
|
||||
title: "tag",
|
||||
key: "device_name",
|
||||
filter: true
|
||||
},
|
||||
{
|
||||
title: t("assetManagement.point"),
|
||||
@ -64,7 +65,7 @@ const getPoint = async (sub_system_tag) => {
|
||||
setPoints(
|
||||
res.data.map((d, index) => ({
|
||||
...d,
|
||||
title: d.points,
|
||||
title: d.full_name,
|
||||
key: d.points,
|
||||
active: false,
|
||||
}))
|
||||
@ -224,7 +225,7 @@ const deleteItem = (value) => {
|
||||
id="asset_add_IoT_item"
|
||||
:title="t('assetManagement.associated_device')"
|
||||
:onCancel="onCancel"
|
||||
width="900"
|
||||
:width="900"
|
||||
>
|
||||
<template #modalContent>
|
||||
<ButtonGroup
|
||||
|
@ -0,0 +1,185 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, inject, watch, computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { postMQTTpublish } from "@/apis/asset";
|
||||
import mqtt from "mqtt";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const { t } = useI18n();
|
||||
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||
const { formState } = inject("asset_table_modal_form");
|
||||
const BASEURL = import.meta.env.VITE_MQTT_BASEURL;
|
||||
// MQTT相關
|
||||
const mqttClient = ref(null); // MQTT客戶端
|
||||
const receivedMessages = ref([]); // 儲存接收到的訊息
|
||||
const countdown = ref(60); // 倒計時初始為 60 秒
|
||||
let timer = null; // 記錄計時器
|
||||
|
||||
const openModal = () => {
|
||||
if (!mqttClient.value) {
|
||||
connectMqtt();
|
||||
}
|
||||
mqtt_test.showModal();
|
||||
startCountdown(); // 開始倒計時
|
||||
};
|
||||
|
||||
const connectMqtt = () => {
|
||||
const topic = formState.value.topic || ""; // 取得主題
|
||||
const mqttHost = `${BASEURL}`;
|
||||
const protocol = "wss"; // 根據伺服器配置,需要設置為 "ws" 或 "wss"
|
||||
mqttClient.value = mqtt.connect(mqttHost, {
|
||||
protocol,
|
||||
reconnectPeriod: 1000, // 每秒嘗試重新連線
|
||||
username: "admin", // MQTT 帳號
|
||||
password: "mjmadmin@99", // MQTT 密碼
|
||||
port: 443,
|
||||
});
|
||||
|
||||
mqttClient.value.on("connect", () => {
|
||||
console.log("MQTT 已連接");
|
||||
if (topic) {
|
||||
mqttClient.value.subscribe(topic, (err) => {
|
||||
if (!err) {
|
||||
console.log(`已訂閱主題: ${topic}`);
|
||||
} else {
|
||||
console.error("訂閱失敗: ", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
mqttClient.value.on("message", (topic, message) => {
|
||||
// 儲存接收到的訊息
|
||||
const now = dayjs(); // 使用 dayjs() 取得當前時間
|
||||
const timestamp = now.format("YYYY-MM-DD HH:mm:ss");
|
||||
|
||||
receivedMessages.value.push({
|
||||
topic,
|
||||
message: message.toString(),
|
||||
timestamp: timestamp,
|
||||
});
|
||||
clearInterval(timer); // 收到訊息後清除倒計時
|
||||
});
|
||||
|
||||
mqttClient.value.on("error", (err) => {
|
||||
console.error("MQTT 連線錯誤: ", err);
|
||||
});
|
||||
};
|
||||
|
||||
const startCountdown = () => {
|
||||
if (timer) return; // 防止重複啟動計時器
|
||||
timer = setInterval(() => {
|
||||
if (countdown.value > 0) {
|
||||
countdown.value--;
|
||||
} else {
|
||||
onCancel(); // 1分鐘後如果沒有收到訊息則觸發 onCancel
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
receivedMessages.value = [];
|
||||
mqtt_test.close();
|
||||
|
||||
// 斷開 MQTT 連線
|
||||
if (mqttClient.value) {
|
||||
mqttClient.value.end();
|
||||
mqttClient.value = null;
|
||||
}
|
||||
|
||||
// 重置倒計時
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null; // 清除計時器引用
|
||||
}
|
||||
countdown.value = 60;
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const Topic = formState.value.topic;
|
||||
let Payload = "";
|
||||
try {
|
||||
Payload = JSON.stringify(JSON.parse(formState.value.publish_message));
|
||||
} catch (e) {
|
||||
openToast("error", t("msg.incorrect_format"), "#asset_add_table_item");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await postMQTTpublish({ Topic, Payload });
|
||||
if (res.isSuccess) {
|
||||
openToast("success", t("msg.send_successfully"), "#asset_add_table_item");
|
||||
} else {
|
||||
openToast("error", res.msg, "#asset_add_table_item");
|
||||
}
|
||||
} catch (error) {
|
||||
openToast("error", t("setting.mqtt_send_error"), "#asset_add_table_item");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex col-span-2 pb-5">
|
||||
<Input :value="formState" name="topic">
|
||||
<template #topLeft>MQTT subscribe topic</template>
|
||||
</Input>
|
||||
<button type="button" class="btn btn-add mt-11 ms-1" @click="openModal">
|
||||
<font-awesome-icon :icon="['fas', 'cog']" />
|
||||
Test
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col col-span-2 border-t-gray-400 border-t py-5">
|
||||
<Input :value="formState" name="topic">
|
||||
<template #topLeft>MQTT publish topic</template>
|
||||
</Input>
|
||||
<Textarea :value="formState" name="publish_message">
|
||||
<template #topLeft>MQTT messages</template>
|
||||
</Textarea>
|
||||
<button type="button" class="btn btn-add mt-6 w-24" @click="onSubmit">
|
||||
<font-awesome-icon :icon="['far', 'paper-plane']" />
|
||||
Send
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Modal id="mqtt_test" title="MQTT Topic" :onCancel="onCancel" :width="400">
|
||||
<template #modalContent>
|
||||
<!-- 顯示接收到的訊息 -->
|
||||
<div v-if="receivedMessages.length > 0" class="overflow-y-auto h-96">
|
||||
<ul>
|
||||
<li
|
||||
v-for="(message, index) in receivedMessages"
|
||||
:key="index"
|
||||
class="bg-base-200 rounded-md text-wrap shadow shadow-slate-400 p-4 my-2 me-2"
|
||||
>
|
||||
<strong class="text-base block text-info mb-2"
|
||||
>{{ message.topic }} :</strong
|
||||
>
|
||||
<p class="text-sm break-words">{{ message.message }}</p>
|
||||
<p class="text-xs text-slate-200 pt-2">
|
||||
<FontAwesomeIcon :icon="['fas', 'clock']" class="me-1" />
|
||||
{{ message.timestamp }}
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 顯示 loading 和倒計時 -->
|
||||
<p v-else class="text-center mt-20">
|
||||
<Loading />
|
||||
<br />
|
||||
<span class="text-base">{{ countdown }} seconds</span>
|
||||
</p>
|
||||
</template>
|
||||
<template #modalAction>
|
||||
<button
|
||||
type="reset"
|
||||
class="btn btn-outline-success mr-2"
|
||||
@click.prevent="onCancel"
|
||||
>
|
||||
{{ t("button.cancel") }}
|
||||
</button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -1,13 +1,9 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, inject, onBeforeMount, watch, computed } from "vue";
|
||||
import EffectScatter from "@/components/chart/EffectScatter.vue";
|
||||
import {
|
||||
getAssetFloorList,
|
||||
postAssetFloor,
|
||||
deleteAssetFloor,
|
||||
} from "@/apis/asset";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import AssetTableModalLeftInfoIoT from "./AssetTableModalLeftInfoIoT.vue";
|
||||
import AssetTableModalLeftInfoGraph from "./AssetTableModalLeftInfoGraph.vue";
|
||||
import * as yup from "yup";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useI18n } from "vue-i18n";
|
||||
@ -15,6 +11,7 @@ import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const { totalCoordinates } = inject("asset_table_data");
|
||||
const { floors } = inject("asset_modal_options");
|
||||
const { updateRightFields, formErrorMsg, formState } = inject(
|
||||
"asset_table_modal_form"
|
||||
);
|
||||
@ -33,17 +30,20 @@ onBeforeMount(() => {
|
||||
|
||||
const asset_floor_chart = ref(null);
|
||||
const currentFloor = ref(null);
|
||||
const selectedOption = ref("add");
|
||||
const parsedCoordinates = ref(null);
|
||||
|
||||
const defaultOption = (map, data = []) => {
|
||||
// 生成坐標數據,根據坐標值的不同設置不同顏色
|
||||
const formattedData = data.map((coordinate) => {
|
||||
const coordString = JSON.stringify(coordinate);
|
||||
const coordString = JSON.stringify(coordinate);
|
||||
return {
|
||||
name: coordString,
|
||||
name: coordString,
|
||||
value: coordinate,
|
||||
itemStyle: {
|
||||
color: coordString === formState.value.device_coordinate ? "#0000FF" : "#b02a02",
|
||||
color:
|
||||
coordString === formState.value.device_coordinate
|
||||
? "#0000FF"
|
||||
: "#b02a02",
|
||||
},
|
||||
};
|
||||
});
|
||||
@ -72,26 +72,25 @@ const defaultOption = (map, data = []) => {
|
||||
|
||||
watch(currentFloor, (newValue) => {
|
||||
if (newValue?.floor_map_name) {
|
||||
const coordinates = totalCoordinates.value[newValue.floor_guid] || [];
|
||||
const parsedCoordinates = coordinates.map((coord) => {
|
||||
return JSON.parse(coord);
|
||||
});
|
||||
const coordinates =
|
||||
totalCoordinates.value?.[newValue.floor_guid]?.filter(
|
||||
(coord) => coord !== ""
|
||||
) || [];
|
||||
|
||||
parsedCoordinates.value =
|
||||
coordinates.length > 0
|
||||
? coordinates.map((coord) => JSON.parse(coord))
|
||||
: [];
|
||||
|
||||
asset_floor_chart.value.updateSvg(
|
||||
{
|
||||
full_name: newValue?.floor_map_name,
|
||||
path: `${FILE_BASEURL}/${newValue?.floor_map_url}.svg`,
|
||||
full_name: newValue.floor_map_name,
|
||||
path: `${FILE_BASEURL}/${newValue.floor_map_url}.svg`,
|
||||
},
|
||||
defaultOption(newValue?.floor_map_name, parsedCoordinates)
|
||||
defaultOption(newValue.floor_map_name, parsedCoordinates.value)
|
||||
);
|
||||
}
|
||||
});
|
||||
const floors = ref([]);
|
||||
|
||||
const getFloors = async () => {
|
||||
const res = await getAssetFloorList();
|
||||
floors.value = res.data[0]?.floors.map((d) => ({ ...d, key: d.floor_guid }));
|
||||
};
|
||||
|
||||
watch(
|
||||
formState,
|
||||
@ -114,126 +113,39 @@ const getCoordinate = (position) => {
|
||||
formState.value.device_coordinate = JSON.stringify(position);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getFloors();
|
||||
});
|
||||
|
||||
// modal
|
||||
const openModal = () => {
|
||||
if (selectedOption.value === "add") {
|
||||
FloorFormState.value = {
|
||||
full_name: "",
|
||||
floorFile: [],
|
||||
};
|
||||
} else if (selectedOption.value === "edit") {
|
||||
const floor = floors.value.find(
|
||||
(f) => f.floor_guid === formState.value.floor_guid
|
||||
);
|
||||
if (floor) {
|
||||
console.log("floor", floor);
|
||||
FloorFormState.value = {
|
||||
full_name: floor.full_name,
|
||||
floorFile: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
asset_add_floor.showModal();
|
||||
};
|
||||
|
||||
const form = ref(null);
|
||||
const FloorFormState = ref({
|
||||
full_name: "",
|
||||
floorFile: [],
|
||||
});
|
||||
|
||||
const floorScheme = yup.object({
|
||||
full_name: yup.string().required(t("button.required")),
|
||||
floorFile: yup.array(),
|
||||
});
|
||||
|
||||
const updateFileList = (files) => {
|
||||
console.log("file", files);
|
||||
FloorFormState.value.floorFile = files;
|
||||
};
|
||||
|
||||
const {
|
||||
formErrorMsg: floorFormErrorMsg,
|
||||
handleSubmit,
|
||||
handleErrorReset,
|
||||
updateScheme,
|
||||
} = useFormErrorMessage(floorScheme);
|
||||
const onOk = async () => {
|
||||
const value = handleSubmit(floorScheme, FloorFormState.value);
|
||||
const formData = new FormData(form.value);
|
||||
formData.append("floor_guid", currentFloor.value.floor_guid);
|
||||
formData.append("building_tag", store.selectedBuilding.building_tag);
|
||||
formData.append("initMapName", FloorFormState.value.floorFile[0].name);
|
||||
formData.append("mapFile", FloorFormState.value.floorFile[0]);
|
||||
formData.delete("floorFile");
|
||||
for (let [key, value] of formData) {
|
||||
console.log(key, value);
|
||||
}
|
||||
|
||||
const res = await postAssetFloor(formData);
|
||||
if (res.isSuccess) {
|
||||
getFloors();
|
||||
onCancel();
|
||||
}
|
||||
};
|
||||
const onDelete = async () => {
|
||||
console.log("guild", formState.value.floor_guid);
|
||||
const res = await deleteAssetFloor({
|
||||
floor_guid: formState.value.floor_guid,
|
||||
});
|
||||
if (res.isSuccess) {
|
||||
getFloors();
|
||||
}
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
FloorFormState.value = {
|
||||
full_name: "",
|
||||
floorFile: [],
|
||||
};
|
||||
asset_add_floor.close();
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 平面圖 -->
|
||||
|
||||
<div class="flex items-center justify-between mb-5">
|
||||
<div className="join">
|
||||
<Select
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info rounded-r-none"
|
||||
name="floor_guid"
|
||||
Attribute="full_name"
|
||||
:options="floors"
|
||||
:isBottomLabelExist="false"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.floor") }}</template>
|
||||
</Select>
|
||||
<select
|
||||
v-model="selectedOption"
|
||||
className="select border-info focus-within:border-info join-item mt-11"
|
||||
>
|
||||
<option value="add" selected>{{ $t("button.add") }}</option>
|
||||
<option value="edit">{{ $t("button.edit") }}</option>
|
||||
<option value="delete">{{ $t("button.delete") }}</option>
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success join-item mt-11"
|
||||
@click="selectedOption === 'delete' ? onDelete() : openModal()"
|
||||
:aria-label="$t('button.submit')"
|
||||
>
|
||||
{{ $t("button.submit") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-4 mb-5">
|
||||
<Select
|
||||
:value="formState"
|
||||
selectClass="border-info focus-within:border-info"
|
||||
name="floor_guid"
|
||||
Attribute="full_name"
|
||||
:options="floors"
|
||||
:isBottomLabelExist="false"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.floor") }}</template>
|
||||
</Select>
|
||||
<Input
|
||||
:value="formState"
|
||||
width="270"
|
||||
name="device_coordinate"
|
||||
:disabled="true"
|
||||
>
|
||||
<template #topLeft>{{
|
||||
$t("assetManagement.device_coordinate")
|
||||
}}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.device_coordinate }}
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div class="relative min-h-[70vh]">
|
||||
<EffectScatter
|
||||
id="asset_floor_chart"
|
||||
ref="asset_floor_chart"
|
||||
@ -247,51 +159,13 @@ const onCancel = () => {
|
||||
/>
|
||||
<div
|
||||
v-if="!currentFloor?.floor_map_url"
|
||||
class="absolute top-0 left-0 flex justify-center items-center min-h-[500px] w-full border border-stone-900 shadow-lg bg-sub-success bg-opacity-25 rounded-md"
|
||||
class="absolute top-0 left-0 flex justify-center items-center min-h-[70vh] w-full border border-stone-900 shadow-lg bg-sub-success bg-opacity-25 rounded-md"
|
||||
>
|
||||
<p class="text-2xl">{{ $t("assetManagement.add_floor_text") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<Modal
|
||||
id="asset_add_floor"
|
||||
:title="t('assetManagement.floor_plan')"
|
||||
:onCancel="onCancel"
|
||||
width="400"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form">
|
||||
<Input :value="FloorFormState" width="270" name="full_name">
|
||||
<template #topLeft>{{ $t("assetManagement.system_name") }}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ floorFormErrorMsg.full_name }}
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
<Upload
|
||||
name="floorFile"
|
||||
:fileList="FloorFormState.floorFile"
|
||||
:getFileList="updateFileList"
|
||||
:multiple="false"
|
||||
class="col-span-2"
|
||||
>
|
||||
<template #topLeft>{{ $t("assetManagement.oriFile") }}</template>
|
||||
</Upload>
|
||||
</form>
|
||||
</template>
|
||||
<template #modalAction>
|
||||
<button
|
||||
type="reset"
|
||||
class="btn btn-outline-success mr-2"
|
||||
@click.prevent="onCancel"
|
||||
>
|
||||
{{ $t("button.cancel") }}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-outline-success" @click="onOk">
|
||||
{{ $t("button.submit") }}
|
||||
</button>
|
||||
</template></Modal
|
||||
>
|
||||
<AssetTableModalLeftInfoGraph />
|
||||
<AssetTableModalLeftInfoIoT />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|