123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- <template>
- <div class="home-floating-panel">
- <floating-panel
- class="floating-panel"
- :class="{ 'background-panel': isBackground }"
- v-model:height="height"
- :anchors="anchors"
- :content-draggable="false"
- @height-change="handleHeightChange"
- >
- <template #header>
- <div class="floating-panel-header" :class="{ 'file-header-active': activeTab === 0 }">
- <div class="tabs">
- <div
- :class="['tab-item', activeTab === index ? 'active' : '']"
- v-for="(tab, index) in tabs"
- :key="tab"
- @click="handleTabClick(index)"
- >
- {{ tab }}
- </div>
- </div>
- <div class="file-header" v-if="activeTab === 1">
- <div class="select-group">
- <el-select class="select-item" v-model="dateValue" placeholder="Select">
- <el-option
- v-for="item in dateOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- <el-select class="select-item" v-model="areaValue" placeholder="Select">
- <el-option
- v-for="item in areaOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </div>
- <el-anchor
- :container="containerRef"
- class="tabs-content-group"
- direction="horizontal"
- type="default"
- :offset="0"
- @click="handleClick"
- >
- <el-anchor-link
- class="tabs-content-item"
- v-for="(tab, index) in tabsContent"
- :key="tab"
- @click="handleTabsContentClick(index)"
- :href="'#part' + (index + 1)"
- :title="tab"
- ></el-anchor-link>
- </el-anchor>
- </div>
- </div>
- </template>
- <div class="floating-panel-content" v-show="activeTab === 0">
- <record-task></record-task>
- </div>
- <div class="floating-panel-content" ref="cardContentRef" v-show="activeTab === 1">
- <div class="card-content-group" ref="containerRef" :style="{ height: `${cardContentHeight}px` }">
- <div class="card-content-item" id="part1">
- <div class="card-content-item-title">果园总览</div>
- <div class="card-content-item-content">
- <div class="card-text">果园面积共XX亩,共有XX棵生产树。</div>
- <div class="card-text">
- 本次飞巡拍摄了XX张照片,包括了XX棵树,目前为施用根部有机肥阶段,根据树体冠幅大小,果园预计施用有机肥XXkg。
- </div>
- <div class="card-text">
- 目前XX%的树体暂未萌动新梢,需要进行剪枝农事,提高树体光合效率与通风效率。
- </div>
- </div>
- </div>
- <div class="card-content-item" id="part2">
- <div class="card-content-item-title">整体园相</div>
- <div class="card-content-item-content">
- <div class="card-name">透光率</div>
- <div class="card-value">
- 透光率体现树体自身郁闭程度,当前XX%的树体透光性较差,可能造成整体减产XX%,需立即执行剪枝农事;XX%的树体透光正常,建议继续保持现有管理措施并及时巡园。
- </div>
- </div>
- <div class="card-content-item-content">
- <div class="card-name">通风率</div>
- <div class="card-value">
- 透光率体现树体自身郁闭程度,当前XX%的树体透光性较差,可能造成整体减产XX%,需立即执行剪枝农事;XX%的树体透光正常,建议继续保持现有管理措施并及时巡园。
- </div>
- <div class="map-wrap">
- <img class="map-img" src="@/assets/img/home/map.png" alt="" />
- <div class="map-text">剪枝农事地图</div>
- </div>
- </div>
- </div>
- <div class="card-content-item" id="part3">
- <div class="card-content-item-title">营养管理</div>
- <div class="card-content-item-content">
- <div class="card-name">根肥</div>
- <div class="card-value">
- 生产树中,树体冠幅平均表面积XX平方米,预计需要使用有机肥XXkg(或者平衡肥+尿素XXkg)用来培养健壮秋梢。如遭遇持续阴雨,可配合芸苔素增强光合作用。
- </div>
- <div class="map-wrap">
- <img class="map-img" src="@/assets/img/home/map.png" alt="" />
- <div class="map-text">根肥农事地图</div>
- </div>
- </div>
- </div>
- <div class="card-content-item" id="part4">
- <div class="card-content-item-title">病虫管理</div>
- <div class="card-content-item-content">
- <div class="card-value">
- 在以萌动新梢的树体中,2%的树体新梢小叶变为红黄色,长度10-15cm,极易被病虫啃食,预计XX月XX日果园进入虫害爆发高峰期,需要做好虫害预防工作。
- </div>
- <div class="map-wrap">
- <img class="map-img" src="@/assets/img/home/map.png" alt="" />
- <div class="map-text">防虫农事地图</div>
- </div>
- </div>
- </div>
- <div class="card-content-item" id="part5">
- <div class="card-content-item-title">农事记录</div>
- <div class="card-content-item-content">农事记录</div>
- </div>
- </div>
- </div>
- </floating-panel>
- <div class="expand-btn-wrap" v-show="height === defalutHeight">
- <span>农事任务/农事档案</span>
- <div class="expand-btn" @click="handleExpandBtnClick">
- <span>展开</span>
- <el-icon><ArrowUpBold /></el-icon>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { FloatingPanel } from "vant";
- import { useStore } from "vuex";
- import { computed, ref } from "vue";
- import RecordTask from "./recordTask.vue";
- const store = useStore();
- // const tabBarHeight = computed(() => store.state.home.tabBarHeight);
- const tabBarHeight = ref(localStorage.getItem("tabBarHeight") * 1 || 50);
- const defalutHeight = ref(0);
- const anchors = ref([defalutHeight.value, 310 + tabBarHeight.value, Math.round(1 * window.innerHeight)]);
- const height = ref(anchors.value[1]);
- const containerRef = ref(null);
- const handleClick = (e) => {
- e.preventDefault();
- };
- const activeTab = ref(1);
- const tabs = ref(["农事任务", "农场档案"]);
- const handleTabClick = (index) => {
- activeTab.value = index;
- };
- const dateValue = ref("2025-08-28");
- const dateOptions = [
- {
- value: "2025-08-28",
- label: "2025-08-28",
- },
- ];
- const areaValue = ref("1");
- const areaOptions = [
- {
- value: "1",
- label: "全部区域",
- },
- ];
- const tabsContent = ref(["果园总览", "整体园相", "营养管理", "病虫管理", "农事记录"]);
- const activeTabsContent = ref(0);
- const handleTabsContentClick = (index) => {
- activeTabsContent.value = index;
- };
- const emit = defineEmits(["heightChange"]);
- const cardContentRef = ref(null);
- const isBackground = ref(false);
- const handleHeightChange = ({ height }) => {
- isBackground.value = false;
- if (height > anchors.value[1]) {
- isBackground.value = true;
- }
- if (height === anchors.value[1]) {
- cardContentHeight.value = 180;
- cardContentRef.value.scrollTo({ top: 0, behavior: "smooth" });
- } else if (height === anchors.value[2]) {
- cardContentHeight.value = Math.round(1 * window.innerHeight) - (tabBarHeight.value - 40) - 180;
- }
- emit("heightChange", height);
- };
- const cardContentHeight = ref(180);
- const handleExpandBtnClick = () => {
- cardContentHeight.value = 180;
- height.value = anchors.value[1];
- cardContentRef.value.scrollTo({ top: 0, behavior: "smooth" });
- emit("heightChange", anchors.value[1]);
- };
- </script>
- <style lang="scss" scoped>
- .van-floating-panel {
- border-radius: 0;
- }
- .floating-panel {
- width: 100%;
- background: linear-gradient(180deg, transparent 0%, #f5f7fb 14%);
- ::v-deep {
- .van-floating-panel__content {
- background: transparent;
- overflow: hidden;
- }
- }
- .floating-panel-header {
- width: calc(100% - 24px);
- border-radius: 14px;
- margin: 0 auto 10px;
- background: #fff;
- &.file-header-active{
- border-radius: 14px 14px 0 0;
- margin-bottom: 0;
- }
- .tabs {
- display: flex;
- .tab-item {
- flex: 1;
- text-align: center;
- font-size: 16px;
- color: rgba(0, 0, 0, 0.5);
- font-weight: 500;
- padding: 10px 0;
- &.active {
- color: #2199f8;
- border-radius: 14px 14px 0 0;
- background: linear-gradient(180deg, #cee5fb 0%, #fff 80%);
- }
- }
- }
- .file-header {
- .select-group {
- display: flex;
- justify-content: center;
- padding-top: 5px;
- .select-item {
- width: 115px;
- ::v-deep {
- .el-select__wrapper {
- text-align: center;
- gap: 2px;
- box-shadow: none;
- justify-content: center;
- }
- .el-select__selection {
- flex: none;
- width: fit-content;
- }
- .el-select__placeholder {
- position: static;
- transform: none;
- width: fit-content;
- color: #000;
- }
- .el-select__caret {
- color: #000;
- }
- }
- }
- .select-item:first-child {
- margin-right: 10px;
- }
- }
- ::v-deep{
- .el-anchor{
- --el-anchor-line-height: auto;
- }
- .el-anchor__marker{
- height: 0;
- }
- .el-anchor.el-anchor--horizontal .el-anchor__list{
- width: 100%;
- }
- .el-anchor__link.is-active{
- background: rgba(33, 153, 248, 0.2);
- }
- }
- .tabs-content-group {
- display: flex;
- justify-content: space-evenly;
- padding: 5px 8px;
- background-color: transparent;
- .tabs-content-item {
- flex: 1;
- font-size: 14px;
- color: rgba(0, 0, 0, 0.5);
- font-weight: 500;
- padding: 1px 0;
- border-radius: 14px;
- text-align: center;
- }
- }
- }
- }
- .floating-panel-content {
- width: calc(100% - 24px);
- height: 100%;
- margin: 0 auto;
- .card-content-group {
- padding-bottom: 12px;
- height: 100%;
- box-sizing: border-box;
- overflow: auto;
- .card-content-item {
- border-radius: 14px;
- padding: 12px;
- background: #fff;
- color: #171717;
- .card-content-item-title {
- font-size: 16px;
- font-weight: 500;
- text-align: center;
- position: relative;
- &::before {
- content: "";
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
- bottom: -1px;
- width: 66px;
- height: 8px;
- background: rgba(33, 153, 248, 0.3);
- border-radius: 4px;
- }
- }
- .card-content-item-content {
- margin-top: 12px;
- border-radius: 8px;
- background: rgba(238, 238, 238, 0.3);
- padding: 10px;
- line-height: 21px;
- .card-name {
- font-weight: 500;
- }
- .card-value {
- font-size: 12px;
- color: rgba(23, 23, 23, 0.6);
- }
- .map-wrap {
- margin-top: 10px;
- .map-img {
- width: 100%;
- height: 137px;
- }
- .map-text {
- font-size: 12px;
- color: rgba(23, 23, 23, 0.6);
- text-align: center;
- margin-top: 5px;
- }
- }
- .card-text + .card-text {
- margin-top: 5px;
- }
- }
- }
- .card-content-item + .card-content-item {
- margin-top: 10px;
- }
- }
- }
- &.background-panel {
- background: #f5f7fb;
- .floating-panel-header {
- margin-top: 12px;
- }
- }
- }
- .expand-btn-wrap{
- position: absolute;
- bottom: 62px;
- left: 12px;
- width: calc(100% - 24px);
- background-image: linear-gradient(180deg, #d7eafc 0%, #ffffff 100%);
- border-radius: 14px;
- padding: 15px 12px;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-weight: 500;
- font-size: 15px;
- .expand-btn{
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 4px;
- font-size: 13px;
- color: #2199f8;
- }
- }
- </style>
|