| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- <template>
- <div class="farm-details-page">
- <custom-header name="农场详情"></custom-header>
- <div class="farm-details-content">
- <!-- <farm-info-card
- v-if="farmDetail.name"
- :data="{
- farmName: farmDetail.name || '',
- userType: farmDetail.userType || '托管客户',
- variety: farmDetail.typeName || '',
- address: farmDetail.address || '',
- }"
- @click="handleFarmInfo"
- >
- <template #right>
- <div @click="handleDetail('plan')">农事规划</div>
- </template>
- </farm-info-card> -->
- <tabs v-model:active="activeTab" class="custom-tabs" scrollspy sticky offset-top="40" background="#F2F3F5">
- <tab title="作物档案" class="tab-item">
- <common-box title="作物档案">
- <template #right>
- <span @click="handleDetail('crop_record')">查看详情</span>
- </template>
- <template v-if="farmWorkData.length">
- <div class="farm-work-timeline">
- <div
- class="farm-work-item"
- v-for="(item, index) in farmWorkData"
- :key="index"
- >
- <div class="timeline-left">
- <div class="timeline-dot"></div>
- <div class="timeline-line"></div>
- </div>
- <div class="timeline-right">
- <div class="farm-work-card" :class="['card-' + getRecordTypeText(item.speakTitleName), , {'is-future': item.isFuture}]">
- <div class="type-box">{{ item.speakTitleName }}</div>
- <div class="farm-work-date" v-html="item.content.renderedContent"></div>
- <!-- <div class="farm-work-desc">
- <span class="farm-work-action">{{ item.action }}</span>
- <span class="farm-work-content">{{ item.content }}</span>
- <span>{{ item.text }}</span>
- </div> -->
- </div>
- </div>
- </div>
- </div>
- </template>
- <empty
- v-else
- image="https://birdseye-img.sysuimars.com/birdseye-look-mini/custom-empty-image.png"
- image-size="80"
- description="暂无数据"
- class="empty-state"
- />
- </common-box>
- </tab>
- <tab title="农事服务" class="tab-item">
- <common-box title="农事服务">
- <template #right>
- <span @click="handleDetail('service_list')">查看详情</span>
- </template>
- <tab-list
- type="light"
- v-model="farmServiceActiveTab"
- :tabs="farmServiceTabs"
- @change="handleFarmServiceTabChange"
- />
- <stats-box :stats-data="serviceStatsData" />
- <div v-for="(section, index) in detailList" :key="index" class="content-section">
- <record-item
- :record-item-data="section"
- onlyRecipeName
- :content-mode="farmServiceActiveTab === 0 ? 'serviceDetail' : ''"
- title-mode="default"
- :title-right-text="farmServiceActiveTab === 0 ? '生成成果报告' : ''"
- :title-right-type="farmServiceActiveTab === 1 ? 'dot' : null"
- :title-right-dot-text="farmServiceActiveTab === 1 ? '全区' : ''"
- class="recipe-item"
- @titleRightClick="handleTitleRightClick"
- />
- </div>
- <empty
- v-if="detailList.length === 0"
- image="https://birdseye-img.sysuimars.com/birdseye-look-mini/custom-empty-image.png"
- image-size="80"
- description="暂无数据"
- class="empty-state"
- />
- </common-box>
- </tab>
- <tab title="作物相册" class="tab-item">
- <common-box title="作物相册">
- <template #right>
- <span @click="handleShareReport()">查看更多</span>
- </template>
- <div class="photo-img-wrap" v-loading="imgsLoading">
- <photo-provider :photo-closable="true">
- <photo-consumer
- v-for="(src, index) in cropAlbum"
- intro="执行照片"
- :key="index"
- :src="base_img_url2 + src.filename"
- >
- <div class="photo-img">
- <img :src="base_img_url2 + src.filename + resize_300" />
- </div>
- </photo-consumer>
- </photo-provider>
- </div>
- </common-box>
- </tab>
- </tabs>
- </div>
- <div class="custom-bottom-fixed-btns center-btn">
- <div class="bottom-btn primary-btn" @click="handleShareFarm">分享认领农场</div>
- <!-- <div class="bottom-btn primary-btn" @click="handleChatFarm">在线沟通</div> -->
- </div>
- </div>
- <fn-share-sheet v-model:show="showShare" @select="onSelect" :options="[{ name: '微信', icon: 'wechat' }]" />
- <!-- 农场信息 -->
- <farm-info-popup
- ref="farmInfoRef"
- :farmId="farmIdVal"
- :showEditBtn="!farmDetail.farmersMiniUserId"
- :showBtn="true"
- ></farm-info-popup>
- </template>
- <script setup>
- import { ref, onMounted } from "vue";
- import { useRoute, useRouter } from "vue-router";
- import { Tab, Tabs, Empty } from "vant";
- import { base_img_url2, resize_300 } from "@/api/config";
- import wx from "weixin-js-sdk";
- import customHeader from "@/components/customHeader.vue";
- // import FarmInfoCard from "@/components/pageComponents/FarmInfoCard.vue";
- import tabList from "@/components/pageComponents/TabList.vue";
- import commonBox from "@/components/pageComponents/CommonBox.vue";
- import StatsBox from "@/components/pageComponents/StatsBox.vue";
- import recordItem from "@/components/recordItem.vue";
- import farmInfoPopup from "../home/components/farmInfoPopup.vue";
- import FnShareSheet from "@/components/pageComponents/FnShareSheet.vue";
- import config from "@/api/config";
- import { ElMessage } from "element-plus";
- const router = useRouter();
- const route = useRoute();
- const activeTab = ref(0);
- const farmServiceTabs = ["过往服务", "未来服务"];
- const farmServiceActiveTab = ref(0);
- const farmInfoRef = ref(null);
- const handleFarmInfo = () => {
- farmInfoRef.value.handleShow();
- };
- const handleFarmServiceTabChange = (index) => {
- if (index === 0) {
- getFarmPastServiceCost();
- getDetailList();
- } else {
- getFutureFarmWorkWarning()
- }
- };
- const getFutureFarmWorkWarning = async () => {
- const {data} = await VE_API.home.listFutureFarmWorkWarning({ farmId: farmIdVal.value });
- let totalCost = 0;
- if (data.length > 0) {
- totalCost = data.reduce((acc, item) => acc + item.estimatedCost, 0);
- detailList.value = data.slice(0, 1);
- }
- serviceStatsData.value = [
- { value: totalCost || 0, unit: "元", desc: "预计成交额" },
- { value: data.length || 0, unit: "次", desc: "预计服务次数" },
- ];
- };
- const serviceStatsData = ref([]);
- onMounted(() => {
- farmIdVal.value = route.query.farmId;
- paramsPage.value = {
- farmId: farmIdVal.value,
- limit: 1,
- page: 1,
- };
- getFarmDetail();
- getFarmWorkList();
- getDetailList();
- getFarmPastServiceCost();
- // 获取图片数据
- getFarmPhoto();
- });
- const farmIdVal = ref(null);
- const farmDetail = ref({});
- const paramsPage = ref({});
- const getFarmDetail = () => {
- VE_API.user.getFarmDetail({ farmId: farmIdVal.value }).then(({ data }) => {
- farmDetail.value = data || {};
- });
- };
- const farmWorkData = ref([]);
- const typeObj = {
- 物候: '1',
- 异常: '2',
- 病虫: '3',
- 农事: '4',
- }
- const getRecordTypeText = (recordType) => {
- return typeObj[recordType];
- }
- const getFarmWorkList = () => {
- VE_API.container_phenology.getFarmSpeakInfo({ farmId: farmIdVal.value }).then(({ data }) => {
- const list = data || [];
- const res = list.filter(item => item.content.hasException !== 0);
- getPhenologyBroadcast();
- // 只展示前三条数据
- farmWorkData.value = res.slice(0, 3);
- });
- };
- const getPhenologyBroadcast = () => {
- VE_API.container_phenology.phenologyBroadcast({ farmId: farmIdVal.value }).then(({ data }) => {
- farmWorkData.value.push({
- speakTitleName: "物候",
- isFuture: true,
- content: {
- renderedContent: data.content,
- },
- });
- });
- };
- const cropAlbum = ref([]);
- const imgsLoading = ref(false);
- // 获取作物相册的三张照片(参考 patrolPhoto 的获取逻辑)
- const getFarmPhoto = async () => {
- if (!farmIdVal.value) return;
- imgsLoading.value = true;
- try {
- // 先获取有图片的日期列表
- const dateParams = {
- farmId: farmIdVal.value,
- pageIndex: 0,
- limit: 10,
- };
- const { data: dateData } = await VE_API.farm.findHasImagesDate(dateParams);
- const dateList = Array.isArray(dateData) ? dateData : [];
- if (!dateList.length) {
- cropAlbum.value = [];
- return;
- }
- const result = [];
- let dateIndex = 0;
- // 按日期依次取图片,直到凑够 3 张或没有更多日期
- while (result.length < 3 && dateIndex < dateList.length) {
- const currentDate = dateList[dateIndex];
- const imgParams = {
- farmId: farmIdVal.value,
- date: currentDate,
- };
- const { data } = await VE_API.farm.getImageInfo(imgParams);
- const images = (data && Array.isArray(data.images)) ? data.images : [];
- images.forEach((item) => {
- if (result.length < 3) {
- // 统一存成 filename 字段,供模板使用
- result.push({
- ...item,
- filename: item.resFilename || item.filename,
- });
- }
- });
- dateIndex += 1;
- }
- cropAlbum.value = result;
- } catch (e) {
- console.error("获取农场相册失败", e);
- cropAlbum.value = [];
- } finally {
- imgsLoading.value = false;
- }
- };
- const detailList = ref([]);
- const getDetailList = () => {
- VE_API.user.farmServiceRecord({ farmId: farmIdVal.value }).then(({ data }) => {
- if(data.length > 0) {
- detailList.value = [data[0]];
- } else {
- detailList.value = [];
- }
- });
- };
- const getFarmPastServiceCost = () => {
- VE_API.user.getFarmPastServiceCost({ farmId: farmIdVal.value }).then(({ data }) => {
- serviceStatsData.value = [
- { value: data?.totalCost, unit: "元", desc: "成交额" },
- { value: data?.serviceCount, unit: "次", desc: "服务次数" },
- ];
- });
- };
- const handleDetail = (path) => {
- router.push(`/${path}?farmId=${farmIdVal.value}&agriculturalStoreId=${route.query.agriculturalStoreId}`);
- };
- const handleShareReport = () => {
- router.push({
- path: "/farm_photo",
- query: {
- // miniJson: JSON.stringify({ farmId: farmIdVal.value }),
- farmId: farmIdVal.value
- },
- });
- };
- const showShare = ref(false);
- const handleShareFarm = () => {
- showShare.value = true;
- };
- const handleChatFarm = () => {
- if (route.query.receiveUserId != "null") {
- router.push(`/chat_frame?userId=${route.query.receiveUserId}&farmId=${farmIdVal.value}`);
- } else {
- ElMessage.warning("尚未绑定用户,暂时无法沟通");
- }
- };
- const onSelect = () => {
- const query = {
- agriculturalStoreId: route.query.agriculturalStoreId,
- farmId: route.query.farmId,
- containerId: farmDetail.value.containerId,
- speciesName: farmDetail.value.speciesName,
- // receiveUserId: route.query.receiveUserId,
- };
- wx.miniProgram.navigateTo({
- url: `/pages/subPages/share_page/index?pageParams=${JSON.stringify(query)}&type=shareFarm`,
- });
- };
- const handleTitleRightClick = (section) => {
- router.push({
- path: "/achievement_report",
- query: { miniJson: JSON.stringify({ id: section.id }) },
- });
- };
- </script>
- <style scoped lang="scss">
- .farm-details-page {
- width: 100%;
- height: 100vh;
- background: #F2F3F5;
- .center-btn {
- justify-content: center;
- }
- .farm-details-content {
- box-sizing: border-box;
- padding: 10px 12px;
- overflow: auto;
- height: calc(100% - 40px - 60px);
- box-sizing: border-box;
- .custom-tabs {
- ::v-deep {
- .van-tabs__wrap {
- height: auto;
- }
- .van-tabs__nav {
- .van-tab {
- color: #8b8b8b;
- background: #F7F8FA;
- height: 34px;
- font-weight: 400;
- border-radius: 25px;
- width: fit-content;
- flex: none;
- padding: 0 12px;
- margin-right: 8px;
- }
- .van-tab--active {
- color: #fff;
- background: #2199f8;
- font-weight: 400;
- }
- }
- .van-tabs__line {
- display: none;
- }
- .van-tabs__nav--line {
- padding: 12px 0;
- }
- }
- .tab-item + .tab-item {
- margin-top: 12px;
- }
- .photo-img-wrap {
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- ::v-deep {
- .PhotoConsumer {
- width: 31%;
- height: 92px;
- }
- }
- .photo-img {
- width: 100%;
- height: 100%;
- position: relative;
- box-sizing: border-box;
- border: 2px solid transparent;
- border-radius: 8px;
- overflow: hidden;
- img {
- width: 100%;
- height: 100%;
- border-radius: 8px;
- object-fit: cover;
- }
- }
- }
- }
- .question-header {
- display: flex;
- align-items: center;
- margin-bottom: 6px;
- gap: 8px;
- font-weight: 500;
- .question-icon {
- width: 22px;
- height: 20px;
- }
- }
- .answer-content {
- color: #333333;
- margin: 6px 0 10px 0;
- }
- .answer-img {
- display: flex;
- gap: 5px;
- img {
- flex: 1;
- max-width: 105px;
- height: 105px;
- border-radius: 5px;
- object-fit: cover;
- }
- }
- .content-section {
- .recipe-item {
- border: 1px solid rgba(0, 0, 0, 0.1);
- margin: 12px 0 0 0;
- }
- }
- .plan-tab-item {
- .recipe-item {
- padding: 0;
- }
- }
- .plan-list-wrapper {
- height: 500px;
- margin-top: 12px;
- }
- .report-content {
- font-size: 13px;
- }
- .answer-btn {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-top: 10px;
- > div {
- display: flex;
- gap: 10px;
- }
- }
- .answer-btn-item {
- padding: 7px 12px;
- border-radius: 25px;
- font-size: 12px;
- text-align: center;
- background: rgba(33, 153, 248, 0.1);
- color: #2199f8;
- min-width: 52px;
- box-sizing: border-box;
- &.primary {
- background: #2199f8;
- color: #ffffff;
- }
- }
- .empty-state {
- ::v-deep .van-empty {
- padding: 40px 0;
- }
- }
- .footer-data {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 12px;
- margin-top: 12px;
- .footer-l {
- display: flex;
- gap: 8px;
- flex: 1;
- .farm-info-footer-item {
- display: flex;
- border: 0.4px solid rgba(215, 215, 215, 0.5);
- padding: 8px 5px 5px;
- box-sizing: border-box;
- .farm-info-footer-item-label {
- font-size: 12px;
- color: rgba(32, 32, 32, 0.4);
- margin-bottom: 4px;
- }
- .farm-info-footer-item-value {
- font-size: 16px;
- color: #202020;
- padding-left: 2px;
- .unit {
- font-size: 12px;
- padding-left: 2px;
- color: rgba(32, 32, 32, 0.4);
- }
- }
- }
- }
- .footer-action {
- border: 0.5px solid #888B8D;
- border-radius: 20px;
- padding: 5px 12px;
- font-size: 12px;
- color: #888B8D;
- white-space: nowrap;
- cursor: pointer;
- flex-shrink: 0;
- }
- }
- .farm-work-timeline {
- padding: 10px 0;
- .farm-work-item {
- display: flex;
- align-items: flex-start;
- position: relative;
- &:not(:last-child) {
- margin-bottom: 20px;
- }
- .timeline-left {
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-right: 12px;
- position: relative;
- .timeline-dot {
- width: 6px;
- height: 6px;
- border-radius: 50%;
- border: 1px solid #2199f8;
- flex-shrink: 0;
- z-index: 1;
- }
- .timeline-line {
- width: 1px;
- height: 48px;
- background: #e5e6eb;
- position: absolute;
- top: 8px;
- }
- }
- .timeline-right {
- flex: 1;
- .farm-work-card {
- border: 1px solid #8bccff;
- border-radius: 4px;
- background: #f8fcff;
- padding: 12px;
- display: flex;
- align-items: center;
- color: #1d2129;
- font-size: 14px;
- line-height: 22px;
- display: flex;
- align-items: center;
- &.card-1 {
- border: 1px solid #8BCCFF;
- .type-box {
- background: #2199F8;
- }
- .farm-work-content {
- color: #2199F8;
- }
- }
- &.card-4 {
- border: 1px solid #FFBB83;
- .type-box {
- background: #FF953D;
- }
- .farm-work-content {
- color: #FF953D;
- }
- }
- &.card-2, &.card-3 {
- border: 1px solid #FF9C9C;
- .type-box {
- background: #FD7676;
- }
- .farm-work-content {
- color: #FD7676;
- }
- }
- &.is-future {
- padding: 0 12px;
- // opacity: 0.5;
- background: rgba(246, 250, 255, 0.5);
- .type-box {
- background: rgba(33, 153, 248, 0.5);
- }
- .farm-work-content {
- color: rgba(29, 33, 41, 0.5);
- }
- }
- .type-box {
- margin-right: 12px;
- padding: 0 5px;
- height: 20px;
- line-height: 20px;
- font-size: 12px;
- flex: none;
- color: #fff;
- border-radius: 0 4px 0 4px;
- }
- .farm-work-date {
- padding-right: 4px;
- }
- .farm-work-desc {
- .farm-work-action {
- padding-right: 4px;
- }
- .farm-work-content {
- padding-right: 4px;
- }
- }
- }
- }
- &.is-estimated {
- .timeline-right {
- .farm-work-card {
- background: rgba(246, 250, 255, 0.5);
- border: 1px solid rgba(190, 218, 255, 0.5);
- .farm-work-date,
- .farm-work-desc {
- color: rgba(29, 33, 41, 0.5);
- }
- }
- }
- }
- }
- }
- }
- }
- </style>
|