明树Git Lab

Commit 5d2eb68b authored by chenron's avatar chenron

提交

parent ad49af42
...@@ -6,6 +6,4 @@ ...@@ -6,6 +6,4 @@
<script setup></script> <script setup></script>
<style scoped lang="less"> <style scoped lang="less"></style>
@import "./assets/font/font.less";
</style>
@font-face {
font-family: 'YouSheBiaoTiHei-Regular';
src: url('../font/字体/优设标题黑.ttf');
font-weight: normal;
font-style: normal;
}
\ No newline at end of file
@font-face {
font-family: 'YouSheBiaoTiHei';
src: url('../fonts/优设标题黑.ttf') format('woff');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'YouSheBiaoTiYuan';
src: url('../fonts/优设标题圆.otf') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'DIN';
src: url('../fonts/0.otf') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Alibaba PuHuiTi';
src: url('../fonts/2.otf') format('woff');
font-weight: normal;
font-style: normal;
}
\ No newline at end of file
This diff is collapsed.
...@@ -5,22 +5,34 @@ ...@@ -5,22 +5,34 @@
<div class="stat-card-value"> <div class="stat-card-value">
<div class="card-value-top"> <div class="card-value-top">
<div> <div>
<p class="pro-title">11月完成</p> <p class="pro-title">{{ item.protitle }}</p>
<p class="pro-value">1.1亿元</p> <p class="pro-value">{{ item.proValue }}<span>亿元</span></p>
</div> </div>
<div> <div>
<p class="pro-title">第三季度完成</p> <p class="pro-title">{{ item.thirdTtile }}</p>
<p class="pro-value">4.21亿元</p> <p class="pro-value">{{ item.thirdValue }}<span>亿元</span></p>
</div> </div>
</div> </div>
<div class="card-value-bottom"> <div class="card-value-bottom">
<div> <div>
<p class="pro-title">2025年累计完成</p> <p class="pro-title">2025年累计完成</p>
<p class="pro-value">112.1亿元</p> <p class="pro-value">112.1<span>亿元</span></p>
</div> </div>
<div class="value-bottom-right"> <div class="value-bottom-right">
<p class="comparison">累计同期环比</p> <p class="comparison">累计同期环比</p>
<p class="comparison-value">+1.2%</p> <p
class="comparison-value"
:class="{ 'down-trend': item.title === '运营成本' }"
>
{{ item.compareValue }}
<el-icon
class="trend-icon"
:class="{ 'down-trend': item.title === '运营成本' }"
>
<Bottom v-if="item.title === '运营成本'" />
<Top v-else />
</el-icon>
</p>
</div> </div>
</div> </div>
</div> </div>
...@@ -30,6 +42,7 @@ ...@@ -30,6 +42,7 @@
<script setup> <script setup>
import { onMounted, reactive, watch, ref } from "vue"; import { onMounted, reactive, watch, ref } from "vue";
import { Top, Bottom } from "@element-plus/icons-vue";
const props = defineProps({ const props = defineProps({
numberList: { numberList: {
type: Array, type: Array,
...@@ -48,7 +61,7 @@ const props = defineProps({ ...@@ -48,7 +61,7 @@ const props = defineProps({
.vw(border-radius, 5); .vw(border-radius, 5);
.vw(padding, 10); .vw(padding, 10);
.vw(margin,10); .vw(margin,10);
background-image: url("../assets/images/complete.png"); background-image: url("@/assets/images/complete.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
background-position: center; background-position: center;
...@@ -66,21 +79,45 @@ const props = defineProps({ ...@@ -66,21 +79,45 @@ const props = defineProps({
.vh(height,10); .vh(height,10);
} }
.pro-title { .pro-title {
.font(12); .font(10);
margin-bottom: -12px;
} }
.pro-value { .pro-value {
.font(16); .font(18);
font-family: "DIN";
color: @Color; color: @Color;
font-weight: 100;
span {
.font(10);
font-weight: 400;
} }
.comparison { }
}
.value-bottom-right {
.vh(margin-top,10);
.font(10); .font(10);
.comparison {
font-family: "Alibaba PuHuiTi";
} }
.comparison-value { .comparison-value {
color: green; color: #32d25a;
display: flex;
align-items: center;
gap: 2px;
&.down-trend {
color: #ff4757;
}
.trend-icon {
font-size: 12px;
color: #32d25a;
&.down-trend {
color: #ff4757;
}
} }
} }
.value-bottom-right {
.vh(margin-top,13);
} }
} }
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<script setup> <script setup>
import AMapLoader from "@amap/amap-jsapi-loader"; import AMapLoader from "@amap/amap-jsapi-loader";
import { onMounted } from "vue"; import { onMounted } from "vue";
import gansuLine from "./gansu.json"; import gansuLine from "./newLine.json";
let map = null; let map = null;
window._AMapSecurityConfig = { window._AMapSecurityConfig = {
securityJsCode: "75a8291a9e8f7c838fc5e4dd0d538f30", securityJsCode: "75a8291a9e8f7c838fc5e4dd0d538f30",
......
<template> <template>
<div class="stat-cards-container"> <div class="stat-cards-container">
<div class="stat-card" v-for="(item, idx) in props.numberList" :key="idx"> <div class="stat-card" v-for="(item, idx) in props.numberList" :key="idx">
<div class="stat-card__title">{{ item.title }}</div> <div class="stat-card-title">{{ item.title }}</div>
<div class="stat-card__value">{{ item.value }}</div> <div class="stat-card-value">{{ item.value }}</div>
<div class="amount"> <div class="amount">
<div> <div>
<p class="amount-title">实际完成金额</p> <p class="amount-title">实际完成金额</p>
<p class="amount-value">2.87亿元</p> <p class="amount-value">2.87<span>亿元</span></p>
</div> </div>
<div> <div>
<p class="amount-title">计划完成金额</p> <p class="amount-title">计划完成金额</p>
<p class="amount-value">4.21亿元</p> <p class="amount-value">4.21<span>亿元</span></p>
</div> </div>
</div> </div>
</div> </div>
...@@ -34,16 +34,18 @@ const props = defineProps({ ...@@ -34,16 +34,18 @@ const props = defineProps({
.vw(border-radius, 5); .vw(border-radius, 5);
.vw(padding, 10); .vw(padding, 10);
.vw(margin,10); .vw(margin,10);
background-image: url("../assets/images/total2.png"); background-image: url("@/assets/images/total2.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
background-position: center; background-position: center;
.stat-card__title { .stat-card-title {
.font(12); .font(12);
font-weight: 700; font-weight: 700;
} }
.stat-card__value { .stat-card-value {
.font(16); .font(20);
color: @Color;
font-family: "DIN";
} }
.amount { .amount {
display: flex; display: flex;
...@@ -53,8 +55,14 @@ const props = defineProps({ ...@@ -53,8 +55,14 @@ const props = defineProps({
.vh(height, 5); .vh(height, 5);
} }
.amount-value { .amount-value {
.font(20); .font(16);
color: @Color; color: @Color;
font-family: "DIN";
font-weight: 100;
span {
.font(10);
font-weight: 400;
}
} }
} }
} }
......
<template> <template>
<div class="common-container">
<div class="stat-cards-container"> <div class="stat-cards-container">
<div class="stat-card" v-for="(item, idx) in props.numberList" :key="idx"> <div class="stat-card" v-for="(item, idx) in props.numberList" :key="idx">
<div class="stat-card__title">{{ item.title }}</div> <div class="stat-card-title">{{ item.title }}</div>
<div class="stat-card__value">{{ item.value }}</div> <div class="stat-card-value" @click="handleDetail(item)">
{{ item.value }}
</div> </div>
</div> </div>
</div>
<!-- 详情信息 -->
<el-dialog
:title="dialogTitle + '详情'"
v-model="dialogVisible"
width="50%"
:before-close="handleClose"
>
<commonTable
:data="tableData"
:columns="tableColumns"
:total="tableTotal"
:current-page="currentPage"
:page-size="pageSize"
@size-change="handleSizeChange"
@current-page-change="handleCurrentPageChange"
@row-click="handleRowClick"
>
<template #status="{ row }">
<el-tag :type="row.status === 'active' ? 'success' : 'danger'">
{{ row.status === "active" ? "正常" : "异常" }}
</el-tag>
</template>
</commonTable>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</template>
</el-dialog>
</div>
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, watch, ref } from "vue"; import { onMounted, reactive, watch, ref } from "vue";
import commonTable from "./common/commonTable.vue";
const props = defineProps({ const props = defineProps({
numberList: { numberList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
}); });
// 弹窗相关
const dialogVisible = ref(false);
const dialogTitle = ref("");
// 表格相关数据
const tableData = ref([]);
const tableColumns = ref([
{ prop: "id", label: "ID", autoWidth: true },
{ prop: "name", label: "名称", autoWidth: true },
{ prop: "type", label: "类型", autoWidth: true },
{ prop: "value", label: "数值", autoWidth: true },
{ prop: "date", label: "日期", autoWidth: true },
{ prop: "status", label: "状态", autoWidth: true, slot: "status" },
]);
// 分页相关
const currentPage = ref(1);
const pageSize = ref(10);
const tableTotal = ref(0);
const generateTableData = () => {
const data = [];
const types = ["类型A", "类型B", "类型C"];
const statuses = ["active", "inactive"];
for (let i = 1; i <= 10; i++) {
data.push({
id: i,
name: `项目${i}`,
type: types[Math.floor(Math.random() * types.length)],
value: Math.floor(Math.random() * 1000),
date: new Date(
Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000
).toLocaleDateString(),
status: statuses[Math.floor(Math.random() * statuses.length)],
});
}
tableTotal.value = data.length;
return data;
};
const handleDetail = (item) => {
dialogVisible.value = true;
dialogTitle.value = item.title;
tableData.value = generateTableData();
};
// 分页处理
const handleSizeChange = (val) => {
pageSize.value = val;
currentPage.value = 1;
loadTableData();
};
const handleCurrentPageChange = (val) => {
currentPage.value = val;
loadTableData();
};
const loadTableData = () => {
const allData = generateTableData();
const start = (currentPage.value - 1) * pageSize.value;
const end = start + pageSize.value;
tableData.value = allData.slice(start, end);
};
const handleRowClick = (row, column, event) => {
console.log("行点击:", row);
};
const handleClose = () => {
dialogVisible.value = false;
};
onMounted(() => {});
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.stat-cards-container { .common-container {
display: flex;
justify-content: center;
.stat-cards-container {
display: flex; display: flex;
.stat-card { .stat-card {
.vw(width, 170); .vw(width, 170);
.vw(border-radius, 5); .vw(border-radius, 5);
.vw(padding, 10); .vw(padding, 20);
.vw(margin,10); // .vw(margin,10);
background-image: url("../assets/images/total2.png"); background-image: url("@/assets/images/total2.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 90% 80%;
background-position: center; background-position: center;
.stat-card__title { .stat-card-title {
.font(12); .font(12);
} }
.stat-card__value { .stat-card-value {
.vh(margin-top, 10); // .vh(margin-top, 10);
.font(20); .font(24);
cursor: pointer;
font-family: "DIN";
} }
} }
}
}
:deep(.el-dialog__title) {
font-weight: 900;
} }
</style> </style>
This diff is collapsed.
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
<!-- 顶部Header --> <!-- 顶部Header -->
<el-header class="city-header"> <el-header class="city-header">
<div class="header-left"> <div class="header-left">
<span class="city-name"></span> <img src="@/assets/images/logo.png" alt="" />
<!-- <span class="city-name">123123</span> -->
</div> </div>
<!-- </div> -->
<div class="header-right"> <div class="header-right">
<div> <div>
<el-dropdown> <el-dropdown>
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
</el-dropdown> </el-dropdown>
</div> </div>
</div> </div>
<!-- </div> -->
</el-header> </el-header>
<el-container> <el-container>
...@@ -88,7 +87,7 @@ const handleLogout = () => { ...@@ -88,7 +87,7 @@ const handleLogout = () => {
}; };
</script> </script>
<style scoped> <style scoped lang="less">
.smart-city-container { .smart-city-container {
height: 100vh; height: 100vh;
overflow: hidden; overflow: hidden;
...@@ -104,13 +103,15 @@ const handleLogout = () => { ...@@ -104,13 +103,15 @@ const handleLogout = () => {
.city-header { .city-header {
width: 100%; width: 100%;
height: 64px; height: 64px;
background: #3db8c5 background: #3db8c5 url("@/assets/images/header-bg.png") no-repeat fixed top
url("https://apaas-static.oss-cn-beijing.aliyuncs.com/app/header_bg.jpg") left / 100% 64px;
no-repeat fixed top left / 100% 64px;
color: #fff; color: #fff;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.header-left {
padding-left: 25px;
}
} }
.city-name { .city-name {
......
...@@ -5,6 +5,7 @@ import ElementPlus from 'element-plus' ...@@ -5,6 +5,7 @@ import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import * as ElIcons from '@element-plus/icons' import * as ElIcons from '@element-plus/icons'
import router from './router' import router from './router'
import "./assets/fonts/font.less"; // 字体样式
const app = createApp(App) const app = createApp(App)
for (const [key, component] of Object.entries(ElIcons)) { for (const [key, component] of Object.entries(ElIcons)) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="construct-container"> <div class="construct-container">
<div class="construct-left"> <div class="construct-left">
<div class="tag-image"> <div class="tag-image">
<img src="../assets/images/建设.png" /> <img src="@/assets/images/建设.png" />
</div> </div>
<div class="construct-left-map"> <div class="construct-left-map">
<Map /> <Map />
...@@ -42,8 +42,8 @@ ...@@ -42,8 +42,8 @@
</template> </template>
<script setup> <script setup>
import Map from "./Map.vue"; import Map from "@/components/CommonMap.vue";
import CommonTotal from "./CommonTotal.vue"; import CommonTotal from "@/components/CommonTotal.vue";
import { reactive, ref, onMounted, onUnmounted } from "vue"; import { reactive, ref, onMounted, onUnmounted } from "vue";
import CircleProgress from "./CircleProgress.vue"; import CircleProgress from "./CircleProgress.vue";
const projectList = reactive([ const projectList = reactive([
...@@ -89,18 +89,16 @@ const recycleList = reactive([ ...@@ -89,18 +89,16 @@ const recycleList = reactive([
.vw(width, 180); .vw(width, 180);
.vh(height, 30); .vh(height, 30);
.vh(line-height, 30); .vh(line-height, 30);
.vw(margin-left,10); .vw(margin-left,20);
.font(14); .font(20);
.vw(padding-left,23); .vw(padding-left,23);
text-align: left; text-align: left;
color: #fff; color: #fff;
font-family: YouSheBiaoTiYuan; font-family: YouSheBiaoTiYuan;
background-image: url("../assets/images/tag.png"); background-image: url("@/assets/images/tag.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
font-weight: 700;
letter-spacing: 3px;
background-size: 100% 100%; background-size: 100% 100%;
} }
.progress { .progress {
...@@ -119,7 +117,7 @@ const recycleList = reactive([ ...@@ -119,7 +117,7 @@ const recycleList = reactive([
align-items: center; align-items: center;
.vw(width,520); .vw(width,520);
.vh(height,85); .vh(height,85);
background-image: url("../assets/images/箭头.png"); background-image: url("@/assets/images/箭头.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: contain; background-size: contain;
background-position: center; background-position: center;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="construct-container"> <div class="construct-container">
<div class="construct-left"> <div class="construct-left">
<div class="tag-image"> <div class="tag-image">
<img src="../assets/images/建设.png" /> <img src="@/assets/images/建设.png" />
</div> </div>
<div class="construct-left-map"> <div class="construct-left-map">
<Map /> <Map />
...@@ -44,10 +44,10 @@ ...@@ -44,10 +44,10 @@
</template> </template>
<script setup> <script setup>
import Map from "./Map.vue"; import Map from "@/components/CommonMap.vue";
import CommonTotal from "./CommonTotal.vue"; import CommonTotal from "@/components/CommonTotal.vue";
import CommonComplete from "./CommonComplete.vue"; import CommonComplete from "@/components/CommonComplete.vue";
import CommonPlant from "./CommonPlant.vue"; import CommonPlant from "@/components/CommonPlant.vue";
import { reactive, ref, onMounted, onUnmounted } from "vue"; import { reactive, ref, onMounted, onUnmounted } from "vue";
const projectList = reactive([ const projectList = reactive([
{ title: "总个数(个)", value: "59" }, { title: "总个数(个)", value: "59" },
...@@ -70,9 +70,30 @@ const operationList = reactive([ ...@@ -70,9 +70,30 @@ const operationList = reactive([
{ title: "利润总额完成进度", value: "68.1%" }, { title: "利润总额完成进度", value: "68.1%" },
]); ]);
const completeList = reactive([ const completeList = reactive([
{ title: "营业收入" }, {
{ title: "运营成本" }, title: "营业收入",
{ title: "利润总额" }, protitle: "11月完成",
proValue: "1.1",
thirdTtile: "第三季度完成",
thirdValue: "4.21",
compareValue: "+1.2%",
},
{
title: "运营成本",
protitle: "11月完成",
proValue: "47.98",
thirdTtile: "第三季度完成",
thirdValue: "5.75",
compareValue: "-0.5%",
},
{
title: "利润总额",
protitle: "11月完成",
proValue: "9.90",
thirdTtile: "第三季度完成",
thirdValue: "23.52",
compareValue: "+1.2%",
},
]); ]);
</script> </script>
...@@ -92,21 +113,19 @@ const completeList = reactive([ ...@@ -92,21 +113,19 @@ const completeList = reactive([
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
.info-title { .info-title {
.vw(width, 220); .vw(width, 230);
.vh(height, 30); .vh(height, 30);
.vh(line-height, 30); .vh(line-height, 30);
.vw(margin-left,10); .vw(margin-left,10);
.font(14); .font(20);
.vw(padding-left,23); .vw(padding-left,28);
text-align: left; text-align: left;
color: #fff; color: #fff;
font-family: YouSheBiaoTiYuan; font-family: YouSheBiaoTiYuan;
background-image: url("../assets/images/tag.png"); background-image: url("@/assets/images/tag.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
font-weight: 700;
letter-spacing: 3px;
background-size: 100% 100%; background-size: 100% 100%;
} }
} }
......
<template> <template>
<div class="stat-cards-container"> <CommonTotal :numberList="initiationList" />
<div class="stat-card" v-for="(item, idx) in numberList" :key="idx">
<div class="stat-card__title">{{ item.title }}</div>
<div class="stat-card__value">{{ item.value }}</div>
</div>
</div>
<Map /> <Map />
</template> </template>
<script setup> <script setup>
import Map from "./Map.vue"; import CommonTotal from "@/components/CommonTotal.vue";
import Map from "@/components/CommonMap.vue";
import { onMounted, reactive, watch, ref } from "vue"; import { onMounted, reactive, watch, ref } from "vue";
const props = defineProps({ const props = defineProps({
...@@ -18,19 +14,17 @@ const props = defineProps({ ...@@ -18,19 +14,17 @@ const props = defineProps({
default: "立项", default: "立项",
}, },
}); });
const initiationList = ref([]);
const numberList = ref([]);
// 根据currentName设置不同的数据 // 根据currentName设置不同的数据
const setNumberList = (name) => { const setNumberList = (name) => {
if (name === "立项") { if (name === "立项") {
numberList.value = [ initiationList.value = [
{ title: "总个数(个)", value: "59" }, { title: "总个数(个)", value: "59" },
{ title: "总投资(亿元)", value: "2733.35" }, { title: "总投资(亿元)", value: "2733.35" },
{ title: "总规模(公里)", value: "5116.72" }, { title: "总规模(公里)", value: "5116.72" },
]; ];
} else { } else {
numberList.value = [ initiationList.value = [
{ title: "总个数(个)", value: "59" }, { title: "总个数(个)", value: "59" },
{ title: "总投资(亿元)", value: "2733.35" }, { title: "总投资(亿元)", value: "2733.35" },
{ title: "总规模(公里)", value: "5116.72" }, { title: "总规模(公里)", value: "5116.72" },
...@@ -67,14 +61,14 @@ onMounted(() => { ...@@ -67,14 +61,14 @@ onMounted(() => {
.vw(padding, 10); .vw(padding, 10);
.vw(padding, 10); .vw(padding, 10);
.vw(margin,10); .vw(margin,10);
background-image: url("../assets/images/total.png"); background-image: url("@/assets/images/total.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
.stat-card__title { .stat-card-title {
.font(14); .font(14);
} }
.stat-card__value { .stat-card-value {
.vh(margin-top, 20); .vh(margin-top, 20);
.font(20); .font(20);
} }
......
...@@ -73,14 +73,14 @@ ...@@ -73,14 +73,14 @@
</template> </template>
<script setup> <script setup>
import Construct from "@/components/Construct.vue"; import Construct from "../components/Construct.vue";
import ProjectApproval from "@/components/ProjectApproval.vue"; import ProjectApproval from "../components/ProjectApproval.vue";
import Operation from "@/components/Operation.vue"; import Operation from "../components/Operation.vue";
import { reactive, ref } from "vue"; import { reactive, ref } from "vue";
const selectedLeftBtn = ref("equity"); const selectedLeftBtn = ref("equity");
const selectedRightBtn = ref(""); const selectedRightBtn = ref("");
const selectedContentBtn = ref(1); const selectedContentBtn = ref(3);
const selectedContentName = ref("立项"); const selectedContentName = ref("立项");
const isFullscreen = ref(false); const isFullscreen = ref(false);
const showPopup = ref(false); const showPopup = ref(false);
...@@ -188,12 +188,13 @@ window.addEventListener("fullscreenchange", () => { ...@@ -188,12 +188,13 @@ window.addEventListener("fullscreenchange", () => {
<style scoped lang="less"> <style scoped lang="less">
.home-container { .home-container {
background-image: url("../../assets/images/bg.png"); // background-image: url("@/assets/images/bg.png");
background-repeat: no-repeat; // background-repeat: no-repeat;
background-size: cover; // background-size: cover;
background-position: center; // background-position: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: #04427e;
overflow: hidden; overflow: hidden;
color: #fff; color: #fff;
display: flex; display: flex;
...@@ -204,38 +205,44 @@ window.addEventListener("fullscreenchange", () => { ...@@ -204,38 +205,44 @@ window.addEventListener("fullscreenchange", () => {
.vh(height, 80); .vh(height, 80);
text-align: center; text-align: center;
.title-section { .title-section {
background-image: url("../../assets/images/header.png"); background-image: url("@/assets/images/header.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover;
background-position: center; background-position: center;
font-weight: 700; background-size: 170% 100%;
letter-spacing: 3px;
.vh(margin-top, -15); .vh(margin-top, -15);
.font(24); .font(28);
font-family: HelveticaNeue; letter-spacing: 1px;
font-weight: 400;
text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25);
font-family: "YouSheBiaoTiHei";
width: 950px;
height: 74px;
display: flex;
justify-content: center;
align-items: center;
} }
.header-left { .header-left {
display: flex; display: flex;
// justify-content: center;
align-items: center; align-items: center;
padding-left: 75px; .vw( padding-left, 75);
.nav-btn { .nav-btn {
.vh(line-height, 36); .vh(line-height, 36);
.font(14); .font(14);
cursor: pointer; cursor: pointer;
color: #fff; color: #fff;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100%, 100%; background-size: 85%, 100%;
background-position: center; background-position: center;
font-family: YouSheBiaoTiYuan;
font-weight: 100;
&:not(.active) { &:not(.active) {
background-image: url("../../assets/images/left-btn.png"); background-image: url("@/assets/images/left-btn.png");
.vh(height,36); .vh(height,36);
.vw(width,208); .vw(width,208);
} }
&.active { &.active {
background-image: url("../../assets/images/left-hlightBtn.png"); background-image: url("@/assets/images/left-hlightBtn.png");
.vh(height,36); .vh(height,36);
.vw(width,208); .vw(width,208);
} }
...@@ -253,15 +260,15 @@ window.addEventListener("fullscreenchange", () => { ...@@ -253,15 +260,15 @@ window.addEventListener("fullscreenchange", () => {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
font-family: YouSheBiaoTiYuan;
&:not(.active) { &:not(.active) {
background-image: url("../../assets/images/right-btn.png"); background-image: url("@/assets/images/right-btn.png");
.vh(height,36); .vh(height,36);
.vw(width,208); .vw(width,208);
} }
&.active { &.active {
background-image: url("../../assets/images/right-hight-btn.png"); background-image: url("@/assets/images/right-hight-btn.png");
.vh(height,36); .vh(height,36);
.vw(width,208); .vw(width,208);
} }
...@@ -275,61 +282,79 @@ window.addEventListener("fullscreenchange", () => { ...@@ -275,61 +282,79 @@ window.addEventListener("fullscreenchange", () => {
.content-btn { .content-btn {
.vh(margin-top,-10); .vh(margin-top,-10);
.vh(margin-bottom,20); .vh(margin-bottom,20);
text-align: center; display: flex;
justify-content: center;
align-items: center;
span { span {
.font(14); .font(14);
.vw(width,110); width: 110px;
.vh(height,35); height: 35px;
display: inline-block; display: flex;
align-items: center;
justify-content: center;
cursor: pointer; cursor: pointer;
flex-shrink: 0;
color: #fff; // 补充文字颜色(匹配蓝色按钮的白色文字)
} }
// 立项按钮
:nth-child(1) { :nth-child(1) {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: 80% 80%;
background-position: center; background-position: center;
.vw(width,105); width: 115px;
.vh(height,35); height: 35px;
.vh(line-height,35); line-height: 35px;
text-align: center; text-align: center;
.vw(margin-right,-7);
background-image: url("../../assets/images/立项.png");
&.active { &.active {
background-image: url("../../assets/images/nav-hight-btn.png"); background-image: url("@/assets/images/立项.png");
}
&:not(.active) {
background-image: url("@/assets/images/initiation-default.png");
} }
} }
// 退出按钮
:nth-child(5) { :nth-child(5) {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: 80% 80%;
background-position: center; background-position: center;
.vw(width,105); width: 111px;
.vh(height,35); height: 35px;
.vh(line-height,35); line-height: 35px;
text-align: center; text-align: center;
background-image: url("../../assets/images/退出.png");
&.active { &.active {
background-image: url("../../assets/images/退出-active.png"); background-image: url("@/assets/images/退出-active.png");
}
&:not(.active) {
background-image: url("@/assets/images/退出.png");
} }
} }
// 中间按钮(建设、运营、转止)
:nth-child(2), :nth-child(2),
:nth-child(3), :nth-child(3),
:nth-child(4) { :nth-child(4) {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: 80% 80%;
background-position: center; background-position: center;
.vw(width,108); width: 115px;
.vh(height,35); height: 35px;
.vh(line-height,35); line-height: 35px;
.vw(margin-right,-7);
text-align: center; text-align: center;
background-image: url("../../assets/images/default-btn.png"); margin-left: -32px;
background-image: url("@/assets/images/default-btn.png");
&.active { &.active {
background-image: url("../../assets/images/nav-hight-btn.png"); background-image: url("@/assets/images/nav-hight-btn.png");
}
} }
:nth-child(5) {
margin-left: -31px;
} }
} }
} }
.bottom { .bottom {
background-image: url("../../assets/images/bottom.png"); background-image: url("@/assets/images/bottom.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
......
<template> <template>
<div class="login-container"> <div class="login-container">
<div class="login-header">葛洲坝集团交通投资有限公司投资决策分析系统</div>
<div class="login-form-wrapper"> <div class="login-form-wrapper">
<h2 class="login-title">后台管理系统登录</h2> <div class="company-logo"></div>
<el-form <el-form
ref="loginFormRef" ref="loginFormRef"
:model="loginForm" :model="loginForm"
:rules="loginRules" :rules="loginRules"
label-width="80px" label-width="70px"
class="login-form" class="login-form"
labelPosition="top"
> >
<el-form-item label="用户名" prop="username"> <el-form-item label="用户名" prop="username">
<el-input <el-input
:prefix-icon="User"
v-model="loginForm.username" v-model="loginForm.username"
placeholder="请输入用户名" placeholder="请输入用户名"
prefix-icon="el-icon-user" prefix-icon="el-icon-user"
...@@ -18,10 +21,11 @@ ...@@ -18,10 +21,11 @@
</el-form-item> </el-form-item>
<el-form-item label="密码" prop="password"> <el-form-item label="密码" prop="password">
<el-input <el-input
prefix-icon="Lock"
v-model="loginForm.password" v-model="loginForm.password"
type="password" type="password"
placeholder="请输入密码" placeholder="请输入密码"
prefix-icon="el-icon-lock" show-password
></el-input> ></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
...@@ -39,23 +43,25 @@ ...@@ -39,23 +43,25 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import type { FormInstance, FormRules } from "element-plus"; import { User, Lock } from "@element-plus/icons-vue";
const router = useRouter(); const router = useRouter();
const loginFormRef = ref<FormInstance>(); const loginFormRef = ref();
const loading = ref(false); const loading = ref(false);
const captchaSrc = ref("https://picsum.photos/120/40"); // 模拟验证码图片
// 登录表单数据 // 登录表单数据
const loginForm = ref({ const loginForm = ref({
username: "", username: "admin",
password: "", password: "",
captcha: "",
}); });
// 表单验证规则 // 表单验证规则
const loginRules = ref<FormRules>({ const loginRules = ref({
username: [ username: [
{ required: true, message: "请输入用户名", trigger: "blur" }, { required: true, message: "请输入用户名", trigger: "blur" },
{ min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }, { min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" },
...@@ -69,12 +75,8 @@ const loginRules = ref<FormRules>({ ...@@ -69,12 +75,8 @@ const loginRules = ref<FormRules>({
// 处理登录 // 处理登录
const handleLogin = async () => { const handleLogin = async () => {
try { try {
// 验证表单
await loginFormRef.value?.validate(); await loginFormRef.value?.validate();
loading.value = true; loading.value = true;
// 模拟登录请求
setTimeout(() => { setTimeout(() => {
// 登录成功后设置token // 登录成功后设置token
const mockToken = "mock-jwt-token"; const mockToken = "mock-jwt-token";
...@@ -92,51 +94,135 @@ const handleLogin = async () => { ...@@ -92,51 +94,135 @@ const handleLogin = async () => {
<style scoped lang="less"> <style scoped lang="less">
.login-container { .login-container {
width: 100%;
height: 100vh;
background-image: url("@/assets/images/login.png");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
padding-top: 15px;
}
.login-header {
color: #fff;
font-size: 24px;
font-weight: bold;
padding-left: 20px;
margin: 0 20px;
border-radius: 5px;
display: flex; display: flex;
justify-content: flex-end; justify-content: left;
align-items: center; align-items: center;
height: 100vh; height: 50px;
// background-image: url('@/assets/images/background.png'); background: linear-gradient(
// background-size: cover; to right,
// background-position: center; rgba(0, 0, 0, 0.3),
// background-repeat: no-repeat; rgba(0, 0, 0, 0.6),
// padding-right: 100px; rgba(0, 0, 0, 0.3)
);
} }
.login-form-wrapper { .login-form-wrapper {
background-color: rgba(255, 255, 255, 0.9); background-color: rgba(0, 0, 0, 0.8);
position: absolute; position: absolute;
top: 35%; top: 50%;
right: 6%; right: 1%;
transform: translateY(-50%); transform: translateY(-50%);
padding: 48px; padding: 15px;
box-sizing: border-box; box-sizing: border-box;
width: 460px; width: 350px;
height: 550px; height: 350px;
box-shadow: 0 0 16px #2e31361a; box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
border-radius: 8px; border-radius: 8px;
:deep(.el-form-item) { :deep(.el-form-item) {
margin-bottom: 10px;
.el-form-item__content { .el-form-item__content {
.el-input { .el-input {
height: 48px; height: 48px;
border-radius: 4px; border-radius: 4px;
.el-input__wrapper { .el-input__wrapper {
background: #f3f4f9; background: rgba(255, 255, 255, 0.9);
}
.el-input__inner {
color: #333;
}
}
.el-form-item__label {
color: #fff;
} }
} }
} }
:deep(.el-form-item__label) {
color: #fff;
} }
} }
.login-title { .company-logo {
text-align: center; width: 100%;
height: 30px;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 30px; margin-bottom: 30px;
color: #304156; background-image: url(/src/assets/images/logo.png);
background-size: 100% 80%;
background-position: center;
background-repeat: no-repeat;
} }
.login-form { .login-form {
.login-btn { .login-btn {
width: 100%; width: 100%;
height: 30px;
border-radius: 4px;
background-color: #1890ff;
margin-top: 18px;
}
.forgot-password {
color: #fff;
float: right;
margin-top: 10px;
}
}
.captcha-image {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
img {
width: 120px;
height: 40px;
border-radius: 4px;
}
}
:deep(.el-form-item__content) {
position: relative;
&.el-form-item__content--with-captcha {
padding-right: 130px;
}
}
:deep(.el-input__inner) {
color: #333;
}
:deep(.el-input__prefix-inner) {
color: #909399;
}
.login-form {
:deep(.el-form-item) {
.el-form-item__content {
.el-input {
height: 30px;
}
}
}
:deep(.el-form-item--label-top) {
.el-form-item__label {
line-height: 15px;
}
} }
} }
</style> </style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment