大屏优化

This commit is contained in:
jiayu 2026-01-19 18:54:35 +08:00
parent f65b8b96b6
commit 7deea972e5
14 changed files with 438 additions and 317 deletions

View File

@ -1,6 +1,7 @@
NODE_ENV=development
VITE_APP_TITLE='数字乡村云平台'
VITE_APP_API_URL='http://192.168.34.155:1024'
# VITE_APP_API_URL='http://192.168.34.179:6080/village'
VITE_APP_API_URL='http://192.168.34.155:1024/village'
# VITE_APP_API_URL='http://jxjzw.zhgdyun.com:10248/village'
# VITE_APP_API_URL='http://jxjzw.zhgdyun.com:11026'
VITE_MQTT_URL='ws://jxj.zhgdyun.com:8083/mqtt'

View File

@ -1,6 +1,6 @@
NODE_ENV=production
VITE_APP_TITLE='数字乡村云平台'
VITE_APP_API_URL='http://localhost:1024'
VITE_APP_API_URL='http://localhost:6080/village'
# VITE_APP_API_URL='http://jxjzw.zhgdyun.com:11026'
# VITE_APP_API_URL='http://jxjzw.zhgdyun.com:10248/village'
# VITE_APP_API_URL='http://jxjzw.zhgdyun.com:10348/village'

View File

@ -2,3 +2,4 @@ const CONFIG = {
loginName: "nanshan",
password: "123456",
}
const VILLAGE_IFRAME_URL = "https://vr.wholeally.com/vr/NDhiZDhiOTAtYzVlNC0yNzZjLTMyYzEtNmQ5OWNmNWQ1YWU5.html";

View File

@ -246,9 +246,13 @@
color: #effaff;
line-height: 20px;
font-family: HanYiZongYiTiJian, HanYiZongYiTiJian;
transition: font-size 0.3s ease-in-out;
}
&:hover {
background-color: rgba(255, 255, 255, 0.1);
// background-color: rgba(255, 255, 255, 0.1);
span {
font-size: 18px;
}
}
&.active-green {
background-image: url('/@/assets/images/village-bigdata/header-tab-active-green.png');

View File

@ -108,9 +108,15 @@
}
.news-item {
width: 100%;
height: 100%;
height: 162px;
display: flex;
flex-direction: column;
gap: 10px;
.image {
width: 100%;
height: 100%;
object-fit: cover;
}
.news-item-content {
flex: 1;
font-family:

View File

@ -5,9 +5,7 @@
</template>
<script setup>
import { ref } from 'vue';
const iframeUrl = ref('https://vr.wholeally.com/vr/NDhiZDhiOTAtYzVlNC0yNzZjLTMyYzEtNmQ5OWNmNWQ1YWU5.html');
const iframeUrl = VILLAGE_IFRAME_URL;
</script>
<style lang="less" scoped>

View File

@ -1,57 +1,65 @@
<template>
<div class="party-org">
<BCard title="党组织">
<div class="org-header">
<div class="establish-date">
<div class="date-value">成立日期{{ currentOrg.incorporationDate || '--' }}</div>
</div>
</div>
<div class="org-content">
<!-- 左侧进度环 -->
<div class="progress-left">
<div class="progress-circle">
<div class="circle-number">{{ orgStat.total }}</div>
<div class="line"></div>
<div class="circle-text">党组织总数</div>
<div class="org-content-wrapper">
<div class="org-header">
<div class="establish-date">
<div class="date-value">成立日期{{ currentOrg.incorporationDate || '--' }}</div>
</div>
<div class="activity-count gradient-border-box">
<img src="/@/assets/images/party-bigdata/party-org-ic.png" alt="" />
<div class="count-box">
<span class="count">{{ orgStat.excellent }}</span>
<span class="label">优秀党组织</span>
</div>
<div class="org-content">
<!-- 左侧进度环 -->
<div class="progress-left">
<div class="progress-circle">
<div class="circle-number">{{ orgStat.total }}</div>
<div class="line"></div>
<div class="circle-text">党组织总数</div>
</div>
<div class="activity-count gradient-border-box">
<img src="/@/assets/images/party-bigdata/party-org-ic.png" alt />
<div class="count-box">
<span class="count">{{ orgStat.excellent }}</span>
<span class="label">优秀党组织</span>
</div>
</div>
</div>
<!-- 右侧组织列表 -->
<div class="org-list">
<div class="list-title">
<span>组织名称</span>
<span>书记</span>
</div>
<div class="list-items">
<a-scrollbar maxHeight="160px">
<div
class="list-item"
:class="{ active: currentOrg.id === item.id }"
v-for="(item, index) in orgList"
:key="index"
@click="handleOrgClick(item)"
>
<span class="org-name">{{ item.name }}</span>
<span class="org-secretary">{{ item.secretaryName || '--' }}</span>
</div>
</a-scrollbar>
</div>
</div>
</div>
<!-- 右侧组织列表 -->
<div class="org-list">
<div class="list-title">
<span>组织名称</span>
<span>书记</span>
<!-- 底部照片 -->
<div class="org-photo gradient-border-box">
<div class="photo-title">党组织风采</div>
<div class="photo-container">
<a-image
width="100%"
height="170px"
style="object-fit: cover"
:src="currentOrg.elegantDemeanour || defaultParty"
alt="党组织风采照片"
/>
</div>
<div class="list-items">
<a-scrollbar maxHeight="160px">
<div
class="list-item"
:class="{ active: currentOrg.id === item.id }"
v-for="(item, index) in orgList"
:key="index"
@click="handleOrgClick(item)"
>
<span class="org-name">{{ item.name }}</span>
<span class="org-secretary">{{ item.secretaryName || '--' }}</span>
</div>
</a-scrollbar>
</div>
</div>
</div>
<!-- 底部照片 -->
<div class="org-photo gradient-border-box">
<div class="photo-title">党组织风采</div>
<div class="photo-container">
<a-image width="100%" height="170px" style="object-fit: cover" :src="currentOrg.elegantDemeanour || defaultParty" alt="党组织风采照片" />
</div>
</div>
</BCard>
@ -59,277 +67,268 @@
</template>
<script setup>
import BCard from './b-card.vue';
import { ref, onMounted, watch } from 'vue';
import { useUserStore } from '/@/store/modules/system/user';
import { partyApi } from '/@/api/business/party/party-api';
import defaultParty from '/@/assets/images/party-bigdata/default-party.png';
import BCard from './b-card.vue';
import { ref, onMounted, watch } from 'vue';
import { useUserStore } from '/@/store/modules/system/user';
import { partyApi } from '/@/api/business/party/party-api';
import defaultParty from '/@/assets/images/party-bigdata/default-party.png';
watch(
() => useUserStore().getCurrentVillageId,
(value) => {
getPartyOrgList();
}
);
watch(
() => useUserStore().getCurrentVillageId,
(value) => {
getPartyOrgList();
}
);
const orgList = ref([]);
const currentOrg = ref({});
const orgStat = ref({});
const orgList = ref([]);
const currentOrg = ref({});
const orgStat = ref({});
const getPartyOrgList = async () => {
const res = await partyApi.listOrg({});
if (res.ok) {
orgList.value = res.data;
currentOrg.value = res.data[0] || {};
}
};
const getPartyOrgList = async () => {
const res = await partyApi.listOrg({});
if (res.ok) {
orgList.value = res.data;
currentOrg.value = res.data[0] || {};
}
};
const getOrganizationStat = async () => {
const res = await partyApi.organizationStat();
if (res.ok) {
orgStat.value = res.data;
}
};
const getOrganizationStat = async () => {
const res = await partyApi.organizationStat();
if (res.ok) {
orgStat.value = res.data;
}
};
const handleOrgClick = (item) => {
currentOrg.value = item;
};
const handleOrgClick = (item) => {
currentOrg.value = item;
};
onMounted(async () => {
await getPartyOrgList();
getOrganizationStat();
});
onMounted(async () => {
await getPartyOrgList();
getOrganizationStat();
});
</script>
<style lang="less" scoped>
.party-org {
// height: 100%;
.org-header {
.org-content-wrapper {
height: 568px;
display: flex;
flex-direction: column;
}
.party-org {
// height: 100%;
.org-header {
display: flex;
justify-content: center;
.establish-date {
width: 380px;
height: 50px;
display: flex;
align-items: center;
// background: linear-gradient(90deg, #7b3a11 0%, rgba(123, 58, 17, 0) 100%);
background-image: url('/@/assets/images/party-bigdata/party-ort-date-bg.png');
background-size: 100% 100%;
background-repeat: no-repeat;
padding: 8px 16px;
border-radius: 4px;
position: relative;
justify-content: center;
.establish-date {
width: 380px;
height: 50px;
display: flex;
align-items: center;
// background: linear-gradient(90deg, #7b3a11 0%, rgba(123, 58, 17, 0) 100%);
background-image: url('/@/assets/images/party-bigdata/party-ort-date-bg.png');
background-size: 100% 100%;
background-repeat: no-repeat;
padding: 8px 16px;
border-radius: 4px;
position: relative;
justify-content: center;
.date-value {
font-family:
PingFang SC,
PingFang SC;
font-weight: 500;
font-size: 18px;
color: #e7d4ac;
line-height: 24px;
text-align: center;
}
}
}
.org-content {
display: flex;
margin-top: 20px;
.progress-left {
display: flex;
flex-direction: column;
align-items: center;
.progress-circle {
position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
border: 1px solid #7b1d1c;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.line {
width: 100px;
height: 2px;
background: rgba(247, 247, 247, 0.1);
margin-top: 6px;
margin-bottom: 6px;
}
.circle-number {
font-weight: 500;
font-size: 26px;
color: #ffffff;
line-height: 24px;
z-index: 1;
}
.circle-text {
font-family:
PingFang SC,
PingFang SC;
font-weight: 500;
font-size: 14px;
color: #ffffff;
z-index: 1;
}
}
.activity-count {
// width: 150px;
margin-top: 16px;
position: relative; //
padding: 10px 20px; //
text-align: center;
display: flex;
align-items: center;
justify-content: center;
img {
width: 44px;
height: 44px;
margin-right: 8px;
}
.count-box {
display: flex;
flex-direction: column;
}
.count {
font-family:
PingFang SC,
PingFang SC;
font-weight: 400;
font-size: 16px;
color: #ffffff;
margin-bottom: 8px;
}
.label {
font-family:
PingFang SC,
PingFang SC;
font-weight: 400;
font-size: 12px;
color: #ffffff;
}
}
}
.org-list {
flex: 1;
margin-left: 20px;
.list-title {
color: #a0a49e;
font-size: 14px;
padding: 8px 16px;
background: rgba(255, 255, 255, 0.1);
border: 1px solid;
border-image: linear-gradient(90deg, rgba(189, 122, 95, 1), rgba(134, 63, 59, 1)) 1 1;
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 14px;
font-family:
PingFang SC,
PingFang SC;
font-weight: 500;
font-size: 16px;
color: #e7d4ac;
}
}
.list-items {
// max-height: 160px;
// overflow-y: auto;
.list-item {
background: rgba(222, 171, 124, 0.05);
display: flex;
align-items: center;
gap: 8px;
color: #ffffff;
font-size: 14px;
margin-top: 6px;
padding: 8px 16px;
&.active {
background: rgba(222, 171, 124, 0.2);
}
.org-name {
flex: 1;
font-weight: 500;
font-size: 14px;
color: #ffffff;
}
.org-secretary {
flex-shrink: 0;
font-size: 14px;
color: #ffffff;
}
}
}
}
}
.org-photo {
margin-top: 16px;
padding: 12px;
box-sizing: border-box;
.photo-title {
font-family:
PingFang SC,
PingFang SC;
.date-value {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 16px;
font-size: 18px;
color: #e7d4ac;
line-height: 24px;
text-align: center;
margin-bottom: 10px;
}
}
}
.org-content {
display: flex;
margin-top: 20px;
.progress-left {
display: flex;
flex-direction: column;
align-items: center;
.progress-circle {
position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
border: 1px solid #7b1d1c;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.line {
width: 100px;
height: 2px;
background: rgba(247, 247, 247, 0.1);
margin-top: 6px;
margin-bottom: 6px;
}
.circle-number {
font-weight: 500;
font-size: 26px;
color: #ffffff;
line-height: 24px;
z-index: 1;
}
.circle-text {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 14px;
color: #ffffff;
z-index: 1;
}
}
.photo-container {
width: 100%;
height: 170px;
overflow: hidden;
border-radius: 8px;
.activity-count {
// width: 150px;
margin-top: 16px;
position: relative; //
padding: 10px 20px; //
text-align: center;
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: cover;
width: 44px;
height: 44px;
margin-right: 8px;
}
.count-box {
display: flex;
flex-direction: column;
}
.count {
font-family: PingFang SC, PingFang SC;
font-weight: 400;
font-size: 16px;
color: #ffffff;
margin-bottom: 8px;
}
.label {
font-family: PingFang SC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #ffffff;
}
}
}
.org-list {
flex: 1;
margin-left: 20px;
.list-title {
color: #a0a49e;
font-size: 14px;
padding: 8px 16px;
background: rgba(255, 255, 255, 0.1);
border: 1px solid;
border-image: linear-gradient(90deg, rgba(189, 122, 95, 1), rgba(134, 63, 59, 1)) 1 1;
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 14px;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 16px;
color: #e7d4ac;
}
}
.list-items {
// max-height: 160px;
// overflow-y: auto;
.list-item {
background: rgba(222, 171, 124, 0.05);
display: flex;
align-items: center;
gap: 8px;
color: #ffffff;
font-size: 14px;
margin-top: 6px;
padding: 8px 16px;
&.active {
background: rgba(222, 171, 124, 0.2);
}
.org-name {
flex: 1;
font-weight: 500;
font-size: 14px;
color: #ffffff;
}
.org-secretary {
flex-shrink: 0;
font-size: 14px;
color: #ffffff;
}
}
}
}
}
// 使 mixin
.gradient-border-box {
position: relative;
border-radius: 6px;
.org-photo {
margin-top: 16px;
padding: 12px;
box-sizing: border-box;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 6px;
padding: 1px;
background: linear-gradient(180deg, rgba(128, 100, 97, 1), rgba(171, 92, 87, 1));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
.photo-title {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 16px;
color: #e7d4ac;
line-height: 24px;
text-align: center;
margin-bottom: 10px;
}
.photo-container {
width: 100%;
height: 170px;
overflow: hidden;
border-radius: 8px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
}
// 使 mixin
.gradient-border-box {
position: relative;
border-radius: 6px;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 6px;
padding: 1px;
background: linear-gradient(180deg, rgba(128, 100, 97, 1), rgba(171, 92, 87, 1));
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
}
</style>

View File

@ -58,7 +58,7 @@
<style lang="less" scoped>
.party-style {
min-height: 210px;
min-height: 160px;
flex: 1;
.list-container {

View File

@ -1,6 +1,6 @@
<template>
<div class="party-video">
<video class="video" :src="videoUrl" controls></video>
<video class="video" :src="videoUrl" controls autoplay></video>
</div>
</template>

View File

@ -15,23 +15,23 @@
<script setup>
import BCard from './b-card.vue';
import { scenicSpotApi } from '/@/api/business/travel/scenic-spot-api';
import { landscapeApi } from '/@/api/business/travel/landscape-api';
import { ref, onMounted } from 'vue';
const scenicList = ref([
{ id: 1, name: '南海岛·中国第一滩', image: '' },
{ id: 2, name: '放鸡岛海洋度假公园', image: '' },
{ id: 3, name: '浪漫海岸国际度假区', image: '' },
{ id: 4, name: '浮山岭风景区', image: '' },
{ id: 5, name: '高州仙人洞风景区', image: '' },
{ id: 6, name: '冼太夫人故里', image: '' },
{ id: 7, name: '柏桥荔博园', image: '' },
{ id: 8, name: '信宜天马山生态旅游区', image: '' },
{ id: 9, name: '御水古温泉度假区', image: '' },
// { id: 1, name: '·', image: '' },
// { id: 2, name: '', image: '' },
// { id: 3, name: '', image: '' },
// { id: 4, name: '', image: '' },
// { id: 5, name: '', image: '' },
// { id: 6, name: '', image: '' },
// { id: 7, name: '', image: '' },
// { id: 8, name: '', image: '' },
// { id: 9, name: '', image: '' },
]);
const getScenicList = async () => {
const res = await scenicSpotApi.queryPage({
const res = await landscapeApi.queryPage({
pageNum: 1,
pageSize: 9,
});
@ -68,7 +68,7 @@
}
.list-item-image {
width: 100%;
height: 80px;
height: 72px;
border-radius: 4px;
overflow: hidden;
background: rgba(255, 255, 255, 0.1);

View File

@ -123,8 +123,8 @@
gap: 12px;
padding: 8px;
.statistics-icon {
width: 40px;
height: 40px;
width: 60px;
height: 70px;
flex-shrink: 0;
img {
width: 100%;

View File

@ -105,7 +105,7 @@
}
.video-item-image {
width: 100%;
height: 80px;
height: 72px;
border-radius: 4px;
overflow: hidden;
background: rgba(255, 255, 255, 0.1);

View File

@ -181,7 +181,7 @@
height: 100%;
.chart-container {
width: 100%;
height: 250px;
height: 308px;
}
}
}

File diff suppressed because one or more lines are too long