This commit is contained in:
koko 2025-06-17 17:38:50 +08:00
commit 143a7ae061
302 changed files with 36471 additions and 0 deletions

4
.env.development Normal file
View File

@ -0,0 +1,4 @@
VITE_API_BASEURL = "https://ibms-Empower-api.production.mjmtech.com.tw"
VITE_FILE_API_BASEURL = "https://ibms-Empower.production.mjmtech.com.tw"
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
VITE_FORGE_BASEURL = "https://ibms-Empower.production.mjmtech.com.tw/dist"

4
.env.production Normal file
View File

@ -0,0 +1,4 @@
VITE_API_BASEURL = "https://ibms-Empower-api.production.mjmtech.com.tw"
VITE_FILE_API_BASEURL = "https://ibms-Empower.production.mjmtech.com.tw"
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
VITE_FORGE_BASEURL = "https://ibms-Empower.production.mjmtech.com.tw/dist"

3
.env.staging Normal file
View File

@ -0,0 +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"

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# 新創賦能
Node version: 18

26
index.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<!-- @noSnoop -->
<html lang="en" data-theme="dracula">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<link
rel="stylesheet"
href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.css"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>新創賦能</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
type="text/javascript"
src="/module/js/com/tridium/js/ext/require/require.min.js?"
></script> -->
</head>
<body>
<div id="app"></div>
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.js"></script>
<script type="module" src="/src/main.js"></script>
</body>
</html>

6457
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

51
package.json Normal file
View File

@ -0,0 +1,51 @@
{
"name": "ibms_netzero",
"version": "0.0.0",
"private": true,
"homepage": "/netzero",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons-vue": "^7.0.1",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/vue-fontawesome": "^3.0.5",
"@vuepic/vue-datepicker": "^8.0.0",
"ant-design-vue": "^4.0.7",
"axios": "^1.6.2",
"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"
},
"devDependencies": {
"@faker-js/faker": "^9.7.0",
"@vitejs/plugin-vue": "^4.4.0",
"autoprefixer": "^10.4.16",
"daisyui": "^4.4.17",
"postcss": "^8.4.31",
"sass": "^1.69.5",
"sass-loader": "^13.3.2",
"tailwindcss": "^3.3.5",
"unplugin-vue-components": "^0.26.0",
"vite": "^4.4.11",
"vite-plugin-svg-icons": "^2.0.1"
}
}

7
postcss.config.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = {
plugins: {
"postcss-import": {},
tailwindcss: {},
autoprefixer: {},
},
};

BIN
public/build_img.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

44
public/config.json Normal file
View File

@ -0,0 +1,44 @@
{
"heatmap": {
"temp": {
"range": [0, 50],
"color": ["#0023F5", "#FF1C05"],
"unit": "°C"
},
"humi": {
"range": [15, 95],
"color": ["#ADD8E6", "#00008B"],
"unit": "%"
},
"CO2": {
"range": [0, 5000],
"color": ["#FFDAB9", "#FF8C00"],
"unit": "ppm"
},
"CO": {
"range": [0, 1000],
"color": ["#FFFFE0", "#FFD700"],
"unit": "ppm"
},
"CH2O": {
"range": [0, 100],
"color": ["#90EE90", "#006400"],
"unit": "ppb"
},
"PM1": {
"range": [0, 20],
"color": ["#E6E6FA", "#800080"],
"unit": "µg/m³"
},
"PM2.5": {
"range": [0, 55],
"color": ["#FFB6C1", "#FF0000"],
"unit": "µg/m³"
},
"PM10": {
"range": [0, 150],
"color": ["#FFDDC1", "#FF1493"],
"unit": "µg/m³"
}
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

21
public/hotspot.svg Normal file
View File

@ -0,0 +1,21 @@
<svg width="164" height="164" viewBox="0 0 164 164" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<circle cx="81.7363" cy="81.8212" r="40" stroke-width="60" style="stroke:grey" />
</g>
<g filter="url(#filter0_d)">
<circle cx="81.7363" cy="81.8212" r="20" stroke="white" stroke-width="60"/>
</g>
<defs>
<filter id="filter0_d" x="0.174763" y="0.259602" width="163.123" height="163.123" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset/>
<feGaussianBlur stdDeviation="5.61135"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 938 B

23
public/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 34 KiB

15
public/setting.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
window.addEventListener("load", () => {
window.location.href = "/file/dist/index.html";
});
</script>
</body>
</html>

60
src/App.vue Normal file
View File

@ -0,0 +1,60 @@
<script setup>
import { RouterView } from "vue-router";
import Navbar from "./components/navbar/Navbar.vue";
import useUserInfoStore from "@/stores/useUserInfoStore";
import { ref, provide, onUnmounted, onMounted } from "vue";
const store = useUserInfoStore();
let isToastOpen = ref({
open: false,
content: "",
status: "info",
to: "body",
});
const cancelToastOpen = () => {
isToastOpen.value = {
open: false,
content: "",
};
};
const openToast = (status, content, to = "body", confirm = null) => {
isToastOpen.value = {
open: true,
content,
status,
to,
confirm,
};
};
provide("app_toast", { openToast, cancelToastOpen });
</script>
<template>
<Toast
:content="isToastOpen.content"
:open="isToastOpen.open"
:status="isToastOpen.status"
:cancel="cancelToastOpen"
:confirm="isToastOpen.confirm"
:to="isToastOpen.to"
/>
<div v-if="store.user.token" class="min-h-screen">
<Navbar />
<div class="px-3 lg:px-8 w-full relative app-container " style="min-height: calc(100vh - 6rem);">
<RouterView />
</div>
</div>
<div v-else class="min-h-screen"><RouterView /></div>
</template>
<style scoped>
header {
line-height: 1.5;
}
.logo {
display: block;
margin: 0 auto 1rem;
}
</style>

14
src/apis/account/api.js Normal file
View File

@ -0,0 +1,14 @@
export const GET_ACCOUNT_USERLIST_API = `/User/UserManagerList`;
export const GET_ACCOUNT_ROLELIST_API = `/User/RoleManagerList`;
export const GET_ACCOUNT_ROLEAUTHLIST_API = `/User/RoleAuthList`;
export const GET_ACCOUNT_ROLEAUTHPAGELIST_API = `/User/AuthPageListByVariable`;
// export const POST_ROLEAUTHLIST_API = `/User/SaveRoleAuth`;
export const POST_ACCOUNT_ROLE_API = `/User/SaveRoleAndAuth`;
export const DELETE_ACCOUNT_ROLE_API = `/User/DeleteOneRole`;
export const GET_ACCOUNT_USER_API = `/User/GetOneUser`;
export const POST_ACCOUNT_USER_API = `/User/SaveUser`;
export const DELETE_ACCOUNT_USER_API = `/User/DeleteOneUser`;

158
src/apis/account/index.js Normal file
View File

@ -0,0 +1,158 @@
import {
GET_ACCOUNT_USERLIST_API,
GET_ACCOUNT_ROLELIST_API,
GET_ACCOUNT_ROLEAUTHLIST_API,
GET_ACCOUNT_ROLEAUTHPAGELIST_API,
DELETE_ACCOUNT_ROLE_API,
POST_ACCOUNT_ROLE_API,
POST_ACCOUNT_USER_API,
GET_ACCOUNT_USER_API,
DELETE_ACCOUNT_USER_API,
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
export const getAccountUserList = async (search_condition = {}) => {
const res = await instance.post(GET_ACCOUNT_USERLIST_API, search_condition);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAccountRoleList = async (search_condition = {}) => {
const res = await instance.post(GET_ACCOUNT_ROLELIST_API, {
Layer: 1,
...search_condition,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAccountRoleAuthList = async (SelectedRoleId) => {
const res = await instance.post(GET_ACCOUNT_ROLEAUTHLIST_API, {
SelectedRoleId,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAccountRoleAuthPageList = async () => {
const res = await instance.post(GET_ACCOUNT_ROLEAUTHPAGELIST_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const postAccountRole = async ({ Id, Name, SaveCheckAuth }) => {
const res = await instance.post(POST_ACCOUNT_ROLE_API, {
Id,
Name,
SaveCheckAuth,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const delRole = async (Id) => {
const res = await instance.post(DELETE_ACCOUNT_ROLE_API, {
Id,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAccountOneUser = async (Id) => {
const res = await instance.post(GET_ACCOUNT_USER_API, {
Id,
});
res.data = {
Account: res.data?.account,
Name: res.data?.full_name,
Email: res.data?.email,
Phone: res.data?.phone,
RoleId: res.data?.role_guid,
Id,
};
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const postAccountUser = async ({
Id,
Account,
Name,
Email,
Phone,
RoleId,
Password,
}) => {
const res = await instance.post(
POST_ACCOUNT_USER_API,
Id
? {
Id: Id,
Account,
Name,
Email,
Phone,
RoleId,
}
: {
Id: "0",
Account,
Name,
Email,
Phone,
RoleId,
Password,
}
);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const changePassword = async ({ Id, Password }) => {
const res = await instance.post(POST_ACCOUNT_USER_API, {
Id,
Password,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const delAccount = async (Id) => {
const res = await instance.post(DELETE_ACCOUNT_USER_API, {
Id,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};

26
src/apis/alert/api.js Normal file
View File

@ -0,0 +1,26 @@
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`;
export const GET_ALERT_MEMBER_LIST_API = `api/Alarm/GetAlarmMemberList`;
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`;

227
src/apis/alert/index.js Normal file
View File

@ -0,0 +1,227 @@
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";
export const getAlertFormId = async (uuid) => {
const res = await instance.post(GET_ALERT_FORMID_API, uuid);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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,
code: res.code,
});
};
export const getAlarmMemberList = async () => {
const res = await instance.post(GET_ALERT_MEMBER_LIST_API, {});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getNoticeList = async (lang) => {
const res = await instance.post(GET_NOTICE_LIST_API, { lang });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const postAlertMember = async (data) => {
const res = await instance.post(POST_ALERT_MEMBER, data);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const deleteAlarmMember = async (id) => {
try {
const res = await instance.post(DELETE_ALERT_MEMBER, { id });
console.log("Delete Alarm Member Response:", res);
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 getAlarmMember = async (data) => {
try {
const res = await instance.post(GET_ALERT_MEMBER, data);
return res.data;
} catch (error) {
console.error("API request failed", error);
return { isSuccess: false, msg: "API request failed" };
}
};
export const getOutliersList = async (id) => {
const res = await instance.post(GET_OUTLIERS_LIST_API, id);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getOutliersDevList = async (id) => {
const res = await instance.post(GET_OUTLIERS_DEVLIST_API, id);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getOutliersPoints = async (id) => {
const res = await instance.post(GET_OUTLIERS_POINTS_API, id);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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);
return apihandler(res.code, res.data, {
msg: res.msg,
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,
});
};

37
src/apis/asset/api.js Normal file
View File

@ -0,0 +1,37 @@
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`;
export const GET_ASSET_LIST_API = `/AssetManage/GetAssetList`;
export const GET_ASSET_SINGLE_API = `/AssetManage/GetAsset`;
export const POST_ASSET_SINGLE_API = `/AssetManage/SaveAsset`;
export const DELETE_ASSET_ITEM_API = `/AssetManage/DeleteAsset`;
export const GET_ASSET_FLOOR_LIST_API = `/AssetManage/GetFloorList`;
export const POST_ASSET_FLOOR_API = `/AssetManage/SaveFloor`;
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`;

337
src/apis/asset/index.js Normal file
View File

@ -0,0 +1,337 @@
import {
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,
GET_ASSET_SINGLE_API,
GET_ASSET_FLOOR_LIST_API,
POST_ASSET_FLOOR_API,
DELETE_ASSET_FLOOR_API,
GET_ASSET_IOT_LIST_API,
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,
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
import { object } from "yup";
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,
code: res.code,
});
};
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,
code: res.code,
});
};
export const postAssetMainList = async ({ id, system_key, system_value, building_guid }) => {
const res = await instance.post(POST_ASSET_MAIN_LIST_API, {
id,
system_key,
system_value,
building_guid
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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 });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAssetList = async (variable_id) => {
const res = await instance.post(GET_ASSET_LIST_API, {
variable_id: parseInt(variable_id),
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAssetSingle = async (main_id) => {
const res = await instance.post(GET_ASSET_SINGLE_API, { main_id });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const postAssetSingle = async (data) => {
let formData = new FormData();
for (let [key, value] of Object.entries(data)) {
console.log(key, value);
if (Array.isArray(value)) {
if (key === "oriFile") {
value.forEach((element, index) => {
formData.append(`${key}[${index}].file`, element.id ? null : element);
formData.append(`${key}[${index}].orgName`, element.name);
formData.append(
`${key}[${index}].saveName`,
element.id ? element.saveName : ""
);
});
} else {
value.forEach((element, index) => {
formData.append(
`sub_device[${index}].device_number`,
element.device_number
);
formData.append(`sub_device[${index}].points`, element.points);
});
}
} else {
formData.append(key, value);
}
}
const res = await instance.post(POST_ASSET_SINGLE_API, formData);
return apihandler(res.code, res.data, { msg: res.msg, code: res.code });
};
export const deleteAssetItem = async (main_id) => {
const res = await instance.post(DELETE_ASSET_ITEM_API, { main_id });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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,
code: res.code,
});
};
export const postAssetFloor = async (formData) => {
const res = await instance.post(POST_ASSET_FLOOR_API, formData);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const deleteAssetFloor = async (formData) => {
const res = await instance.post(DELETE_ASSET_FLOOR_API, formData);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAssetIOTList = async (sub_system_tag, points) => {
const res = await instance.post(GET_ASSET_IOT_LIST_API, {
sub_system_tag,
points,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAssetSubPoint = async (sub_system_tag) => {
const res = await instance.post(GET_ASSET_SUB_POINT_API, {
sub_system_tag,
});
return apihandler(res.code, res.data, {
msg: res.msg,
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,
}) => {
const res = await instance.post(POST_ASSET_DEVICE_ITEM_API, {
id,
variable_id,
full_name,
points,
decimals,
is_bool,
is_link,
});
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,
});
};

6
src/apis/building/api.js Normal file
View File

@ -0,0 +1,6 @@
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`;

View File

@ -0,0 +1,90 @@
import {
GET_BUILDING_API,
POST_BUILDING_API,
DELETE_BUILDING_API,
GET_AUTHPAGE_API,
GET_SUBAUTHPAGE_API,
GET_ALL_DEVICE_API,
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
export const getBuildings = async () => {
const res = await instance.post(GET_BUILDING_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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,
});
};
export const getSysSidebar = async (building_tag) => {
const res = await instance.post(GET_SUBAUTHPAGE_API, {
building_tag,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAllDevice = async () => {
const res = await instance.post(GET_ALL_DEVICE_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const ackSingleAlarm = async (uuid) => {
const res = await instance.post(
`/obix/alarm/${uuid}/ack`,
'<obj is="obix:AckAlarmIn"><str name="ackUser" val="obix" /></obj>'
);
console.log("acked", res);
return apihandler(res.code, res, {
msg: res.msg,
code: res.code,
});
};

13
src/apis/dashboard/api.js Normal file
View File

@ -0,0 +1,13 @@
export const GET_DASHBOARD_INIT_API = `/SituationRoom/Initialize`;
export const GET_DASHBOARD_DEVICE_API = `/SituationRoom/GetDeviceList`;
export const GET_DASHBOARD_PRODUCT_COMPLETE_API = `/SituationRoom/GetProductionStatus`;
export const GET_DASHBOARD_TEMP_API = `/SituationRoom/GetTempratureData`;
export const GET_DASHBOARD_ROOM_TEMP_API = `/SituationRoom/GetFormulaRoomStatusData`;
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_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`

178
src/apis/dashboard/index.js Normal file
View File

@ -0,0 +1,178 @@
import {
GET_DASHBOARD_INIT_API,
GET_DASHBOARD_DEVICE_API,
GET_DASHBOARD_PRODUCT_COMPLETE_API,
GET_DASHBOARD_TEMP_API,
GET_DASHBOARD_ROOM_TEMP_API,
GET_DASHBOARD_ENERGY_API,
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,
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
export const getDashboardInit = async (page_type = "SR") => {
const res = await instance.post(GET_DASHBOARD_INIT_API, {
page_type, // SR:戰情室;PS:生產設定
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getDashboardDevice = async ({ option }) => {
const res = await instance.post(GET_DASHBOARD_DEVICE_API, {
option: parseInt(option),
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getDashboardProductCompletion = async () => {
const res = await instance.post(GET_DASHBOARD_PRODUCT_COMPLETE_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getDashboardEnergy = async () => {
const res = await instance.post(GET_DASHBOARD_ENERGY_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getDashboardFormulaRoom = async ({ timeInterval, typeOption }) => {
const res = await instance.post(GET_DASHBOARD_ROOM_TEMP_API, {
timeInterval,
typeOption,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getDashboardTemp = async ({
timeInterval,
tempOption,
typeOption = "",
}) => {
const res = typeOption
? await instance.post(GET_DASHBOARD_TEMP_API, {
timeInterval,
tempOption,
typeOption,
})
: await instance.post(GET_DASHBOARD_TEMP_API, {
timeInterval,
tempOption,
});
console.log(res);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const postDashboardProductTarget = async ({ date, type, data }) => {
let formatData = [];
for (let [key, value] of Object.entries(data)) {
formatData.push({
name: key,
value,
});
}
const res = await instance.post(POST_DASHBOARD_PRODUCT_TARGET_SETTING_API, {
target: {
date,
type,
data: formatData,
},
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getDashboardProductTarget = async ({ date, type }) => {
const res = await instance.post(GET_DASHBOARD_PRODUCT_TARGET_SETTING_API, {
target: {
date,
type,
},
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getDashboardProductRecord = async ({ start_time, end_time }) => {
const res = await instance.post(GET_DASHBOARD_PRODUCT_HISTORY_API, {
start_time,
end_time,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
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,
});
};

23
src/apis/energy/api.js Normal file
View 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
View 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,
});
};

3
src/apis/forge/api.js Normal file
View File

@ -0,0 +1,3 @@
export const GET_FORGETOKEN_API = `/api/forge/oauth/token`;
export const GET_FORGEURN_API = `/api/Device/GetBuild`;

24
src/apis/forge/index.js Normal file
View File

@ -0,0 +1,24 @@
import instance from "@/util/request";
import { GET_FORGETOKEN_API, GET_FORGEURN_API } from "./api";
import apihandler from "@/util/apihandler";
export const getUrn = async () => {
const res = await instance.post(GET_FORGEURN_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAccessToken = async (callback) => {
try {
const resp = await instance.get(GET_FORGETOKEN_API);
console.log(resp)
const { dictionary } = resp;
callback(dictionary.access_token, dictionary.expires_in);
} catch (err) {
alert("Could not obtain access token. See the console for more details.");
console.error(err);
}
};

16
src/apis/graph/api.js Normal file
View File

@ -0,0 +1,16 @@
// graph
const BASEURL = import.meta.env.VITE_API_BASEURL;
export const GET_GRAPH_SIDEBAR_API = `/GraphManage/GraphManageTreeList`;
export const UPDATE_GRAPH_SIDEBAR_API = `/GraphManage/EditGraphManageTree`;
export const REMOVE_GRAPH_SIDEBAR_API = `/GraphManage/DelGraphManageTree`;
export const POST_GRAPH_SIDEBAR_API = `/GraphManage/SaveGraphManageTree`;
export const GET_GRAPH_PARAM_OPTION_API = `/GraphManage/GraManSpecList`;
export const GET_GRAPH_TABLE_API = `/GraphManage/GraManList`;
export const POST_GRAPH_TABLE_API = `/GraphManage/SaveGraMan`;
export const POST_GRAPH_TABLE_API_2 = `/GraphManage/SaveGraMan`; // 原先沒有小類及規格的
export const UPDATE_GRAPH_TABLE_API = `/GraphManage/EdtOneGraMan`;
export const DELETE_GRAPH_TABLE_API = `/GraphManage/DelOneGraMan`;

122
src/apis/graph/index.js Normal file
View File

@ -0,0 +1,122 @@
import {
GET_GRAPH_SIDEBAR_API,
UPDATE_GRAPH_SIDEBAR_API,
REMOVE_GRAPH_SIDEBAR_API,
POST_GRAPH_SIDEBAR_API,
GET_GRAPH_TABLE_API,
GET_GRAPH_PARAM_OPTION_API,
POST_GRAPH_TABLE_API,
DELETE_GRAPH_TABLE_API,
POST_GRAPH_TABLE_API_2,
UPDATE_GRAPH_TABLE_API
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apiHandler";
export const getSideBar = async () => {
const res = await instance.post(GET_GRAPH_SIDEBAR_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const addSideBarTreeName = async ({ parent_id, name }) => {
const res = await instance.post(POST_GRAPH_SIDEBAR_API, { parent_id, name });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const updateSideBarTreeName = async ({ id, name }) => {
const res = await instance.post(UPDATE_GRAPH_SIDEBAR_API, { id, name });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const removeSideBarTreeName = async (id) => {
const res = await instance.post(REMOVE_GRAPH_SIDEBAR_API, { id });
return apihandler(
res.code,
{ isSuccess: true },
{
msg: res.msg,
code: res.code,
isSuccess: false,
}
);
};
// 中間 table
export const getGraphData = async (id) => {
const res = await instance.post(GET_GRAPH_TABLE_API, { layer_id: id });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};
export const getGraphAddParamOption = async () => {
const res = await instance.post(GET_GRAPH_PARAM_OPTION_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};
export const addGraphTableData = async (formData) => {
const res = await instance.post(POST_GRAPH_TABLE_API, formData);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};
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,
code: res.code,
isSuccess: false,
});
};
export const addGraphTableDataWithoutSubSys = async (formData) => {
const res = await instance.post(POST_GRAPH_TABLE_API_2, formData);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};
export const editGraphTableDataWithoutSubSys = async (formData) => {
const res = await instance.post(UPDATE_GRAPH_TABLE_API, formData);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};

11
src/apis/history/api.js Normal file
View File

@ -0,0 +1,11 @@
// history
const BASEURL = import.meta.env.VITE_API_BASEURL;
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_FAVORITE_API = `/api/History/GetHistoryFavorite`;
export const POST_HISTORY_FAVORITE_API = `/api/History/SaveHistoryFavorite`;
export const DELETE_HISTORY_FAVORITE_API = `/api/History/DeleteHistoryFavorite`;
export const UPDATE_HISTORY_FAVORITE_API = `/api/History/EditHistoryFavorite`;

177
src/apis/history/index.js Normal file
View File

@ -0,0 +1,177 @@
import {
GET_HISTORY_SIDEBAR_API,
GET_HISTORY_POINT_API,
GET_HISTORY_DATA_API,
GET_HISTORY_FAVORITE_API,
POST_HISTORY_FAVORITE_API,
DELETE_HISTORY_FAVORITE_API,
UPDATE_HISTORY_FAVORITE_API,
GET_HISTORY_EXPORT_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,
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, {
msg: res.msg,
code: res.code,
});
};
export const getHistoryPoints = async (Device_list) => {
const res = await instance.post(GET_HISTORY_POINT_API, {
Device_list,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getHistoryData = async ({
Type,
Start_date,
End_date,
Start_time,
End_time,
Device_list,
Points,
table_type,
}) => {
/*
{
Type,
Start_date,
End_date,
Start_time,
End_time,
Device_list,
Points,
}
*/
const res = await instance.post(GET_HISTORY_DATA_API, {
Start_date,
End_date,
Start_time,
End_time,
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, {
msg: res.msg,
code: res.code,
});
};
export const getHistoryExportData = async ({
Type,
Start_date,
End_date,
Start_time,
End_time,
Device_list,
Points,
}) => {
/*
{
Type,
Start_date,
End_date,
Start_time,
End_time,
Device_list,
Points,
}
*/
const res = await fileInstance.post(
GET_HISTORY_EXPORT_API,
{
// ...exportContent,
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]))],
},
{ responseType: "blob" }
);
return apihandler(
res.code,
res,
{
msg: res.msg,
code: res.code,
},
downloadExcel
);
};
export const getHistoryFavorite = async () => {
const res = await instance.post(GET_HISTORY_FAVORITE_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const addHistoryFavorite = async (value) => {
const res = await instance.post(POST_HISTORY_FAVORITE_API, {
device_name_tag: value.sub_system_tag,
Device_list: Array.isArray(value.Device_list)
? value.Device_list
: [value.Device_list],
Points: Array.isArray(value.Points) ? value.Points : [value.Points],
favorite_name: value.favorite_name,
Type: parseInt(value.Type),
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const deleteHistoryFavorite = async (favorite_guid) => {
const res = await instance.post(DELETE_HISTORY_FAVORITE_API, {
favorite_guid,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const editHistoryFavorite = async ({ favorite_guid, favorite_name }) => {
const res = await instance.post(UPDATE_HISTORY_FAVORITE_API, {
favorite_guid,
favorite_name,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};

1
src/apis/login/api.js Normal file
View File

@ -0,0 +1 @@
export const POST_LOGIN = `/api/LoginV2/`;

27
src/apis/login/index.js Normal file
View File

@ -0,0 +1,27 @@
import { POST_LOGIN } from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
export async function Login({ account, password }) {
const res = await instance.post(POST_LOGIN, {
account,
password,
});
if (res.code === "0000") {
console.log(res.data);
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, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
}

16
src/apis/operation/api.js Normal file
View File

@ -0,0 +1,16 @@
export const GET_OPERATION_RECORD_API = `/operation/OpeRecList`;
export const GET_OPERATION_EXPORT_API = `/operation/OpeExportExcel`;
export const GET_OPERATION_DEVICELIST_API = `/operation/DevList`;
export const GET_OPERATION_COMPANYLIST_API = `/operation/OpeFirSel`;
export const GET_SINGLE_OPERATION_RECORD_API = `/operation/OpeRecRead`;
export const GET_OPERATION_FORMID_API = `/operation/GetFormId`; // 新增單號前置
export const POST_OPERATION_RECORD_API = `/operation/SavOpeRecord`;
export const DELETE_OPERATION_RECORD_API = `/operation/DelOpeRecord`;
// 廠商
export const GET_OPERATION_COMPANY_API = `/operation/OpeFirList`; // 廠商列表
export const GET_OPERATION_SINGLE_CONPANY_API = `/operation/OpeFirRead`; // 單一廠商
export const POST_OPERATION_COMPANY_API = `/operation/SaveOpeFirm`;
export const UPDATE_OPERATION_COMPANY_API = `/operation/EdtOneOpeFirm`;
export const DELETE_OPERATION_COMPANY_API = `/operation/DelOpeFirm`;

190
src/apis/operation/index.js Normal file
View File

@ -0,0 +1,190 @@
import {
GET_OPERATION_RECORD_API,
GET_OPERATION_COMPANY_API,
GET_SINGLE_OPERATION_RECORD_API,
GET_OPERATION_DEVICELIST_API,
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,
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
import dayjs from "dayjs";
export const getOperationRecord = async ({
work_type,
start_created_at,
end_created_at,
serial_number,
sub_system_tag,
}) => {
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"),
serial_number: serial_number || null,
main_system_tag: null,
sub_system_tag:
typeof sub_system_tag === "string" ? [sub_system_tag] : sub_system_tag,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getOperationExportRecord = async ({
work_type,
start_created_at,
end_created_at,
}) => {
const res = await instance.post(GET_OPERATION_EXPORT_API, {
work_type: parseInt(work_type),
startdate: dayjs(start_created_at).format("YYYY-MM-DDTHH:mm:ss"),
enddate: dayjs(end_created_at)
.date(dayjs(end_created_at).get("date") + 1)
.format("YYYY-MM-DDTHH:mm:ss"),
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getOperationCompanyList = async () => {
const res = await instance.post(GET_OPERATION_COMPANY_API, {
sub_system_tag: [],
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getOperationDeviceList = async ({
list_sub_system_tag,
device_building_tag,
device_area_tag,
}) => {
const res = await instance.post(GET_OPERATION_DEVICELIST_API, {
list_sub_system_tag:
typeof list_sub_system_tag === "string"
? [list_sub_system_tag]
: list_sub_system_tag,
device_building_tag,
device_area_tag,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getOperationEditRecord = async (formId) => {
const res = await instance.post(GET_SINGLE_OPERATION_RECORD_API, {
formId,
});
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);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getOperationFormId = async () => {
const res = await instance.post(GET_OPERATION_FORMID_API, {});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const deleteOperationRecord = async (id) => {
const res = await instance.post(DELETE_OPERATION_RECORD_API, { id });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
// 公司
export const postOperationCompany = async ({
name,
contact_person,
phone,
email,
city,
address,
tax_id_number,
remark,
}) => {
const res = await instance.post(POST_OPERATION_COMPANY_API, {
name,
contact_person,
phone,
email,
city,
address,
tax_id_number,
remark,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const updateOperationCompany = async ({
name,
contact_person,
phone,
email,
city,
address,
tax_id_number,
remark,
id,
}) => {
const res = await instance.post(UPDATE_OPERATION_COMPANY_API, {
id,
name,
contact_person,
phone,
email,
city,
address,
tax_id_number,
remark,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const deleteOperationCompany = async (id) => {
const res = await instance.post(DELETE_OPERATION_COMPANY_API, { id });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};

View File

@ -0,0 +1,4 @@
export const POST_SETTING_POINT_API = `/SituationRoom/SetPointSetting`;
export const GET_SETTING_TYPE_API = `/SituationRoom/GetProducts`;
export const POST_SETTING_TYPE_API = `/SituationRoom/SetProduct`;

View File

@ -0,0 +1,45 @@
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
import {
POST_SETTING_POINT_API,
GET_SETTING_TYPE_API,
POST_SETTING_TYPE_API,
} from "./api";
export const postProductSettingPoint = async (type, devices) => {
const res = await instance.post(POST_SETTING_POINT_API, {
devices: devices.map(({ device_number }) => device_number),
values: [
{
point: "Type",
value: type.value,
},
],
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};
export const getProductSettingType = async () => {
const res = await instance.post(GET_SETTING_TYPE_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};
export const postProductSettingType = async (data) => {
const res = await instance.post(POST_SETTING_TYPE_API, data);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
isSuccess: false,
});
};

3
src/apis/system/api.js Normal file
View File

@ -0,0 +1,3 @@
export const GET_SYSTEM_FLOOR_LIST_API = `/api/Device/GetFloor`;
export const GET_SYSTEM_DEVICE_LIST_API = `/api/Device/GetDeviceList`;
export const GET_SYSTEM_REALTIME_API = `/api/Device/GetRealTimeData`;

44
src/apis/system/index.js Normal file
View File

@ -0,0 +1,44 @@
import {
GET_SYSTEM_FLOOR_LIST_API,
GET_SYSTEM_DEVICE_LIST_API,
GET_SYSTEM_REALTIME_API,
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
export const getSystemFloors = async (building_tag, sub_system_tag) => {
const res = await instance.post(GET_SYSTEM_FLOOR_LIST_API, {
building_tag,
sub_system_tag,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getSystemDevices = async ({
sub_system_tag,
building_guid,
department_id_list,
}) => {
const res = await instance.post(GET_SYSTEM_DEVICE_LIST_API, {
sub_system_tag,
building_guid,
department_id_list,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getSystemRealTime = async (device_list) => {
const res = await instance.post(GET_SYSTEM_REALTIME_API, { device_list });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};

89
src/assets/base.css Normal file
View File

@ -0,0 +1,89 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--primary: #6fdda8;
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-dark-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

56
src/assets/btn.css Normal file
View File

@ -0,0 +1,56 @@
/**區域框**/
.area-box {
/* width: 100%; */
border-radius: 10px;
display: flex;
align-items: center;
flex-wrap: wrap;
color: #fff;
}
.area-box .item {
display: flex;
align-items: center;
flex-wrap: wrap;
color: #fff;
margin: 0;
}
.area-box .item button:last-child::after {
display: none;
}
.area-box .item button::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
right: -15px;
margin: auto;
display: block;
width: 15px;
height: 1px;
background-color: #a1ffd6;
z-index: -1;
}
.area-box .item button {
position: relative;
z-index: 1;
border-radius: 5px;
margin: 0 7px;
background-color: #021422;
padding: 0.5rem 0;
min-width: 65px;
color: #fff;
border: 1px solid #a1ffd6 !important;
text-align: center;
margin-bottom: 15px;
padding: 0 5px;
}
.area-box .item button.active {
background-color: #6fdda8;
text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.9);
box-shadow: 0px 0px 5px rgba(255, 255, 255, 0.8);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#dff3fa;}.cls-2{fill:#74b6ed;}</style></defs><path class="cls-1" d="M2.79,24.12a2.59,2.59,0,0,0,2.58-2.58V7.1A5,5,0,0,0,7.11,5.4H21.23a2.59,2.59,0,0,0,2.58-2.58.12.12,0,0,0-.12-.12.12.12,0,0,0-.12.12,2.34,2.34,0,0,1-2.34,2.34H7l0,.06A4.86,4.86,0,0,1,5.19,6.93L5.13,7V21.54a2.34,2.34,0,0,1-2.34,2.34.12.12,0,0,0-.12.12A.12.12,0,0,0,2.79,24.12Z"/><path class="cls-2" d="M2,18.05a.6.6,0,0,1-.6-.59V4.14L1,3.86A2.09,2.09,0,0,1,2.09,0,2.05,2.05,0,0,1,3.88,1l.28.46H17a.6.6,0,0,1,.6.6.59.59,0,0,1-.6.59H4.16l-.28.47a2.08,2.08,0,0,1-.77.76l-.49.27V17.46A.59.59,0,0,1,2,18.05Z"/></svg>

After

Width:  |  Height:  |  Size: 697 B

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#dff3fa;}.cls-2{fill:#74b6ed;}</style></defs><path class="cls-1" d="M-.15,21.18A2.58,2.58,0,0,1,2.43,18.6H16.87a4.88,4.88,0,0,1,1.7-1.74V2.74A2.59,2.59,0,0,1,21.15.15a.12.12,0,0,1,.12.12.12.12,0,0,1-.12.12,2.35,2.35,0,0,0-2.34,2.35V17l-.06,0A4.63,4.63,0,0,0,17,18.78l0,.06H2.43A2.35,2.35,0,0,0,.08,21.18.12.12,0,0,1,0,21.3.11.11,0,0,1-.15,21.18Z"/><path class="cls-2" d="M5.92,21.94a.59.59,0,0,0,.59.6H19.83l.28.44a2.07,2.07,0,0,0,1.77,1,2.09,2.09,0,0,0,1.06-3.89l-.47-.27V7a.59.59,0,0,0-.59-.6.6.6,0,0,0-.6.6V19.81l-.46.27a2.11,2.11,0,0,0-.76.78l-.28.48H6.51A.59.59,0,0,0,5.92,21.94Z"/></svg>

After

Width:  |  Height:  |  Size: 713 B

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><defs><style>.cls-1{fill:#0ca9d4;}</style></defs><polygon id="_13" data-name="13" class="cls-1" points="3.96 0 4.48 3.43 7.91 3.96 4.48 4.48 3.96 7.91 3.43 4.48 0 3.96 3.43 3.43 3.96 0"/></svg>

After

Width:  |  Height:  |  Size: 286 B

View 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:#17CEE3;}
.st1{opacity:0.3;fill:#969696;}
.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 "/>
<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

View File

@ -0,0 +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: #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>

After

Width:  |  Height:  |  Size: 1.1 KiB

View 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

View 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

View 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 2.5 21" style="enable-background:new 0 0 2.5 21;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.8;}
.st1{fill:#FDE9F2;}
</style>
<g id="_x37_0_00000047024518298343511510000016821505459452511412_" class="st0">
<rect x="1.2" y="1" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -1.5991 1.79)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="-0.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.5638 1.3612)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="5.2" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -4.5762 3.0232)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="3.8" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -3.541 2.5943)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="9.5" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -7.5533 4.2563)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="8" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -6.5181 3.8275)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="13.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -10.5305 5.4895)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="12.2" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -9.4952 5.0607)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="17.9" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -13.5076 6.7227)" class="st1" width="0.3" height="3.6"/>
<rect x="1.2" y="16.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -12.4724 6.2938)" class="st1" width="0.3" height="3.6"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 151 38"><defs><style>.cls-1,.cls-5{fill:#b3e8f4;}.cls-1{opacity:0;}.cls-2{fill:#83beed;}.cls-3{fill:#dff3fa;}.cls-4{fill:#fcfefd;}.cls-6{fill:#fde9f2;}</style></defs><path class="cls-1" d="M140.66,2H4.17A4.17,4.17,0,0,0,0,6.15v21.5l10.6,10.6H147.09a4.17,4.17,0,0,0,4.17-4.17V12.59Z"/><path class="cls-2" d="M147.09,36.29H11.41L2,26.84V6.15A2.21,2.21,0,0,1,4.17,3.94H139.85l9.45,9.46V34.08A2.21,2.21,0,0,1,147.09,36.29ZM11.52,36H147.09a2,2,0,0,0,2-2V13.5l-9.31-9.31H4.17a2,2,0,0,0-2,2V26.73Z"/><polygon class="cls-3" points="24.78 5.81 8.01 5.81 11.16 2.33 27.93 2.33 24.78 5.81"/><polygon class="cls-4" points="137.13 36.16 127.56 36.16 129.36 34.17 138.93 34.17 137.13 36.16"/><polygon class="cls-4" points="114.9 36.16 105.33 36.16 107.13 34.17 116.7 34.17 114.9 36.16"/><polygon class="cls-4" points="92.67 36.16 83.11 36.16 84.91 34.17 94.47 34.17 92.67 36.16"/><polygon class="cls-5" points="123.2 6.35 92.68 6.35 98.42 0 128.94 0 123.2 6.35"/><rect class="cls-4" x="77.43" y="33.96" width="71.74" height="0.25"/><polygon id="_13" data-name="13" class="cls-6" points="138.62 8.13 139.09 11.2 142.16 11.67 139.09 12.14 138.62 15.21 138.15 12.14 135.08 11.67 138.15 11.2 138.62 8.13"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 151 38"><defs><style>.cls-1{fill:#fff;opacity:0.05;}.cls-2{fill:#af2334;opacity:0.75;}.cls-3{fill:#30c4c4;}.cls-4{fill:#dff3fa;}.cls-5{fill:#fcfefd;}</style></defs><path class="cls-1" d="M140.18,2H3.68A4.17,4.17,0,0,0-.48,6.15v21.5l10.6,10.6H146.61a4.17,4.17,0,0,0,4.17-4.17V12.59Z"/><path class="cls-2" d="M140.18,2H3.68A4.17,4.17,0,0,0-.48,6.15v21.5l10.6,10.6H146.61a4.17,4.17,0,0,0,4.17-4.17V12.59Z"/><path class="cls-3" d="M146.61,36.29H10.93L1.47,26.84V6.15A2.22,2.22,0,0,1,3.68,3.94H139.36l9.46,9.46V34.08A2.21,2.21,0,0,1,146.61,36.29ZM11,36H146.61a2,2,0,0,0,2-2V13.5l-9.31-9.31H3.68a2,2,0,0,0-2,2V26.73Z"/><polygon class="cls-4" points="24.3 5.81 7.53 5.81 10.68 2.33 27.45 2.33 24.3 5.81"/><polygon class="cls-5" points="136.65 36.16 127.08 36.16 128.88 34.17 138.45 34.17 136.65 36.16"/><polygon class="cls-5" points="114.42 36.16 104.85 36.16 106.65 34.17 116.22 34.17 114.42 36.16"/><polygon class="cls-5" points="92.19 36.16 82.62 36.16 84.42 34.17 93.99 34.17 92.19 36.16"/><polygon class="cls-4" points="122.72 6.35 92.2 6.35 97.94 0 128.45 0 122.72 6.35"/><rect class="cls-5" x="76.95" y="33.96" width="71.74" height="0.25"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12.66 12.66"><defs><style>.cls-1{opacity:0.8;}.cls-2{fill:#35eded;}.cls-3{fill:#ffe448;}</style></defs><g class="cls-1"><path class="cls-2" d="M4.89.76a5.87,5.87,0,0,0-1.48.62L2.87.84l-2,2,.54.54A5.87,5.87,0,0,0,.76,4.89H0V6.14H2.25A4.07,4.07,0,0,1,6.14,2.25V0H4.89Z"/><path class="cls-2" d="M10.41,6.51a4.09,4.09,0,0,1-3.9,3.9v2.25H7.76v-.77a5.57,5.57,0,0,0,1.49-.61l.54.54,2-2-.54-.54a5.57,5.57,0,0,0,.61-1.49h.77V6.51Z"/></g><g class="cls-1"><path class="cls-3" d="M2.25,6.51H0V7.76H.76a5.94,5.94,0,0,0,.62,1.49l-.54.54,2,2,.54-.54a5.5,5.5,0,0,0,1.48.61v.77H6.14V10.41A4.08,4.08,0,0,1,2.25,6.51Z"/><path class="cls-3" d="M11.89,4.89a5.5,5.5,0,0,0-.61-1.48l.54-.54-2-2-.54.54A5.94,5.94,0,0,0,7.76.76V0H6.51V2.25a4.08,4.08,0,0,1,3.9,3.89h2.25V4.89Z"/></g></svg>

After

Width:  |  Height:  |  Size: 850 B

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13.73 25.44"><defs><style>.cls-1{opacity:0.8;}.cls-2{fill:#64ed81;}</style></defs><g class="cls-1"><path class="cls-2" d="M2.52,4.79A2.4,2.4,0,0,1,2.52,0,2.42,2.42,0,0,1,4.84,1.79h8.89V3H4.84A2.42,2.42,0,0,1,2.52,4.79Zm0-4.54A2.15,2.15,0,1,0,4.61,2.84l0-.09h8.84V2H4.64l0-.1A2.15,2.15,0,0,0,2.52.25Zm0,3.58A1.44,1.44,0,1,1,4,2.39,1.44,1.44,0,0,1,2.52,3.83Zm0-2.62A1.19,1.19,0,1,0,3.71,2.39,1.18,1.18,0,0,0,2.52,1.21Z"/><path class="cls-2" d="M2.48,11.67a2.4,2.4,0,1,1,2.32-3h8.9V9.88H4.8A2.41,2.41,0,0,1,2.48,11.67Zm0-4.54a2.15,2.15,0,1,0,2.1,2.6l0-.1h8.85V8.92H4.6l0-.09A2.16,2.16,0,0,0,2.48,7.13Zm0,3.59A1.44,1.44,0,1,1,3.92,9.28,1.44,1.44,0,0,1,2.48,10.72Zm0-2.63A1.19,1.19,0,1,0,3.67,9.28,1.18,1.18,0,0,0,2.48,8.09Z"/><path class="cls-2" d="M2.43,18.55a2.39,2.39,0,1,1,2.31-3h8.9v1.2H4.74A2.4,2.4,0,0,1,2.43,18.55Zm0-4.53a2.14,2.14,0,1,0,2.09,2.59l0-.1h8.85v-.7H4.54l0-.1A2.15,2.15,0,0,0,2.43,14Zm0,3.58a1.44,1.44,0,1,1,1.44-1.44A1.45,1.45,0,0,1,2.43,17.6Zm0-2.63a1.19,1.19,0,0,0,0,2.38,1.19,1.19,0,1,0,0-2.38Z"/><path class="cls-2" d="M2.39,25.44a2.4,2.4,0,1,1,2.32-3H13.6v1.21H4.71A2.41,2.41,0,0,1,2.39,25.44Zm0-4.54a2.15,2.15,0,1,0,2.1,2.59l0-.09h8.84v-.71H4.51l0-.1A2.15,2.15,0,0,0,2.39,20.9Zm0,3.58A1.44,1.44,0,1,1,3.83,23,1.43,1.43,0,0,1,2.39,24.48Zm0-2.63A1.19,1.19,0,1,0,3.58,23,1.19,1.19,0,0,0,2.39,21.85Z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44.63 9.62"><defs><style>.cls-1{opacity:0.8;}.cls-2{fill:#35eded;}.cls-3{fill:#64ed81;}</style></defs><g class="cls-1"><rect class="cls-2" y="7.2" width="44.63" height="0.5"/></g><rect class="cls-3" x="34.71" y="4.68" width="9.62" height="0.25"/><rect class="cls-3" x="39.4" width="0.25" height="9.62"/></svg>

After

Width:  |  Height:  |  Size: 397 B

View File

@ -0,0 +1,7 @@
<?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 16.1 11.6" style="enable-background:new 0 0 16.1 11.6;" xml:space="preserve">
<polygon class="st0" fill="currentColor" points="0,11.6 10.3,11.6 16.1,5.8 10.3,0 0,0 5.8,5.8 "/>
</svg>

After

Width:  |  Height:  |  Size: 460 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 14 55"><defs><style>.cls-1{isolation:isolate;}.cls-2{mix-blend-mode:screen;opacity:0.75;}.cls-3{fill:#58bfe8;}</style></defs><g class="cls-1"><g id="圖層_1" data-name="圖層 1"><image class="cls-2" width="14" height="55" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAA3CAYAAAA8PXu0AAAACXBIWXMAAAsSAAALEgHS3X78AAAA8ElEQVRIS+2WTQrCMBBGX4roQhDcieAZvP9VPICIKxGyUKtx4Zc6TXVQF67yQZjm52Xarl5IKfFLRsU8FNUm2WrBRvOJqoUTcAHOqimDQYfnwBKYai1ptMAR2KtebMeJoLXA7nbgJChqtGXHqUYEdqo3nh0jcMW8aoYDj047YKPDN/rf2MLwr+bviYIOAvNeV0swbyQBeQzSvFr8JBV0UkEnFXRSQScVdFJBJxV08n/wla5kUWroX+x6jlWzmdZKs+rZIzzFaAwstFa63MAerYpFHh1XfGCPaHOr53e+2tljME7e8IUhh0Lmf3LywaaXO0TIazwsXqhCAAAAAElFTkSuQmCC"/><polygon class="cls-3" points="10.59 51.05 3.9 51.05 3.86 3.77 10.55 3.77 10.55 4.77 4.86 4.77 4.9 50.05 10.59 50.05 10.59 51.05"/></g></g></svg>

After

Width:  |  Height:  |  Size: 926 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 14 55"><defs><style>.cls-1{isolation:isolate;}.cls-2{mix-blend-mode:screen;opacity:0.75;}.cls-3{fill:#23c8cc;}</style></defs><g class="cls-1"><g id="圖層_1" data-name="圖層 1"><image class="cls-2" width="14" height="55" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAA3CAYAAAA8PXu0AAAACXBIWXMAAAsSAAALEgHS3X78AAAA8ElEQVRIS+2WTQrCMBBGX4roQhDcieAZvP9VPICIKxGyUKtx4Zc6TXVQF67yQZjm52Xarl5IKfFLRsU8FNUm2WrBRvOJqoUTcAHOqimDQYfnwBKYai1ptMAR2KtebMeJoLXA7nbgJChqtGXHqUYEdqo3nh0jcMW8aoYDj047YKPDN/rf2MLwr+bviYIOAvNeV0swbyQBeQzSvFr8JBV0UkEnFXRSQScVdFJBJxV08n/wla5kUWroX+x6jlWzmdZKs+rZIzzFaAwstFa63MAerYpFHh1XfGCPaHOr53e+2tljME7e8IUhh0Lmf3LywaaXO0TIazwsXqhCAAAAAElFTkSuQmCC"/><polygon class="cls-3" points="10.59 51.05 3.9 51.05 3.86 3.77 10.55 3.77 10.55 4.77 4.86 4.77 4.9 50.05 10.59 50.05 10.59 51.05"/></g></g></svg>

After

Width:  |  Height:  |  Size: 926 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 14 55"><defs><style>.cls-1{isolation:isolate;}.cls-2{mix-blend-mode:screen;opacity:0.75;}.cls-3{fill:#58bfe8;}</style></defs><g class="cls-1"><g id="圖層_1" data-name="圖層 1"><image class="cls-2" width="14" height="55" transform="matrix(-1, 0, 0, 1, 14, 0)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAA3CAYAAAA8PXu0AAAACXBIWXMAAAsSAAALEgHS3X78AAAA8ElEQVRIS+2WTQrCMBBGX4roQhDcieAZvP9VPICIKxGyUKtx4Zc6TXVQF67yQZjm52Xarl5IKfFLRsU8FNUm2WrBRvOJqoUTcAHOqimDQYfnwBKYai1ptMAR2KtebMeJoLXA7nbgJChqtGXHqUYEdqo3nh0jcMW8aoYDj047YKPDN/rf2MLwr+bviYIOAvNeV0swbyQBeQzSvFr8JBV0UkEnFXRSQScVdFJBJxV08n/wla5kUWroX+x6jlWzmdZKs+rZIzzFaAwstFa63MAerYpFHh1XfGCPaHOr53e+2tljME7e8IUhh0Lmf3LywaaXO0TIazwsXqhCAAAAAElFTkSuQmCC"/><polygon class="cls-3" points="3.41 51.05 10.1 51.05 10.14 3.77 3.44 3.77 3.44 4.77 9.14 4.77 9.1 50.05 3.41 50.05 3.41 51.05"/></g></g></svg>

After

Width:  |  Height:  |  Size: 962 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 14 55"><defs><style>.cls-1{isolation:isolate;}.cls-2{mix-blend-mode:screen;opacity:0.75;}.cls-3{fill:#23c8cc;}</style></defs><g class="cls-1"><g id="圖層_1" data-name="圖層 1"><image class="cls-2" width="14" height="55" transform="matrix(-1, 0, 0, 1, 14, 0)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAA3CAYAAAA8PXu0AAAACXBIWXMAAAsSAAALEgHS3X78AAAA8ElEQVRIS+2WTQrCMBBGX4roQhDcieAZvP9VPICIKxGyUKtx4Zc6TXVQF67yQZjm52Xarl5IKfFLRsU8FNUm2WrBRvOJqoUTcAHOqimDQYfnwBKYai1ptMAR2KtebMeJoLXA7nbgJChqtGXHqUYEdqo3nh0jcMW8aoYDj047YKPDN/rf2MLwr+bviYIOAvNeV0swbyQBeQzSvFr8JBV0UkEnFXRSQScVdFJBJxV08n/wla5kUWroX+x6jlWzmdZKs+rZIzzFaAwstFa63MAerYpFHh1XfGCPaHOr53e+2tljME7e8IUhh0Lmf3LywaaXO0TIazwsXqhCAAAAAElFTkSuQmCC"/><polygon class="cls-3" points="3.41 51.05 10.1 51.05 10.14 3.77 3.44 3.77 3.44 4.77 9.14 4.77 9.1 50.05 3.41 50.05 3.41 51.05"/></g></g></svg>

After

Width:  |  Height:  |  Size: 962 B

BIN
src/assets/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

1
src/assets/img/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 122 KiB

View File

@ -0,0 +1,14 @@
<?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 24.4 19.5" style="enable-background:new 0 0 24.4 19.5;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.6;}
.st1{fill:#83FF97;}
</style>
<g class="st0">
<g>
<path class="st1" d="M17.5,19.5H0l6.8-9.8L0,0h17.5l6.8,9.8l-0.1,0.1L17.5,19.5z M1,19h16.3l6.5-9.3l-6.5-9.3H1l6.5,9.3L1,19z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 595 B

View File

@ -0,0 +1,9 @@
<?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 24.4 19.5" style="enable-background:new 0 0 24.4 19.5;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.6;fill:#83FF97;}
</style>
<polygon class="st0" points="17.5,0 0,0 6.8,9.8 0,19.5 17.5,19.5 24.3,9.9 24.4,9.8 "/>
</svg>

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><defs><style>.cls-1{fill:#ffe422;}</style></defs><polygon id="_13" data-name="13" class="cls-1" points="4 0.19 4.5 3.5 7.81 4 4.5 4.5 4 7.81 3.5 4.5 0.19 4 3.5 3.5 4 0.19"/></svg>

After

Width:  |  Height:  |  Size: 272 B

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 9"><defs><style>.cls-1{fill:#30c4c4;}</style></defs><path id="_12" data-name="12" class="cls-1" d="M22,4.44C21.92,4.4,8.63,4,7.59,3.11A11.13,11.13,0,0,1,4.82.19h-1A9.65,9.65,0,0,1,0,4V5a9.65,9.65,0,0,1,3.8,3.8h1a11.12,11.12,0,0,1,2.7-3.1C8.17,5.17,21.94,4.59,22,4.56Z"/></svg>

After

Width:  |  Height:  |  Size: 367 B

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4.91 37.93"><defs><style>.cls-1{opacity:0.8;}.cls-2{fill:#ffe422;}</style></defs><g id="_70" data-name="70" class="cls-1"><rect class="cls-2" x="2.21" y="29.6" width="0.49" height="6.45" transform="translate(-22.5 11.35) rotate(-45)"/><rect class="cls-2" x="2.21" y="32.24" width="0.49" height="6.45" transform="translate(-24.36 12.13) rotate(-45)"/><rect class="cls-2" x="2.21" y="22.01" width="0.49" height="6.45" transform="translate(-17.13 9.13) rotate(-45)"/><rect class="cls-2" x="2.21" y="24.65" width="0.49" height="6.45" transform="translate(-18.99 9.9) rotate(-45)"/><rect class="cls-2" x="2.21" y="14.42" width="0.49" height="6.45" transform="translate(-11.76 6.9) rotate(-45)"/><rect class="cls-2" x="2.21" y="17.06" width="0.49" height="6.45" transform="translate(-13.62 7.68) rotate(-45)"/><rect class="cls-2" x="2.21" y="6.82" width="0.49" height="6.45" transform="translate(-6.39 4.68) rotate(-45)"/><rect class="cls-2" x="2.21" y="9.46" width="0.49" height="6.45" transform="translate(-8.25 5.45) rotate(-45)"/><rect class="cls-2" x="2.21" y="-0.77" width="0.49" height="6.45" transform="translate(-1.02 2.46) rotate(-45)"/><rect class="cls-2" x="2.21" y="1.87" width="0.49" height="6.45" transform="translate(-2.88 3.23) rotate(-45)"/></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7.13 78.94"><defs><style>.cls-1{fill:#fde9f2;}</style></defs><g id="_67" data-name="67"><rect class="cls-1" y="75.13" width="3.57" height="3.57"/><rect class="cls-1" y="68" width="3.57" height="3.57"/><rect class="cls-1" y="60.87" width="3.57" height="3.57"/><rect class="cls-1" y="53.73" width="3.57" height="3.57"/><rect class="cls-1" y="46.6" width="3.57" height="3.57"/><rect class="cls-1" y="39.47" width="3.57" height="3.57"/><rect class="cls-1" y="32.34" width="3.57" height="3.57"/><rect class="cls-1" y="25.2" width="3.57" height="3.57"/><rect class="cls-1" y="18.07" width="3.57" height="3.57"/><rect class="cls-1" y="10.94" width="3.57" height="3.57"/><rect class="cls-1" y="3.81" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="71.56" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="64.43" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="57.3" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="50.17" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="43.03" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="35.9" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="28.77" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="21.64" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="14.51" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="7.37" width="3.57" height="3.57"/><rect class="cls-1" x="3.57" y="0.24" width="3.57" height="3.57"/></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 9"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M22.56,4.36h-8a3,3,0,0,0-2.87-2.88V.4h-.29V1.48A3,3,0,0,0,8.49,4.36h-8v.28H8.49a3,3,0,0,0,2.87,2.88V8.6h.29V7.52a3,3,0,0,0,2.87-2.88h8ZM13.44,2.57a2.73,2.73,0,0,1,.8,1.79H12.38a.89.89,0,0,0-.73-.74V1.77A2.7,2.7,0,0,1,13.44,2.57Zm-3.87,0a2.7,2.7,0,0,1,1.79-.8V3.62a.88.88,0,0,0-.73.74H8.77A2.73,2.73,0,0,1,9.57,2.57Zm0,3.87a2.76,2.76,0,0,1-.8-1.8h1.86a.88.88,0,0,0,.73.74V7.23A2.74,2.74,0,0,1,9.57,6.44Zm3.87,0a2.74,2.74,0,0,1-1.79.79V5.38a.89.89,0,0,0,.73-.74h1.86A2.76,2.76,0,0,1,13.44,6.44Z"/></svg>

After

Width:  |  Height:  |  Size: 664 B

View File

@ -0,0 +1,49 @@
<?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 110.8 43.5" style="enable-background:new 0 0 110.8 43.5;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.5;fill:url(#SVGID_1_);}
.st1{fill:#FFFFFF;}
.st2{opacity:0.7;}
.st3{fill:#79AECC;}
.st4{fill:#DFF3FA;}
</style>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="6.0326" y1="21.8344" x2="106.0948" y2="21.8344">
<stop offset="0" style="stop-color:#0CA9D4;stop-opacity:0.7"/>
<stop offset="2.671185e-02" style="stop-color:#27ABD7;stop-opacity:0.6626"/>
<stop offset="6.063062e-02" style="stop-color:#42AEDA;stop-opacity:0.6151"/>
<stop offset="9.965897e-02" style="stop-color:#58B0DC;stop-opacity:0.5605"/>
<stop offset="0.1452" style="stop-color:#69B1DE;stop-opacity:0.4967"/>
<stop offset="0.2015" style="stop-color:#74B2DF;stop-opacity:0.4178"/>
<stop offset="0.2806" style="stop-color:#7BB3E0;stop-opacity:0.3072"/>
<stop offset="0.5" style="stop-color:#7DB3E0;stop-opacity:0"/>
<stop offset="0.7194" style="stop-color:#7BB3E0;stop-opacity:0.3072"/>
<stop offset="0.7985" style="stop-color:#74B2DF;stop-opacity:0.4178"/>
<stop offset="0.8548" style="stop-color:#69B1DE;stop-opacity:0.4967"/>
<stop offset="0.9003" style="stop-color:#58B0DC;stop-opacity:0.5605"/>
<stop offset="0.9394" style="stop-color:#42AEDA;stop-opacity:0.6151"/>
<stop offset="0.9733" style="stop-color:#27ABD7;stop-opacity:0.6626"/>
<stop offset="1" style="stop-color:#0CA9D4;stop-opacity:0.7"/>
</linearGradient>
<path class="st0" d="M104.6,39.6H7.5c-0.8,0-1.5-0.7-1.5-1.5V5.5c0-0.8,0.7-1.5,1.5-1.5h97.1c0.8,0,1.5,0.7,1.5,1.5v32.6
C106.1,38.9,105.4,39.6,104.6,39.6z"/>
<g>
<path class="st1" d="M102.5,38H9.6c-0.8,0-1.5-0.7-1.5-1.5V7.1c0-0.8,0.7-1.5,1.5-1.5h92.9c0.8,0,1.5,0.7,1.5,1.5v29.5
C104,37.4,103.3,38,102.5,38z M9.6,5.9c-0.7,0-1.2,0.5-1.2,1.2v29.5c0,0.7,0.5,1.2,1.2,1.2h92.9c0.7,0,1.2-0.5,1.2-1.2V7.1
c0-0.7-0.5-1.2-1.2-1.2H9.6z"/>
</g>
<g class="st2">
<g>
<path class="st3" d="M107,43.4H5.1c-2.4,0-4.4-2-4.4-4.4V4.6c0-2.4,2-4.4,4.4-4.4H107c2.4,0,4.4,2,4.4,4.4V39
C111.4,41.5,109.4,43.4,107,43.4z M5.1,2.3c-1.3,0-2.4,1.1-2.4,2.4V39c0,1.3,1.1,2.4,2.4,2.4H107c1.3,0,2.4-1.1,2.4-2.4V4.6
c0-1.3-1.1-2.4-2.4-2.4H5.1z"/>
</g>
</g>
<polygon class="st4" points="66.5,3.1 44,3.1 45.7,0.2 68.1,0.2 "/>
<polygon class="st4" points="66.5,43.4 44,43.4 45.7,40.6 68.1,40.6 "/>
<polygon class="st4" points="4.5,11.4 4.5,33.9 0.7,32.2 0.7,9.8 "/>
<polygon class="st4" points="111.4,11.4 111.4,33.9 107.6,32.2 107.6,9.8 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,44 @@
<?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 9.7 11.1" style="enable-background:new 0 0 9.7 11.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#3BBBC9;}
.st1{fill:#3B69B1;}
</style>
<g>
<g>
<rect y="0" class="st0" width="1" height="0.8"/>
<rect y="2.1" class="st0" width="1" height="0.8"/>
<rect y="4.1" class="st0" width="1" height="0.8"/>
<rect y="6.2" class="st0" width="1" height="0.8"/>
<rect y="8.2" class="st0" width="1" height="0.8"/>
<rect y="10.3" class="st0" width="1" height="0.8"/>
</g>
<g>
<rect x="1.7" y="0" class="st1" width="1" height="0.8"/>
<rect x="1.7" y="2.1" class="st1" width="1" height="0.8"/>
<rect x="1.7" y="4.1" class="st1" width="1" height="0.8"/>
<rect x="1.7" y="6.2" class="st1" width="1" height="0.8"/>
<rect x="1.7" y="8.2" class="st1" width="1" height="0.8"/>
</g>
<g>
<rect x="3.6" class="st0" width="1" height="0.8"/>
<rect x="3.6" y="2.1" class="st0" width="1" height="0.8"/>
<rect x="3.6" y="4.1" class="st0" width="1" height="0.8"/>
<rect x="3.6" y="6.2" class="st0" width="1" height="0.8"/>
</g>
<g>
<rect x="5.4" class="st1" width="1" height="0.8"/>
<rect x="5.4" y="2.1" class="st1" width="1" height="0.8"/>
<rect x="5.4" y="4.1" class="st1" width="1" height="0.8"/>
</g>
<g>
<rect x="7.1" y="0" class="st0" width="1" height="0.8"/>
<rect x="7.1" y="2.1" class="st0" width="1" height="0.8"/>
</g>
<g>
<rect x="8.7" class="st1" width="1" height="0.8"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,43 @@
<?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 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_00000139282756432431693520000014554874042273548179_);fill:#041725;}
.st1{clip-path:url(#SVGID_00000139282756432431693520000014554874042273548179_);}
.st2{clip-path:url(#SVGID_00000180351338875884756140000007490444363737273490_);}
.st3{opacity:0.8;fill:#35EDED;enable-background:new ;}
.st4{fill:#35EDED;}
</style>
<g>
<defs>
<polygon id="SVGID_1_" points="0,6 6.1,12 12,12 12,0 0,0 "/>
</defs>
<clipPath id="SVGID_00000108283119261920149820000010393207167217912208_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<rect style="clip-path:url(#SVGID_00000108283119261920149820000010393207167217912208_);fill:#041725;" width="12" height="12"/>
<g style="clip-path:url(#SVGID_00000108283119261920149820000010393207167217912208_);">
<g>
<defs>
<rect id="SVGID_00000118377240633176785250000005727722924531941272_" y="1.9" width="11" height="10.1"/>
</defs>
<clipPath id="SVGID_00000117676141971077797980000001536752723917697420_">
<use xlink:href="#SVGID_00000118377240633176785250000005727722924531941272_" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#SVGID_00000117676141971077797980000001536752723917697420_);">
<path class="st3" d="M16.5,256.3c-1.2-0.9-2.4-0.2-2.6,0.8H8v26.3h-792.4l-5.7-5.7v-4.5l0,0v-1.3h-4.1v1.3h3.4v4.7l6.1,6.1H-0.5
l1.7,2.8h10.1v-8.4l-2.7-1.8v-18.9h5.3c0.2,0.7,0.8,1.2,1.5,1.2C16.6,259,17.5,257.6,16.5,256.3z M15.4,258.4
c-0.5,0-0.9-0.4-0.9-0.9s0.4-0.9,0.9-0.9s0.9,0.4,0.9,0.9S15.9,258.4,15.4,258.4z"/>
<polyline class="st3" points="0.8,4.7 8,11.8 8,250.1 8.6,250.1 8.6,11.5 1.1,4 "/>
<polyline class="st3" points="1.1,4 -790.8,4 -790.8,261.5 -794.2,261.5 -794.2,262.7 -790.1,262.7 -790.1,261.5 -790.1,261.5
-790.1,4.7 0.8,4.7 "/>
<rect x="-794.2" y="269.8" class="st4" width="4.1" height="1.2"/>
<rect x="-794.2" y="267.7" class="st4" width="4.1" height="1.2"/>
<rect x="-794.2" y="265.6" class="st4" width="4.1" height="1.2"/>
<rect x="-794.2" y="263.6" class="st4" width="4.1" height="1.2"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,43 @@
<?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 9.8 23.2" style="enable-background:new 0 0 9.8 23.2;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_00000162336351291435253000000011369610487883135147_);fill:#041725;}
.st1{clip-path:url(#SVGID_00000162336351291435253000000011369610487883135147_);}
.st2{clip-path:url(#SVGID_00000179646246557638455150000007031289474206077343_);}
.st3{opacity:0.8;fill:#35EDED;enable-background:new ;}
.st4{fill:#35EDED;}
</style>
<g>
<defs>
<polygon id="SVGID_1_" points="6,-0.1 6,14.8 9.8,19.3 9.9,23.2 0,23.2 0,-0.1 "/>
</defs>
<clipPath id="SVGID_00000069365692663666114570000004382809312686603691_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<rect x="-0.3" y="-0.1" style="clip-path:url(#SVGID_00000069365692663666114570000004382809312686603691_);fill:#041725;" width="10.2" height="23.3"/>
<g style="clip-path:url(#SVGID_00000069365692663666114570000004382809312686603691_);">
<g>
<defs>
<rect id="SVGID_00000069391242059943023700000011095916327524102832_" x="-0.3" width="10.2" height="23.2"/>
</defs>
<clipPath id="SVGID_00000076592079320817103330000010913419046470824587_">
<use xlink:href="#SVGID_00000069391242059943023700000011095916327524102832_" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#SVGID_00000076592079320817103330000010913419046470824587_);">
<path class="st3" d="M810.7-5.2c-1.2-0.9-2.4-0.2-2.6,0.8h-5.9v26.3H9.8l-5.7-5.7v-4.5l0,0v-1.3H0v1.3h3.4v4.7l6.1,6.1h784.2
l1.7,2.8h10.1v-8.4l-2.7-1.8V-3.8h5.3c0.2,0.7,0.8,1.2,1.5,1.2C810.8-2.5,811.7-3.9,810.7-5.2z M809.6-3.2
c-0.5,0-0.9-0.4-0.9-0.9s0.4-0.9,0.9-0.9s0.9,0.4,0.9,0.9S810.1-3.2,809.6-3.2z"/>
<polygon class="st3" points="4.1,-0.1 4.1,-0.1 4.1,-256.9 795,-256.9 802.2,-249.8 802.2,-11.5 802.8,-11.5 802.8,-250
795.3,-257.6 3.4,-257.6 3.4,-0.1 0,-0.1 0,1.2 4.1,1.2 "/>
<rect y="8.3" class="st4" width="4.1" height="1.2"/>
<rect y="6.2" class="st4" width="4.1" height="1.2"/>
<rect y="4.1" class="st4" width="4.1" height="1.2"/>
<rect y="2" class="st4" width="4.1" height="1.2"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,38 @@
<?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 17.7 36.8" style="enable-background:new 0 0 17.7 36.8;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_00000014592019429068395720000011308713662110083751_);fill:#041725;}
.st1{clip-path:url(#SVGID_00000014592019429068395720000011308713662110083751_);}
.st2{clip-path:url(#SVGID_00000139268676221631833710000004672253205110111671_);}
.st3{opacity:0.8;fill:#35EDED;enable-background:new ;}
</style>
<g>
<defs>
<polygon id="SVGID_1_" points="0,29.7 4.9,29.7 4.9,0.1 17.7,0.1 17.7,36.9 0,36.9 "/>
</defs>
<clipPath id="SVGID_00000146475346453478477000000018158311794988225670_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<rect y="0.1" style="clip-path:url(#SVGID_00000146475346453478477000000018158311794988225670_);fill:#041725;" width="17.7" height="36.8"/>
<g style="clip-path:url(#SVGID_00000146475346453478477000000018158311794988225670_);">
<g>
<defs>
<rect id="SVGID_00000181088581726856941440000011579023093141653907_" y="0.1" width="17.7" height="36.8"/>
</defs>
<clipPath id="SVGID_00000064336413382373671560000002740350498911710124_">
<use xlink:href="#SVGID_00000181088581726856941440000011579023093141653907_" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#SVGID_00000064336413382373671560000002740350498911710124_);">
<path class="st3" d="M17.3,6.3c-1.2-0.9-2.4-0.2-2.6,0.8h-6v26.3h-792.4l-5.7-5.7v-4.5l0,0v-1.3h-4.1v1.3h3.4V28l6.1,6.1H0.3
L2,36.8h10.1v-8.4l-2.7-1.8V7.8h5.3C14.8,8.5,15.4,9,16.2,9C17.4,9,18.3,7.6,17.3,6.3z M16.2,8.4c-0.5,0-0.9-0.4-0.9-0.9
s0.4-0.9,0.9-0.9s0.9,0.4,0.9,0.9S16.7,8.4,16.2,8.4z"/>
<polygon class="st3" points="-789.3,11.5 -789.3,11.5 -789.3,-245.3 1.6,-245.3 8.8,-238.2 8.8,0.1 9.4,0.1 9.4,-238.4
1.9,-246 -790,-246 -790,11.5 -793.4,11.5 -793.4,12.7 -789.3,12.7 "/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,44 @@
<?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 9.7 11.1" style="enable-background:new 0 0 9.7 11.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#3BBBC9;}
.st1{fill:#3B69B1;}
</style>
<g>
<g>
<rect x="8.7" y="10.3" class="st0" width="1" height="0.8"/>
<rect x="8.7" y="8.2" class="st0" width="1" height="0.8"/>
<rect x="8.7" y="6.2" class="st0" width="1" height="0.8"/>
<rect x="8.7" y="4.1" class="st0" width="1" height="0.8"/>
<rect x="8.7" y="2.1" class="st0" width="1" height="0.8"/>
<rect x="8.7" y="0" class="st0" width="1" height="0.8"/>
</g>
<g>
<rect x="7" y="10.3" class="st1" width="1" height="0.8"/>
<rect x="7" y="8.2" class="st1" width="1" height="0.8"/>
<rect x="7" y="6.2" class="st1" width="1" height="0.8"/>
<rect x="7" y="4.1" class="st1" width="1" height="0.8"/>
<rect x="7" y="2.1" class="st1" width="1" height="0.8"/>
</g>
<g>
<rect x="5.1" y="10.3" class="st0" width="1" height="0.8"/>
<rect x="5.1" y="8.2" class="st0" width="1" height="0.8"/>
<rect x="5.1" y="6.2" class="st0" width="1" height="0.8"/>
<rect x="5.1" y="4.1" class="st0" width="1" height="0.8"/>
</g>
<g>
<rect x="3.3" y="10.3" class="st1" width="1" height="0.8"/>
<rect x="3.3" y="8.2" class="st1" width="1" height="0.8"/>
<rect x="3.3" y="6.2" class="st1" width="1" height="0.8"/>
</g>
<g>
<rect x="1.6" y="10.3" class="st0" width="1" height="0.8"/>
<rect x="1.6" y="8.2" class="st0" width="1" height="0.8"/>
</g>
<g>
<rect x="0" y="10.3" class="st1" width="1" height="0.8"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,18 @@
<?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 36.7 19.5" style="enable-background:new 0 0 36.7 19.5;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.6;}
.st1{fill:#FFFFFF;}
.st2{fill:#83FF97;}
</style>
<g class="st0">
<g>
<polygon class="st1" points="0.5,19.3 29.7,19.3 36.4,9.8 29.7,0.2 0.5,0.2 7.1,9.8 "/>
</g>
<g>
<path class="st2" d="M29.8,19.5H0l6.8-9.8L0,0h29.8l6.8,9.8L29.8,19.5z M1,19h28.6l6.5-9.3l-6.5-9.3H1l6.5,9.3L1,19z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 708 B

View File

@ -0,0 +1,14 @@
<?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 36.7 19.5" style="enable-background:new 0 0 36.7 19.5;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.6;}
.st1{fill:#83FF97;}
</style>
<g class="st0">
<g>
<path class="st1" d="M29.8,19.5H0l6.8-9.8L0,0h29.8l6.8,9.8l-0.1,0.1L29.8,19.5z M1,19h28.6l6.5-9.3l-6.5-9.3H1l6.5,9.3L1,19z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 595 B

View File

@ -0,0 +1,14 @@
<?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 24.4 19.5" style="enable-background:new 0 0 24.4 19.5;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.6;}
.st1{fill:#83FF97;}
</style>
<g class="st0">
<g>
<path class="st1" d="M17.5,19.5H0l6.8-9.8L0,0h17.5l6.8,9.8l-0.1,0.1L17.5,19.5z M1,19h16.3l6.5-9.3l-6.5-9.3H1l6.5,9.3L1,19z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 595 B

View File

@ -0,0 +1,9 @@
<?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 24.4 19.5" style="enable-background:new 0 0 24.4 19.5;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.6;fill:#83FF97;}
</style>
<polygon class="st0" points="17.5,0 0,0 6.8,9.8 0,19.5 17.5,19.5 24.3,9.9 24.4,9.8 "/>
</svg>

After

Width:  |  Height:  |  Size: 514 B

View File

@ -0,0 +1 @@
<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 111 7"><defs><style>.cls-1{fill:#5eabea;}.cls-2{fill:#d0032c;}</style></defs><path id="_66" data-name="66" class="cls-1" d="M55.74,7.19A3.7,3.7,0,0,1,59.37,4l51.39-.45L59.37,3.15A3.7,3.7,0,0,1,55.74,0Z"/><path id="_66-2" data-name="66" class="cls-2" d="M55.74,0h0a3.7,3.7,0,0,1-3.63,3.15L0,3.59,52.11,4a3.7,3.7,0,0,1,3.63,3.15Z"/></svg>

After

Width:  |  Height:  |  Size: 424 B

81
src/assets/index.css Normal file
View File

@ -0,0 +1,81 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.arrow {
@apply relative triangle flex justify-center items-center text-lg;
box-shadow: inset 0px 6px 10px -10px rgba(255, 255, 255, 0.8),
inset 0px -6px 10px -10px rgba(255, 255, 255, 0.8);
}
.triangle {
@apply after:block after:absolute after:bottom-0 after:left-[100%]
after:border-t-[1rem] after:border-b-[1rem] after:border-l-[2rem]
after:border-t-transparent after:border-b-transparent after:z-50;
}
.triangle-dark {
@apply after:border-l-info;
}
.triangle-light {
@apply after:border-l-success;
}
.item button {
@apply hover:bg-active !important;
}
/* table */
.content-box-background {
background: linear-gradient(
180deg,
rgba(127, 237, 193, 0.1),
rgba(0, 0, 0, 0),
rgba(127, 237, 193, 0.1)
);
}
}
@layer utilities {
.btn{
@apply whitespace-nowrap px-4 py-1;
text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.9);
box-shadow: 0px 0px 5px rgba(255, 255, 255, 0.8);
}
.btn-success {
@apply text-white border border-active bg-active hover:bg-[theme("colors.green.500")]
}
.btn-info {
@apply text-white border border-info bg-info hover:bg-[theme("colors.sky.400")]
}
.btn-outline-success {
@apply text-white border border-active hover:bg-active bg-transparent
}
.btn-outline-info {
@apply text-white border border-info hover:bg-info bg-transparent
}
.custom-border {
@apply border border-info rounded-md;
}
.btn-text-without-border {
@apply active:border-0 focus:border-0 focus-visible:border-0 active:outline-none focus:outline-none focus-visible:outline-none;
}
.btn-add {
@apply text-white border border-cyan-400 bg-cyan-400 hover:bg-[theme("colors.cyan.500")]
}
.btn-search {
@apply text-white border border-sky-400 bg-sky-400 hover:bg-[theme("colors.sky.500")]
}
.btn-export {
@apply text-white border border-emerald-400 bg-emerald-400 hover:bg-[theme("colors.emerald.500")]
}
}

1
src/assets/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 150 KiB

29
src/assets/main.css Normal file
View File

@ -0,0 +1,29 @@
@import "./base.css";
#app {
overflow: hidden;
font-weight: normal;
background-color: theme("colors.body");
background-image: url("./img/background.jpg");
background-size: cover;
color: #fff;
min-height: 100dvh;
}
::-webkit-scrollbar {
width: 5px !important;
height: 8px !important;
}
/* Track */
::-webkit-scrollbar-track {
box-shadow: inset 0 0 5px grey;
border-radius: 10px;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: theme("colors.info");
border-radius: 10px;
box-shadow: theme("boxShadow.custom");
}

40
src/assets/pagination.css Normal file
View File

@ -0,0 +1,40 @@
.page-box ul {
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
font-size: 1rem;
color: #fff;
margin-bottom: 10px;
}
.page-box ul li {
padding: 10px;
white-space: nowrap;
cursor: pointer;
}
.page-box ul .ant-pagination-item {
background-image: url(./img/pagination/small-btn.svg);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
padding: 10px 15px 10px 25px;
background-color: transparent;
display: flex;
justify-content: center;
align-items: center;
border: none;
}
.page-box ul .ant-pagination-item.ant-pagination-item-active {
background-image: url(./img/pagination/small-btn02.svg);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
padding: 10px 15px 10px 25px;
}
.page-box .ant-pagination-item a {
color: #fff;
}

122
src/assets/table.css Normal file
View File

@ -0,0 +1,122 @@
/**資料框**/
.ant-table {
width: 100%;
margin-bottom: 1rem;
background-color: transparent !important;
color: white;
}
.ant-table::-webkit-scrollbar-thumb {
background-color: theme("colors.info") !important;
}
.ant-table th.ant-table-cell::before{
height: 100% !important;
}
.content-box {
border: 1px solid #35eded;
padding: 5px;
position: relative;
margin-bottom: 15px;
background-color: theme("colors.body");
}
.content-box table,
.content-box table th {
border-radius: 0 !important;
}
.content-box .ant-table th.ant-table-cell,
.content-box .ant-table td.ant-table-cell {
border-color: #fff !important;
color: #fff !important;
font-size: 1rem !important;
font-weight: 300 !important;
border-right: 1px solid #fff !important;
text-align: center !important;
padding: 0.5rem 0.75rem !important;
background-color: transparent !important;
}
.content-box .ant-table th.ant-table-cell.ant-table-cell-fix-left,
.content-box .ant-table th.ant-table-cell.ant-table-cell-fix-right {
background-color: theme("colors.body") !important;
color: white;
}
.content-box .ant-table th.ant-table-cell {
border-bottom: 1px solid #e9e9e9 !important;
}
.content-box .ant-table tr td:last-child,
.content-box .ant-table tr:first-child th:last-child {
border-right: 0 !important;
}
.content-box .ant-table tr:last-child td {
border-bottom: 0 !important;
}
/**資料框裝飾**/
.content-box::before {
content: "" !important;
background: url(./img/table/content-box-background01.svg) center center !important;
position: absolute !important;
left: 4px !important;
top: 4px !important;
height: 20px !important;
width: 20px !important;
background-repeat: no-repeat !important;
z-index: 1 !important;
}
.content-box::after {
content: "" !important;
background: url(./img/table/content-box-background05.svg) center center !important;
position: absolute !important;
right: 4px !important;
bottom: 4px !important;
height: 20px !important;
width: 20px !important;
background-repeat: no-repeat !important;
z-index: 3 !important;
}
.content-box .page-box::before {
content: "" !important;
background: url(./img/table/content-box-background03.svg) center center !important;
position: absolute !important;
left: -1.2% !important;
bottom: -2px !important;
height: 56px !important;
width: 30px !important;
background-repeat: no-repeat !important;
z-index: 2 !important;
}
.content-box .page-box::after {
content: "" !important;
background: url(./img/table/content-box-background04.svg) center center !important;
position: absolute !important;
right: -27px !important;
bottom: -7px !important;
height: 65px !important;
width: 50px !important;
background-repeat: no-repeat !important;
z-index: 2 !important;
}
.content-box .content-decoration {
@apply px-2;
}
.content-box .content-decoration::before {
content: "" !important;
background: url(./img/table/content-box-background02.svg) center center !important;
position: absolute !important;
right: -10px !important;
top: -10px !important;
height: 30px !important;
width: 29px !important;
background-repeat: no-repeat !important;
z-index: 1 !important;
}

View File

@ -0,0 +1,32 @@
<script setup></script>
<template>
<div class="w-full h-full flex items-center justify-center">
<div class="loader"></div>
</div>
</template>
<style lang="css" scoped>
.loader {
width: 20%;
height: 22px;
border-radius: 20px;
color: theme(colors.success);
border: 2px solid theme(colors.success);
position: relative;
}
.loader::before {
content: "";
position: absolute;
margin: 2px;
inset: 0 100% 0 0;
border-radius: inherit;
background: currentColor;
animation: l6 2s infinite;
}
@keyframes l6 {
100% {
inset: 0;
}
}
</style>

View File

@ -0,0 +1,44 @@
<template>
<i :style="getStyle">
<svg :class="class" aria-hidden="true">
<use :xlink:href="symbolId" :stroke="color" :fill="color" />
</svg>
</i>
</template>
<script setup name="SvgIcon">
import { computed } from 'vue'
const props = defineProps({
prefix: {
type: String,
default: 'icon',
},
name: {
type: String,
required: true,
},
color: {
type: String,
default: 'transparent',
},
size: {
type: [Number, String],
default: 10,
},
class: {
type: String,
default: "w-10 h-10",
},
})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
const getStyle = computed(() => {
const { size } = props
let s = `${size}`
s = `${s.replace('px', '')}px`
return {
fontSize: s,
}
})
</script>

View File

@ -0,0 +1,87 @@
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import { getAlertLog } from "@/apis/alert";
import dayjs from "dayjs";
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(() => {
getAlarmData();
intervalId = setInterval(() => {
getAlarmData();
}, 30 * 1000);
});
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 dataSource" :key="alarm.id">
<div
class="w-full shadow-xl border border-success bg-body bg-opacity-80"
>
<div class="p-5">
<p class="text-base flex justify-between">
<span>
<font-awesome-icon
:icon="['fas', 'exclamation-triangle']"
class="text-warning mr-2"
/>
<span>{{ $t("alarm.notify") }}</span></span
>
<small>
<span class="mr-4"
>{{ alarm.created_at }}</span
>
<!-- <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.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>
</li>
</ul>
</div>
</template>
<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;
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;
content: "";
}
</style>

View File

@ -0,0 +1,51 @@
<script setup>
import { onMounted, ref } from "vue";
import AlarmCards from "./AlarmCards.vue";
const showErr = ref(false);
const toggleErrIcon = () => {
console.log("Toggle");
showErr.value = !showErr.value;
};
</script>
<template>
<div class="drawer drawer-end">
<input id="alarm" type="checkbox" class="drawer-toggle" />
<div class="drawer-content">
<!-- Page content here -->
<label
for="alarm"
class="drawer-button flex flex-col justify-center items-center bg-transparent text-white"
@click="toggleErrIcon"
>
<font-awesome-icon
v-if="!showErr"
:icon="['fas', 'comment-dots']"
class="text-lg lg:text-2xl mb-1"
/>
<font-awesome-icon
v-else
:icon="['fas', 'comment-slash']"
class="text-lg lg:text-2xl mb-1"
/>
<span class="text-xs lg:text-sm block"> {{ $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"
>
<AlarmCards />
</div>
</div>
</template>
<style lang="scss" scoped>
.drawer-toggle,
.drawer-button {
outline: none !important;
outline-offset: 0 !important;
border: 0 !important;
}
</style>

View File

@ -0,0 +1,57 @@
<script setup>
import * as echarts from "echarts";
import { onMounted, ref, markRaw, watch, onBeforeUnmount } from "vue";
const props = defineProps({
option: Object, //
class: String, //
id: String, // ID
});
let chart = ref(null); //
let dom = ref(null); // DOM
//
function init() {
if (dom.value) {
let echart = echarts;
chart.value = markRaw(echart.init(dom.value)); //
chart.value.setOption(props.option); //
}
}
//
onMounted(() => {
if (!chart.value && dom.value) {
init();
}
});
// props.option
watch(
() => props.option,
(newOption) => {
if (chart.value) {
chart.value.setOption(newOption); //
}
},
{ deep: true }
);
//
onBeforeUnmount(() => {
if (chart.value) {
chart.value.dispose(); //
}
});
defineExpose({
chart, // chart
});
</script>
<template>
<div :id="id" :class="class" ref="dom" style="height: 100%; width: 100%;"></div>
</template>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,83 @@
<script setup>
import * as echarts from "echarts";
import { onMounted, ref, markRaw } from "vue";
import axios from "axios";
const props = defineProps({
option: Object,
className: String,
id: String,
svg: Object,
getCoordinate: {
type: Function,
default: null,
},
});
let chart = ref(null);
let dom = ref(null);
let currentClickPosition = ref([]);
async function updateSvg(svg, option) {
if (!chart.value && dom.value && svg) {
init();
} else {
clear();
}
axios.get(svg.path).then(({ data }) => {
echarts.registerMap(svg.full_name, { svg: data });
chart.value.setOption(option);
if (props.getCoordinate) {
chart.value.getZr().on("click", function (params) {
var pixelPoint = [params.offsetX, params.offsetY];
var dataPoint = chart.value.convertFromPixel(
{ geoIndex: 0 },
pixelPoint
);
currentClickPosition.value = dataPoint;
props.getCoordinate(dataPoint);
const updatedData = option.series.data
.filter(
(point) => !(point.itemStyle && point.itemStyle.color === "#0000FF")
)
.concat({
value: dataPoint, //
itemStyle: { color: "#0000FF" }, //
});
chart.value.setOption({
series: {
data: updatedData,
},
});
});
}
});
console.log("updateSvg", svg.path);
}
function clear() {
chart.value.clear();
}
function init() {
const curChart = echarts.init(dom.value);
chart.value = markRaw(curChart);
}
onMounted(() => {
if (!chart.value && dom.value && props.svg) {
init();
}
});
defineExpose({
chart,
currentClickPosition,
updateSvg,
});
</script>
<template>
<div :id="id" class="min-h-full max-h-fit w-full" ref="dom"></div>
</template>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,34 @@
<script setup>
import * as echarts from "echarts";
import { onMounted, ref, markRaw } from "vue";
const props = defineProps({
option: Object,
class: String,
id: String,
});
let chart = ref(null);
let dom = ref(null);
function init() {
let echart = echarts;
chart.value = markRaw(echart.init(dom.value));
chart.value.setOption(props.option);
}
onMounted(() => {
if (!chart.value && dom.value) {
init();
}
});
defineExpose({
chart,
});
</script>
<template>
<div :id="id" :class="class" ref="dom"></div>
</template>
<style lang="scss" scoped></style>

Some files were not shown because too many files have changed in this diff Show More