設備管理:選擇圖資圖片資料夾路徑、樓層編輯與刪除 | 系統監控照片初切版
This commit is contained in:
parent
364ac7b730
commit
1dbd58b965
@ -11,6 +11,7 @@ export const DELETE_ASSET_ITEM_API = `/AssetManage/DeleteAsset`;
|
|||||||
export const GET_ASSET_FLOOR_LIST_API = `/AssetManage/GetFloorList`;
|
export const GET_ASSET_FLOOR_LIST_API = `/AssetManage/GetFloorList`;
|
||||||
|
|
||||||
export const POST_ASSET_FLOOR_API = `/AssetManage/SaveFloor`;
|
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_IOT_LIST_API = `/AssetManage/GetIOTList`;
|
||||||
export const GET_ASSET_SUB_POINT_API = `/AssetManage/GetSubPoint`;
|
export const GET_ASSET_SUB_POINT_API = `/AssetManage/GetSubPoint`;
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
GET_ASSET_SINGLE_API,
|
GET_ASSET_SINGLE_API,
|
||||||
GET_ASSET_FLOOR_LIST_API,
|
GET_ASSET_FLOOR_LIST_API,
|
||||||
POST_ASSET_FLOOR_API,
|
POST_ASSET_FLOOR_API,
|
||||||
|
DELETE_ASSET_FLOOR_API,
|
||||||
GET_ASSET_IOT_LIST_API,
|
GET_ASSET_IOT_LIST_API,
|
||||||
DELETE_ASSET_ITEM_API,
|
DELETE_ASSET_ITEM_API,
|
||||||
POST_ASSET_SINGLE_API,
|
POST_ASSET_SINGLE_API,
|
||||||
@ -143,6 +144,15 @@ export const postAssetFloor = async (formData) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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) => {
|
export const getAssetIOTList = async (sub_system_tag, points) => {
|
||||||
const res = await instance.post(GET_ASSET_IOT_LIST_API, {
|
const res = await instance.post(GET_ASSET_IOT_LIST_API, {
|
||||||
sub_system_tag,
|
sub_system_tag,
|
||||||
|
35
src/components/customUI/Menu.vue
Normal file
35
src/components/customUI/Menu.vue
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<script setup>
|
||||||
|
import Checkbox from "@/components/customUI/Checkbox.vue";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
import { computed, defineProps, onMounted, ref, watch } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
item: Object,
|
||||||
|
selectedId: String,
|
||||||
|
menuCheck:Function,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<li>
|
||||||
|
<!-- 項目無子層級 -->
|
||||||
|
<a v-if="item.children.length === 0">
|
||||||
|
<Checkbox
|
||||||
|
:title="item.name"
|
||||||
|
:checked="selectedId === item.id"
|
||||||
|
@click="() => menuCheck(item.id)"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<!-- 項目有子層級 -->
|
||||||
|
<details v-else>
|
||||||
|
<summary>{{ item.name }}</summary>
|
||||||
|
<ul>
|
||||||
|
<li v-for="(child, index) in item.children" :key="index">
|
||||||
|
<Menu :item="child" :selectedId="selectedId" :menuCheck="menuCheck"></Menu>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped></style>
|
@ -166,7 +166,7 @@ watch(
|
|||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
withStyle ? 'table' : 'table border',
|
withStyle ? 'table' : 'table border',
|
||||||
currentDataSource.length === 0 ? 'h-96' : ''
|
currentDataSource.length === 0 ? 'h-28' : ''
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
@ -3,9 +3,6 @@ import { getBuildings } from "@/apis/building";
|
|||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import useBuildingStore from "@/stores/useBuildingStore";
|
import useBuildingStore from "@/stores/useBuildingStore";
|
||||||
|
|
||||||
// const buildings = ref(null);
|
|
||||||
// const selectedBuilding = ref(null);
|
|
||||||
|
|
||||||
const store = useBuildingStore();
|
const store = useBuildingStore();
|
||||||
|
|
||||||
const getBui = async () => {
|
const getBui = async () => {
|
||||||
@ -15,6 +12,10 @@ const getBui = async () => {
|
|||||||
store.selectedBuilding = res?.data[0];
|
store.selectedBuilding = res?.data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const selectBuilding = (bui) => {
|
||||||
|
store.selectedBuilding = bui;
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getBui();
|
getBui();
|
||||||
});
|
});
|
||||||
@ -25,10 +26,10 @@ onMounted(() => {
|
|||||||
<div
|
<div
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="button"
|
role="button"
|
||||||
class="text-white ml-8 text-lg font-semiLight "
|
class="text-white ml-8 text-lg font-semiLight"
|
||||||
>
|
>
|
||||||
{{ store.selectedBuilding?.full_name }}
|
{{ store.selectedBuilding?.full_name }}
|
||||||
<font-awesome-icon :icon="['fas', 'angle-down']" class="ml-1"/>
|
<font-awesome-icon :icon="['fas', 'angle-down']" class="ml-1" />
|
||||||
</div>
|
</div>
|
||||||
<ul
|
<ul
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@ -38,6 +39,7 @@ onMounted(() => {
|
|||||||
class="text-white my-1 text-base"
|
class="text-white my-1 text-base"
|
||||||
v-for="bui in store.buildings"
|
v-for="bui in store.buildings"
|
||||||
:key="bui.building_tag"
|
:key="bui.building_tag"
|
||||||
|
@click="selectBuilding(bui)"
|
||||||
>
|
>
|
||||||
{{ bui.full_name }}
|
{{ bui.full_name }}
|
||||||
</li>
|
</li>
|
||||||
|
@ -38,6 +38,9 @@ instance.interceptors.response.use(
|
|||||||
function (error) {
|
function (error) {
|
||||||
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
||||||
// Do something with response error
|
// Do something with response error
|
||||||
|
if (response && response.status === 401) {
|
||||||
|
window.location.href = "/logout";
|
||||||
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,7 @@ import { ref, inject, onBeforeMount, onMounted, watch } from "vue";
|
|||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import "yup-phone-lite";
|
import "yup-phone-lite";
|
||||||
import AssetTableModalLeftInfoIoT from "./AssetTableModalLeftInfoIoT.vue";
|
import AssetTableModalLeftInfoIoT from "./AssetTableModalLeftInfoIoT.vue";
|
||||||
|
import AssetTableModalLeftInfoGraph from "./AssetTableModalLeftInfoGraph.vue";
|
||||||
import { getOperationCompanyList } from "@/apis/operation";
|
import { getOperationCompanyList } from "@/apis/operation";
|
||||||
import useSearchParam from "@/hooks/useSearchParam";
|
import useSearchParam from "@/hooks/useSearchParam";
|
||||||
import OperationTableModal from "@/views/operation/components/OperationTableModal.vue";
|
import OperationTableModal from "@/views/operation/components/OperationTableModal.vue";
|
||||||
@ -199,7 +200,8 @@ const openCompanyAddModal = () => {
|
|||||||
{{ $t("button.add") }}
|
{{ $t("button.add") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<Upload
|
<AssetTableModalLeftInfoGraph />
|
||||||
|
<!-- <Upload
|
||||||
name="oriFile"
|
name="oriFile"
|
||||||
:fileList="formState.oriFile"
|
:fileList="formState.oriFile"
|
||||||
:getFileList="updateFileList"
|
:getFileList="updateFileList"
|
||||||
@ -208,7 +210,7 @@ const openCompanyAddModal = () => {
|
|||||||
:baseUrl="FILE_BASEURL"
|
:baseUrl="FILE_BASEURL"
|
||||||
>
|
>
|
||||||
<template #topLeft>{{ $t("assetManagement.oriFile") }}</template>
|
<template #topLeft>{{ $t("assetManagement.oriFile") }}</template>
|
||||||
</Upload>
|
</Upload> -->
|
||||||
<AssetTableModalLeftInfoIoT />
|
<AssetTableModalLeftInfoIoT />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -0,0 +1,146 @@
|
|||||||
|
<script setup>
|
||||||
|
import { getSideBar, getGraphData } from "@/apis/graph";
|
||||||
|
import { ref, computed, inject, watch, onMounted } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import Menu from "@/components/customUI/Menu.vue";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { formState } = inject("asset_table_modal_form");
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
title: t("assetManagement.index"),
|
||||||
|
key: "index",
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("graphManagement.oriOrgName"),
|
||||||
|
key: "oriOrgName",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const graphData = ref([]);
|
||||||
|
const menuData = ref([]);
|
||||||
|
const selectedId = ref(null);
|
||||||
|
const dataSource = ref([]);
|
||||||
|
|
||||||
|
const getMenuData = async () => {
|
||||||
|
const res = await getSideBar();
|
||||||
|
graphData.value = res.data;
|
||||||
|
console.log(" graphData", graphData.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getData = async (id) => {
|
||||||
|
const res = await getGraphData(id);
|
||||||
|
if (res.isSuccess) {
|
||||||
|
dataSource.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildMenuTree = (data) => {
|
||||||
|
const map = new Map();
|
||||||
|
const menu = [];
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
map.set(item.id, { ...item, children: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
const parent = map.get(item.parent_id);
|
||||||
|
if (item.parent_id === 0) {
|
||||||
|
menu.push(map.get(item.id));
|
||||||
|
} else {
|
||||||
|
if (parent) {
|
||||||
|
parent.children.push(map.get(item.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
};
|
||||||
|
|
||||||
|
const openModal = () => {
|
||||||
|
asset_add_graph_item.showModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOk = () => {
|
||||||
|
console.log("selectedId", selectedId.value);
|
||||||
|
formState.value.graph = selectedId.value;
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
asset_add_graph_item.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const menuCheck = (id) => {
|
||||||
|
selectedId.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(selectedId, (newId) => {
|
||||||
|
getData(newId);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getMenuData();
|
||||||
|
menuData.value = buildMenuTree(graphData.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col mt-8 col-span-2">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<span class="label-text-alt text-lg"> 圖片 </span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm btn-success"
|
||||||
|
@click.stop.prevent="openModal"
|
||||||
|
>
|
||||||
|
圖資管理
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Table
|
||||||
|
:columns="columns"
|
||||||
|
:dataSource="dataSource"
|
||||||
|
:withStyle="false"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ record, column, index }">
|
||||||
|
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
<Modal
|
||||||
|
id="asset_add_graph_item"
|
||||||
|
:title="t('graphManagement.title')"
|
||||||
|
:onCancel="onCancel"
|
||||||
|
width="500"
|
||||||
|
>
|
||||||
|
<template #modalContent>
|
||||||
|
<ul class="menu bg-base-200 rounded-box text-lg w-full mt-3">
|
||||||
|
<li v-for="(item, index) in menuData" :key="index">
|
||||||
|
<Menu
|
||||||
|
:item="item"
|
||||||
|
:selectedId="selectedId"
|
||||||
|
:menuCheck="menuCheck"
|
||||||
|
></Menu>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
<template #modalAction>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
class="btn btn-outline-success mr-2"
|
||||||
|
@click.prevent="onCancel"
|
||||||
|
>
|
||||||
|
{{ $t("button.cancel") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-outline-success"
|
||||||
|
@click.prevent="onOk"
|
||||||
|
>
|
||||||
|
{{ $t("button.submit") }}
|
||||||
|
</button>
|
||||||
|
</template></Modal
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
@ -1,7 +1,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, inject, onBeforeMount, watch, computed } from "vue";
|
import { onMounted, ref, inject, onBeforeMount, watch, computed } from "vue";
|
||||||
import EffectScatter from "@/components/chart/EffectScatter.vue";
|
import EffectScatter from "@/components/chart/EffectScatter.vue";
|
||||||
import { getAssetFloorList, postAssetFloor } from "@/apis/asset";
|
import {
|
||||||
|
getAssetFloorList,
|
||||||
|
postAssetFloor,
|
||||||
|
deleteAssetFloor,
|
||||||
|
} from "@/apis/asset";
|
||||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
@ -27,6 +31,8 @@ onBeforeMount(() => {
|
|||||||
|
|
||||||
const asset_floor_chart = ref(null);
|
const asset_floor_chart = ref(null);
|
||||||
const currentFloor = ref(null);
|
const currentFloor = ref(null);
|
||||||
|
const selectedOption = ref("add");
|
||||||
|
|
||||||
const defaultOption = (map, data = []) => ({
|
const defaultOption = (map, data = []) => ({
|
||||||
tooltip: {},
|
tooltip: {},
|
||||||
geo: {
|
geo: {
|
||||||
@ -99,6 +105,25 @@ onMounted(() => {
|
|||||||
|
|
||||||
// modal
|
// modal
|
||||||
const openModal = () => {
|
const openModal = () => {
|
||||||
|
if (selectedOption.value === "add") {
|
||||||
|
FloorFormState.value = {
|
||||||
|
building_tag: "F3",
|
||||||
|
full_name: "",
|
||||||
|
floorFile: [],
|
||||||
|
};
|
||||||
|
} else if (selectedOption.value === "edit") {
|
||||||
|
const floor = floors.value.find(
|
||||||
|
(f) => f.floor_guid === formState.value.floor_guid
|
||||||
|
);
|
||||||
|
if (floor) {
|
||||||
|
console.log("floor", floor);
|
||||||
|
FloorFormState.value = {
|
||||||
|
building_tag: "F3",
|
||||||
|
full_name: floor.full_name,
|
||||||
|
floorFile: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
asset_add_floor.showModal();
|
asset_add_floor.showModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,6 +141,7 @@ const floorScheme = yup.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const updateFileList = (files) => {
|
const updateFileList = (files) => {
|
||||||
|
console.log("file",files)
|
||||||
FloorFormState.value.floorFile = files;
|
FloorFormState.value.floorFile = files;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -143,6 +169,16 @@ const onOk = async () => {
|
|||||||
onCancel();
|
onCancel();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const onDelete = async () => {
|
||||||
|
console.log("guild", formState.value.floor_guid);
|
||||||
|
// const res = await deleteAssetFloor({
|
||||||
|
// floor_guid: formState.value.floor_guid,
|
||||||
|
// });
|
||||||
|
// if (res.isSuccess) {
|
||||||
|
// getFloors(); // 更新樓層列表
|
||||||
|
// formState.value.floor_guid = ""; // 重置選取
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
FloorFormState.value = {
|
FloorFormState.value = {
|
||||||
@ -158,10 +194,10 @@ const onCancel = () => {
|
|||||||
<!-- 平面圖 -->
|
<!-- 平面圖 -->
|
||||||
|
|
||||||
<div class="flex items-center justify-between mb-5">
|
<div class="flex items-center justify-between mb-5">
|
||||||
<div class="flex justify-start">
|
<div className="join">
|
||||||
<Select
|
<Select
|
||||||
:value="formState"
|
:value="formState"
|
||||||
selectClass="border-info focus-within:border-info"
|
selectClass="border-info focus-within:border-info rounded-r-none"
|
||||||
name="floor_guid"
|
name="floor_guid"
|
||||||
Attribute="full_name"
|
Attribute="full_name"
|
||||||
:options="floors"
|
:options="floors"
|
||||||
@ -169,15 +205,23 @@ const onCancel = () => {
|
|||||||
>
|
>
|
||||||
<template #topLeft>{{ $t("assetManagement.floor") }}</template>
|
<template #topLeft>{{ $t("assetManagement.floor") }}</template>
|
||||||
</Select>
|
</Select>
|
||||||
|
<select
|
||||||
|
v-model="selectedOption"
|
||||||
|
className="select border-info focus-within:border-info join-item mt-11"
|
||||||
|
>
|
||||||
|
<option value="add" selected>{{ $t("button.add") }}</option>
|
||||||
|
<option value="edit">{{ $t("button.edit") }}</option>
|
||||||
|
<option value="delete">{{ $t("button.delete") }}</option>
|
||||||
|
</select>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-success mt-10 ml-5"
|
class="btn btn-success join-item mt-11"
|
||||||
@click="openModal"
|
@click="selectedOption === 'delete' ? onDelete() : openModal()"
|
||||||
|
:aria-label="$t('button.submit')"
|
||||||
>
|
>
|
||||||
{{ $t("assetManagement.add_floor") }}
|
{{ $t("button.submit") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- <button type="button" class="btn btn-success mt-10">確認座標</button> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<EffectScatter
|
<EffectScatter
|
||||||
|
@ -25,8 +25,8 @@ watch(selectedFloor, (newValue) => {
|
|||||||
<p class="title">{{ d.full_name }}</p>
|
<p class="title">{{ d.full_name }}</p>
|
||||||
<div class="grid grid-cols-3 gap-5">
|
<div class="grid grid-cols-3 gap-5">
|
||||||
<div class="col-auto relative" v-for="device in d.device_list" :key="device.device_guid">
|
<div class="col-auto relative" v-for="device in d.device_list" :key="device.device_guid">
|
||||||
<div class="item h-36">
|
<div class="item h-full">
|
||||||
<div class="left w-4/5 h-full flex flex-wrap justify-center">
|
<div class="left h-full flex flex-wrap justify-center">
|
||||||
<div class="sec02 w-full">
|
<div class="sec02 w-full">
|
||||||
<img v-if="device.device_image_url" :src="device.device_image_url" alt="" class="w-8 h-8">
|
<img v-if="device.device_image_url" :src="device.device_image_url" alt="" class="w-8 h-8">
|
||||||
<span class="w-8 h-8" v-else></span>
|
<span class="w-8 h-8" v-else></span>
|
||||||
@ -35,7 +35,7 @@ watch(selectedFloor, (newValue) => {
|
|||||||
<div class="flex justify-between w-full self-end">
|
<div class="flex justify-between w-full self-end">
|
||||||
<div class="sec03">
|
<div class="sec03">
|
||||||
<span class="w-5 h-5 rounded-full" :style="{ backgroundColor: device.device_normal_color }"></span>
|
<span class="w-5 h-5 rounded-full" :style="{ backgroundColor: device.device_normal_color }"></span>
|
||||||
<span class="mx-2">{{ $t("system.status") }}:</span>
|
<span class="mx-2">{{ $t("system.status") }}:</span>
|
||||||
<span>{{ device.device_status }}</span>
|
<span>{{ device.device_status }}</span>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn-text border-0 "
|
<button class="btn-text border-0 "
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { defineProps, inject, ref, watch } from "vue";
|
import { defineProps, inject, ref, watch } from "vue";
|
||||||
import SystemInfoModalDesktop from "./SystemInfoModalDesktop.vue";
|
import SystemInfoModalDesktop from "./SystemInfoModalDesktop.vue";
|
||||||
import SystemInfoModalCog from "./SystemInfoModalCog.vue";
|
import SystemInfoModalCog from "./SystemInfoModalCog.vue";
|
||||||
|
import SystemInfoModalImage from "./SystemInfoModalImage.vue";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ const currentTab = ref("desktop");
|
|||||||
const tabs = {
|
const tabs = {
|
||||||
desktop: SystemInfoModalDesktop,
|
desktop: SystemInfoModalDesktop,
|
||||||
cog: SystemInfoModalCog,
|
cog: SystemInfoModalCog,
|
||||||
|
image: SystemInfoModalImage
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeOpenKey = (key) => {
|
const changeOpenKey = (key) => {
|
||||||
@ -34,6 +36,10 @@ const onCancel = () => {
|
|||||||
<font-awesome-icon :icon="['fas', 'desktop']" size="lg"
|
<font-awesome-icon :icon="['fas', 'desktop']" size="lg"
|
||||||
:class="twMerge(currentTab === 'desktop' ? 'text-success' : 'text-[#a5abb1]')" />
|
:class="twMerge(currentTab === 'desktop' ? 'text-success' : 'text-[#a5abb1]')" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('image')">
|
||||||
|
<font-awesome-icon :icon="['fas', 'image']" size="lg"
|
||||||
|
:class="twMerge(currentTab === 'image' ? 'text-success' : 'text-[#a5abb1]')" />
|
||||||
|
</Button>
|
||||||
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('cog')">
|
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('cog')">
|
||||||
<font-awesome-icon :icon="['fas', 'cog']" size="lg"
|
<font-awesome-icon :icon="['fas', 'cog']" size="lg"
|
||||||
:class="twMerge(currentTab === 'cog' ? 'text-success' : 'text-[#a5abb1]')" />
|
:class="twMerge(currentTab === 'cog' ? 'text-success' : 'text-[#a5abb1]')" />
|
||||||
|
59
src/views/system/components/SystemInfoModalImage.vue
Normal file
59
src/views/system/components/SystemInfoModalImage.vue
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<script setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-carousel arrows class="mt-5 shadow-lg">
|
||||||
|
<template #prevArrow>
|
||||||
|
<div class="custom-slick-arrow" style="left: 10px; z-index: 1">
|
||||||
|
<font-awesome-icon
|
||||||
|
:icon="['fas', 'chevron-left']"
|
||||||
|
size="lg"
|
||||||
|
class="text-[#a5abb1]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #nextArrow>
|
||||||
|
<div class="custom-slick-arrow" style="right: 10px">
|
||||||
|
<font-awesome-icon
|
||||||
|
:icon="['fas', 'chevron-right']"
|
||||||
|
size="lg"
|
||||||
|
class="text-[#a5abb1]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div><img src="https://picsum.photos/id/122/300/300" /></div>
|
||||||
|
<div><img src="https://picsum.photos/id/127/300/300" /></div>
|
||||||
|
<div><img src="https://picsum.photos/id/124/300/300" /></div>
|
||||||
|
<div><img src="https://picsum.photos/id/125/300/300" /></div>
|
||||||
|
</a-carousel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* For demo */
|
||||||
|
:deep(.slick-slide) {
|
||||||
|
text-align: center;
|
||||||
|
background: #1d2429;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow) {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(31, 45, 61, 0.11);
|
||||||
|
transition: ease all 0.3s;
|
||||||
|
opacity: 0.3;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:before) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
:deep(.slick-arrow.custom-slick-arrow:hover) {
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.slick-slide img) {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user