| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- <template>
- <div class="plan-page">
- <custom-header
- :name="headerTitle"
- isGoBack
- @goback="goback"
- :isClose="route.query.headerTitle ? true : false"
- ></custom-header>
- <div class="plan-content">
- <div class="plan-content-header" v-if="pageType === 'plant'">
- <el-select
- class="select-item"
- v-model="specieValue"
- placeholder="选择品类"
- @change="() => getListMySchemes('left')"
- >
- <el-option
- v-for="item in options"
- :key="item.id"
- :label="item.name"
- :value="item.defaultContainerId"
- />
- </el-select>
- <tab-list
- class="tabs-list"
- type="light"
- v-model="active"
- :tabs="tabs"
- :scrollType="scrollType"
- @change="handleTabChange"
- />
- </div>
- <div class="tip-box">
- <Highlight
- :keywords="['关注农事/托管农事', '取消关注']"
- source-string="提示:关注农事/托管农事 会触发农情互动,并且为您推送农事,取消关注 则不会为您推送任何与该农事相关的内容"
- />
- </div>
- <div
- class="timeline-wrap"
- :class="{
- 'timeline-container-plant-wrap': pageType == 'plant',
- 'timeline-container-no-permission-wrap': !hasPlanPermission,
- 'no-default-plan-wrap':
- active !== tabs[0]?.id && pageType == 'plant' && tabs[currentTabIndex]?.enabled == 0,
- }"
- >
- <farm-work-plan-timeline
- :pageType="pageType"
- :farmId="route.query.farmId"
- :containerId="containerIdData"
- @row-click="handleRowClick"
- :disableClick="!hasPlanPermission || active === tabs[0]?.id"
- :isStandard="active === tabs[0]?.id"
- :schemeId="active"
- />
- </div>
- </div>
- <div
- class="custom-bottom-fixed-btns"
- :class="{ center: active === tabs[0]?.id && pageType == 'plant' }"
- v-has-permission="'农事规划'"
- >
- <div class="bottom-btn-group-wrap">
- <div
- class="bottom-btn-group"
- :class="{ 'justify-center': active === tabs[0]?.id && pageType == 'plant' }"
- >
- <div
- class="bottom-btn secondary-btn"
- @click="handlePhenologySetting"
- v-show="active !== tabs[0]?.id"
- >
- 物候期设置
- </div>
- <div class="bottom-btn secondary-btn" v-if="pageType === 'plant'" @click="openCopyPlanPopup">
- {{ active === tabs[0]?.id ? "复制方案" : "方案设置" }}
- </div>
- </div>
- <div class="bottom-btn primary-btn" @click="addNewTask" v-show="active !== tabs[0]?.id">新增农事</div>
- </div>
- <template v-if="active !== tabs[0]?.id && pageType == 'plant' && tabs[currentTabIndex]?.enabled == 0">
- <div class="bottom-btn-divider"></div>
- <div class="bottom-btn primary-btn submit-btn" @click="handleSubmitPlan">提交方案</div>
- </template>
- </div>
- </div>
- <!-- 农事信息弹窗 -->
- <detail-dialog ref="detailDialogRef" @triggerFarmWork="triggerFarmWork"></detail-dialog>
- <!-- 复制方案弹窗 -->
- <Popup v-model:show="showCopyPlan" class="copy-plan-popup" round closeable :close-on-click-overlay="false">
- <div class="copy-plan-content">
- <div class="label">{{ active === tabs[0]?.id ? "复制为" : "方案名称" }}</div>
- <el-input v-model="copyPlanName" size="large" placeholder="请输入方案名称" class="copy-plan-input" />
- </div>
- <div class="copy-plan-footer">
- <div class="btn btn-cancel" @click="handleCancelCopyPlan">
- {{ active === tabs[0]?.id ? "取消复制" : "删除方案" }}
- </div>
- <div class="btn btn-confirm" @click="handleConfirmCopyPlan">
- {{ active === tabs[0]?.id ? "确定复制" : "确定设置" }}
- </div>
- </div>
- </Popup>
- <!-- 物候期设置弹窗 -->
- <Popup
- v-model:show="showPhenologySetting"
- class="copy-plan-popup phenology-popup"
- round
- closeable
- :close-on-click-overlay="false"
- >
- <div class="phenology-header">物候期时间设置</div>
- <div class="phenology-list">
- <div class="phenology-item" v-for="(item, index) in mergedReproductiveList" :key="item.id || index">
- <div class="item-label">
- <span class="label-text">{{ item.name }}</span>
- <span>起始时间</span>
- </div>
- <div class="item-value">
- <el-date-picker
- style="width: 100%"
- size="large"
- value-format="YYYY-MM-DD"
- v-model="item.startDate"
- type="date"
- placeholder="选择日期"
- />
- </div>
- </div>
- </div>
- <div class="phenology-footer" @click="handleConfirmPhenologySetting">确认设置</div>
- </Popup>
- <tip-popup
- v-model:show="showTipPopup"
- type="warning"
- text2="还未完善此方案不可用"
- :highlightText="highlightText"
- buttonText="我知道了"
- @confirm="handleBtn"
- />
- </template>
- <script setup>
- import { ref, onMounted, computed } from "vue";
- import { Popup, Highlight } from "vant";
- import customHeader from "@/components/customHeader.vue";
- import tabList from "@/components/pageComponents/TabList.vue";
- import FarmWorkPlanTimeline from "@/components/pageComponents/FarmWorkPlanTimeline.vue";
- import { useRouter, useRoute } from "vue-router";
- import detailDialog from "@/components/detailDialog.vue";
- import eventBus from "@/api/eventBus";
- import tipPopup from "@/components/popup/tipPopup.vue";
- import { ElMessage, ElMessageBox } from "element-plus";
- const router = useRouter();
- const route = useRoute();
- const showTipPopup = ref(false);
- const highlightText = ref("");
- const handleBtn = () => {
- showTipPopup.value = false;
- setTimeout(() => {
- router.go(-1);
- }, 10);
- };
- const goback = () => {
- if (
- tabs.value[currentTabIndex.value]?.enabled == 0 &&
- pageType.value === "plant" &&
- active.value !== tabs.value[0]?.id
- ) {
- highlightText.value = tabs.value[currentTabIndex.value]?.name;
- showTipPopup.value = true;
- } else {
- router.go(-1);
- }
- };
- const userInfoStr = localStorage.getItem("localUserInfo");
- const userInfo = userInfoStr ? JSON.parse(userInfoStr) : {};
- // 检查是否有"农事规划"权限
- const hasPlanPermission = computed(() => {
- try {
- const permissions = userInfo?.agriculturalPermissions || [];
- return permissions.includes("农事规划");
- } catch (error) {
- console.error("解析用户信息失败:", error);
- return false;
- }
- });
- const pageType = ref("");
- const headerTitle = ref("");
- onMounted(() => {
- pageType.value = route.query.pageType || "";
- headerTitle.value = route.query.headerTitle || (pageType.value === "plant" ? "种植方案" : "农事规划");
- if (!pageType.value) {
- getFarmWorkPlanForPhenology();
- } else {
- getSpecieList();
- }
- });
- // 获取品类列表
- const specieValue = ref(null);
- const options = ref([]);
- const getSpecieList = () => {
- VE_API.farm.fetchSpecieList({ agriculturalId: userInfo?.agriculturalId }).then(({ data }) => {
- if (data && data.length) {
- options.value = data || [];
- if (sessionStorage.getItem("specieValue")) {
- specieValue.value = sessionStorage.getItem("specieValue");
- currentTabIndex.value = sessionStorage.getItem("currentTabIndex");
- sessionStorage.removeItem("specieValue");
- sessionStorage.removeItem("currentTabIndex");
- } else {
- specieValue.value = data[0]?.defaultContainerId;
- }
- getListMySchemes("left");
- }
- });
- };
- // 获取方案列表
- const active = ref(null);
- const tabs = ref([]);
- // 控制标签滚动方向:'left' | 'right' | 'auto' | ''
- const scrollType = ref("auto");
- const containerIdData = ref(null);
- const getListMySchemes = (type = "auto") => {
- VE_API.home.listMySchemes({ containerId: specieValue.value }).then(({ data }) => {
- tabs.value = data || [];
- containerIdData.value = tabs.value[0]?.containerId;
- if (sessionStorage.getItem("active")) {
- active.value = sessionStorage.getItem("active");
- sessionStorage.removeItem("active");
- } else {
- if (type === "right") {
- active.value = data[data.length - 1].id;
- } else if (type === "left") {
- active.value = data[0].id;
- } else {
- currentTab.value = data.filter((item) => item.id === currentTab.value.id)[0];
- copyPlanName.value = currentTab.value.name;
- }
- }
- scrollType.value = type;
- getFarmWorkPlanForPhenology();
- });
- };
- const currentTab = ref(null);
- const currentTabIndex = ref(0);
- const handleTabChange = (id, item, index) => {
- active.value = id;
- currentTab.value = item;
- currentTabIndex.value = index;
- getFarmWorkPlanForPhenology();
- };
- const mergedReproductiveList = ref([]);
- const containerSpaceTimeId = ref(null);
- const schemeId = ref(null);
- const getPhenologyList = async () => {
- const params = {
- containerSpaceTimeId: containerSpaceTimeId.value,
- agriculturalId: userInfo?.agriculturalId,
- farmId: route.query.farmId,
- };
- const res = await VE_API.monitor.listPhenology(params);
- if (res.code === 0) {
- mergedReproductiveList.value = res.data || [];
- }
- };
- const farmWorkIds = ref([]);
- const arrangeIds = ref([]);
- // 获取农事规划数据以获取 containerSpaceTimeId
- const getFarmWorkPlanForPhenology = async () => {
- try {
- const { data, code } = await VE_API.monitor.farmWorkPlan({
- containerId: specieValue.value,
- farmId: route.query.farmId,
- schemeId: active.value,
- });
- if (code === 0 && data?.phenologyList?.[0]?.containerSpaceTimeId) {
- containerSpaceTimeId.value = data.phenologyList[0].containerSpaceTimeId;
- schemeId.value = data.phenologyList[0].reproductiveList[0].farmWorkArrangeList[0].schemeId;
- // 收集所有farmWorkId
- farmWorkIds.value = [];
- arrangeIds.value = [];
- data.phenologyList.forEach((phenology) => {
- if (Array.isArray(phenology.reproductiveList)) {
- phenology.reproductiveList.forEach((reproductive) => {
- if (Array.isArray(reproductive.farmWorkArrangeList)) {
- reproductive.farmWorkArrangeList.forEach((farmWork) => {
- if (farmWork.farmWorkId && farmWork.isFollow !== 0) {
- farmWorkIds.value.push(farmWork.farmWorkId);
- arrangeIds.value.push(farmWork.id);
- }
- });
- }
- });
- }
- });
- await getPhenologyList(containerSpaceTimeId.value);
- }
- } catch (error) {
- console.error("获取农事规划数据失败:", error);
- }
- };
- // 复制方案弹窗相关
- const showCopyPlan = ref(false);
- const showPhenologySetting = ref(false);
- const copyPlanName = ref("");
- const openCopyPlanPopup = () => {
- copyPlanName.value = "";
- showCopyPlan.value = true;
- if (active.value !== tabs.value[0]?.id) {
- copyPlanName.value = currentTab.value.name;
- }
- };
- // 物候期设置弹窗
- const handlePhenologySetting = () => {
- showPhenologySetting.value = true;
- };
- /**
- * 确认物候期设置
- */
- const handleConfirmPhenologySetting = async () => {
- const params = {
- farmId: route.query.farmId,
- agriculturalId: userInfo?.agriculturalId,
- items: mergedReproductiveList.value.map((item) => ({
- phenologyId: item.id,
- startDate: item.startDate,
- })),
- };
- const res = await VE_API.monitor.batchSaveFarmPhenologyTime(params);
- if (res.code === 0) {
- ElMessage.success("设置成功");
- showPhenologySetting.value = false;
- getFarmWorkPlanForPhenology();
- }
- };
- // 取消复制方案
- const handleCancelCopyPlan = () => {
- if (active.value === tabs.value[0]?.id) {
- showCopyPlan.value = false;
- } else {
- ElMessageBox.confirm("确定要删除该方案吗?", "提示", {
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- type: "warning",
- }).then(() => {
- VE_API.monitor
- .deleteScheme({
- schemeId: active.value,
- })
- .then(({ code }) => {
- if (code === 0) {
- showCopyPlan.value = false;
- ElMessage.success("删除成功");
- getListMySchemes("left");
- }
- });
- });
- }
- };
- // 确定复制方案
- const handleConfirmCopyPlan = () => {
- if (!copyPlanName.value.trim()) {
- ElMessage.warning("请输入方案名称");
- return;
- }
- if (active.value === tabs.value[0]?.id) {
- VE_API.monitor
- .copyScheme({
- containerId: specieValue.value,
- sourceSchemeId: active.value,
- schemeName: copyPlanName.value,
- })
- .then(({ code, data }) => {
- if (code === 0) {
- showCopyPlan.value = false;
- ElMessage.success("复制成功");
- getListMySchemes("right");
- currentTab.value = data;
- }
- });
- } else {
- VE_API.monitor
- .renameScheme({
- schemeId: active.value,
- name: copyPlanName.value,
- })
- .then(({ code }) => {
- if (code === 0) {
- showCopyPlan.value = false;
- ElMessage.success("修改成功");
- getListMySchemes("auto");
- }
- });
- }
- };
- // 验证药肥报价信息并返回结果
- // 返回: { allTrue: boolean, invalidIds: string[] }
- const validatePesticideFertilizerQuotes = async () => {
- const { data, code } = await VE_API.monitor.batchValidatePesticideFertilizerQuotes({
- ids: farmWorkIds.value,
- schemeId: active.value,
- });
- if (code !== 0 || !data) {
- return { allTrue: false, invalidIds: [] };
- }
- // 判断所有值是否都为true
- const allTrue = Object.values(data).every((value) => value === true);
- // 收集所有不为true的ID
- const invalidIds = Object.keys(data).filter((key) => data[key] !== true);
- return { allTrue, invalidIds };
- };
- // 提交方案
- const handleSubmitPlan = async () => {
- // 调用验证方法,传入所有ids
- if (farmWorkIds.value.length > 0) {
- const { allTrue } = await validatePesticideFertilizerQuotes();
- if (allTrue) {
- VE_API.monitor
- .enableScheme({
- schemeId: active.value,
- })
- .then(({ code }) => {
- if (code === 0) {
- ElMessage.success("提交成功");
- getListMySchemes("auto");
- }
- });
- } else {
- ElMessage.warning("当前方案有未完善报价信息的农事,请先完善报价信息");
- }
- }
- };
- const savePlanPageInfo = () => {
- sessionStorage.setItem("specieValue", specieValue.value);
- sessionStorage.setItem("active", active.value);
- sessionStorage.setItem("arrangeIds", JSON.stringify(arrangeIds.value));
- sessionStorage.setItem("currentTabIndex", currentTabIndex.value);
- };
- // 新增农事
- const addNewTask = () => {
- savePlanPageInfo();
- router.push({
- path: "/add_work",
- query: {
- containerSpaceTimeId: containerSpaceTimeId.value,
- schemeId: schemeId.value,
- },
- });
- };
- const triggerFarmWork = () => {
- eventBus.emit("activeUpload:show", {
- gardenIdVal: route.query.farmId,
- problemTitleVal: "请选择您出现" + curFarmObj.value.farmWorkName + "的时间",
- arrangeIdVal: curFarmObj.value.id,
- needExecutorVal: true,
- });
- };
- const curFarmObj = ref({});
- const handleRowClick = (item) => {
- curFarmObj.value = item;
- savePlanPageInfo();
- sessionStorage.setItem("farmWorkIds", JSON.stringify(item.invalidIds));
- const enabled = tabs.value[currentTabIndex.value]?.enabled;
- router.push({
- path: "/modify",
- query: {
- id: item.id,
- noPrice: pageType.value === "plant" ? true : false,
- farmId: route.query.farmId,
- farmWorkId: item.farmWorkId,
- containerSpaceTimeId: item.containerSpaceTimeId,
- isDefault: active.value === tabs.value[0]?.id,
- enabled: enabled,
- isEdit: item.isEdit,
- },
- });
- };
- </script>
- <style scoped lang="scss">
- .plan-page {
- width: 100%;
- height: 100vh;
- background: #f5f7fb;
- .plan-content {
- .plan-content-header {
- display: flex;
- align-items: center;
- gap: 12px;
- margin: 10px 0 10px 12px;
- .select-item {
- width: 82px;
- ::v-deep {
- .el-select__wrapper {
- box-shadow: none;
- border-radius: 25px;
- border: 0.5px solid rgba(153, 153, 153, 0.5);
- }
- }
- }
- .tabs-list {
- width: calc(100% - 94px);
- margin-right: 8px;
- }
- }
- .tip-box {
- padding: 5px 10px;
- background: rgba(33, 153, 248, 0.1);
- border-radius: 5px;
- font-size: 12px;
- margin: 8px 10px;
- color: #444;
- }
- .timeline-wrap {
- height: calc(100vh - 90px - 80px);
- padding: 0 12px;
- &.timeline-container-plant-wrap {
- height: calc(100vh - 90px - 85px - 38px);
- }
- &.no-default-plan-wrap {
- height: calc(100vh - 90px - 85px - 100px);
- }
- // 没有权限时,底部按钮不显示,高度增加 73px
- &.timeline-container-no-permission-wrap {
- height: calc(100vh - 90px - 18px);
- }
- }
- }
- // 控制区域样式
- .custom-bottom-fixed-btns {
- flex-direction: column;
- .bottom-btn-group-wrap {
- display: flex;
- gap: 12px;
- width: 100%;
- justify-content: space-between;
- .bottom-btn-group {
- display: flex;
- gap: 12px;
- &.justify-center {
- justify-content: center;
- width: 100%;
- }
- }
- }
- &.center {
- justify-content: center;
- .bottom-btn {
- padding: 10px 45px;
- }
- }
- .bottom-btn-divider {
- width: calc(100% + 24px);
- height: 1px;
- background: #f0f0f0;
- margin: 10px -12px;
- }
- .submit-btn {
- padding: 10px 83px;
- }
- }
- }
- .copy-plan-popup {
- width: 100%;
- padding: 50px 12px 20px 12px;
- &::before {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 136px;
- pointer-events: none;
- background: url("@/assets/img/monitor/popup-header-bg.png") no-repeat center center / 100% 100%;
- }
- .copy-plan-content {
- display: flex;
- align-items: center;
- gap: 12px;
- .label {
- font-size: 16px;
- font-weight: 500;
- }
- .copy-plan-input {
- width: calc(100% - 80px);
- }
- }
- .copy-plan-footer {
- display: flex;
- gap: 12px;
- margin-top: 20px;
- .btn {
- flex: 1;
- color: #666666;
- border: 1px solid #999999;
- border-radius: 25px;
- padding: 10px 0;
- font-size: 16px;
- text-align: center;
- &.btn-confirm {
- color: #fff;
- border: 1px solid #2199f8;
- background: #2199f8;
- }
- }
- }
- }
- .phenology-popup {
- padding: 28px 20px 20px;
- .phenology-header {
- font-size: 24px;
- text-align: center;
- margin-bottom: 20px;
- font-family: "PangMenZhengDao";
- }
- .phenology-list {
- width: 100%;
- .phenology-item {
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: space-between;
- .item-label {
- display: flex;
- align-items: center;
- gap: 4px;
- font-size: 15px;
- color: rgba(0, 0, 0, 0.4);
- .label-text {
- color: #000;
- font-size: 16px;
- font-weight: 500;
- }
- }
- .item-value {
- width: calc(100% - 156px);
- }
- }
- .phenology-item + .phenology-item {
- margin-top: 10px;
- }
- }
- .phenology-footer {
- width: 100%;
- text-align: center;
- font-size: 16px;
- margin-top: 20px;
- color: #fff;
- background: #2199f8;
- border-radius: 25px;
- padding: 10px 0;
- }
- }
- </style>
|