|
|
@@ -1,567 +0,0 @@
|
|
|
-<template>
|
|
|
- <div class="price-detail">
|
|
|
- <custom-header name="报价详情"></custom-header>
|
|
|
- <div class="price-content">
|
|
|
- <div class="box-wrap">
|
|
|
- <div class="price-info">
|
|
|
- <div class="info-title">执行时间</div>
|
|
|
- <div class="info-val">
|
|
|
- <el-date-picker
|
|
|
- class="item-input"
|
|
|
- style="width: 132px"
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
- v-model="executeDate"
|
|
|
- type="date"
|
|
|
- :clearable="false"
|
|
|
- placeholder="选择日期"
|
|
|
- :editable="false"
|
|
|
- />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="price-info">
|
|
|
- <div class="info-title">施肥方式</div>
|
|
|
- <div class="info-val">{{ detailData?.usageMode }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="service-wrap">
|
|
|
- <div class="medicine-box">
|
|
|
- <div class="item-title">服务费用</div>
|
|
|
- <div class="box-wrap">
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-name">执行方式</div>
|
|
|
- <div class="item-val" v-if="detailData?.usageMode === '叶面施'">
|
|
|
- <el-select
|
|
|
- class="select-item"
|
|
|
- v-model="executionMethod"
|
|
|
- placeholder="执行方式"
|
|
|
- style="width: 132px"
|
|
|
- @change="handleExecutionMethodChange"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="(item, index) in modeList"
|
|
|
- :key="index"
|
|
|
- :label="item.name"
|
|
|
- :value="item.value"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
- <div class="item-val" v-else>人工</div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item mt-8">
|
|
|
- <div class="item-name">亩单价</div>
|
|
|
- <div class="item-val">
|
|
|
- <!-- <el-input-number
|
|
|
- style="width: 132px"
|
|
|
- placeholder="服务单价"
|
|
|
- v-model="servicePricePerMu"
|
|
|
- :min="0.0001"
|
|
|
- /> -->
|
|
|
- <!-- <span class="price-unit">元/亩</span> -->
|
|
|
-
|
|
|
- <el-input
|
|
|
- style="width: 132px"
|
|
|
- v-model="servicePricePerMu"
|
|
|
- type="number"
|
|
|
- step="0.01"
|
|
|
- placeholder="服务单价"
|
|
|
- >
|
|
|
- <template #append>元/亩</template>
|
|
|
- </el-input>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-name">亩数</div>
|
|
|
- <div class="item-val">{{ formatArea(detailData?.area) }}亩</div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-total">总计:</div>
|
|
|
- <div class="item-price">{{ getServiceTotal() }}<span class="item-unit">元</span></div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="medicine-wrap">
|
|
|
- <template v-for="(prescription, pIndex) in detailData?.prescriptionList" :key="pIndex">
|
|
|
- <div
|
|
|
- class="medicine-box"
|
|
|
- v-for="(pesticide, mIndex) in prescription.pesticideFertilizerList"
|
|
|
- :key="mIndex"
|
|
|
- >
|
|
|
- <div class="item-title">药肥{{ mIndex + 1 }}</div>
|
|
|
- <div class="box-wrap">
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-name">药肥名称</div>
|
|
|
- <div class="item-val">{{ pesticide.pesticideFertilizerName }}</div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-name">药肥品牌</div>
|
|
|
- <div class="item-val">
|
|
|
- <el-input v-model="pesticide.brand" placeholder="药肥品牌" style="width: 132px" />
|
|
|
- <!-- <el-select
|
|
|
- class="select-item"
|
|
|
- v-model="pesticide.brand"
|
|
|
- placeholder="药肥品牌"
|
|
|
- style="width: 132px"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="(brand, bIndex) in brandList"
|
|
|
- :key="bIndex"
|
|
|
- :label="brand.name"
|
|
|
- :value="brand.value"
|
|
|
- />
|
|
|
- </el-select> -->
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item mt-8">
|
|
|
- <div class="item-name">药肥单价</div>
|
|
|
- <div class="item-val">
|
|
|
- <!-- <el-input-number
|
|
|
- style="width: 132px"
|
|
|
- placeholder="单价"
|
|
|
- v-model="pesticide.price"
|
|
|
- :min="0.0000000001"
|
|
|
- /> -->
|
|
|
- <!-- <span class="price-unit">元/{{ pesticide.unit }}</span> -->
|
|
|
-
|
|
|
- <el-input
|
|
|
- style="width: 132px"
|
|
|
- v-model="pesticide.price"
|
|
|
- type="number"
|
|
|
- step="0.01"
|
|
|
- placeholder="单价"
|
|
|
- >
|
|
|
- <template #append>元/{{ pesticide.unit }}</template>
|
|
|
- </el-input>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-name">单亩用量</div>
|
|
|
- <div class="item-val">{{ getMuUsage(pesticide) }}{{ pesticide.unit }}</div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-name">亩数</div>
|
|
|
- <div class="item-val">{{ formatArea(detailData?.area) }}亩</div>
|
|
|
- </div>
|
|
|
- <div class="medicine-item">
|
|
|
- <div class="item-total">总计:</div>
|
|
|
- <div class="item-price">
|
|
|
- {{ getPesticideTotal(pesticide) }}<span class="item-unit">元</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="bottom-btn">
|
|
|
- <div class="bottom-l">
|
|
|
- 合计:<span class="main-val">{{ getTotalCost() }}</span
|
|
|
- >元
|
|
|
- </div>
|
|
|
- <div class="bottom-r" @click="confirmPrice">确认报价</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup>
|
|
|
-import customHeader from "@/components/customHeader.vue";
|
|
|
-import { ElMessage } from "element-plus";
|
|
|
-import { ref, onMounted, onActivated, onBeforeUnmount, onDeactivated } from "vue";
|
|
|
-import { useRoute, useRouter } from "vue-router";
|
|
|
-import { formatArea } from "@/common/commonFun";
|
|
|
-
|
|
|
-const router = useRouter();
|
|
|
-const executeDate = ref(null);
|
|
|
-let query = useRoute().query;
|
|
|
-const detailData = ref(JSON.parse(query.data));
|
|
|
-const priceData = ref({});
|
|
|
-
|
|
|
-const servicePricePerMu = ref(null);
|
|
|
-const executionMethod = ref(null);
|
|
|
-const modeList = ref([
|
|
|
- { name: "无人机", value: 1 },
|
|
|
- { name: "人工", value: 2 },
|
|
|
-]);
|
|
|
-
|
|
|
-// 初始化数据
|
|
|
-onActivated(() => {
|
|
|
- query = useRoute().query;
|
|
|
- detailData.value = JSON.parse(query.data);
|
|
|
- if (detailData.value.usageMode === "根部施") {
|
|
|
- executionMethod.value = 2;
|
|
|
- }
|
|
|
- priceData.value = JSON.parse(query?.priceData || "{}");
|
|
|
- executeDate.value = priceData.value.executeDate;
|
|
|
-
|
|
|
- // 从 priceData 中匹配价格和品牌到对应的药肥
|
|
|
- if (priceData.value?.itemsList && detailData.value?.prescriptionList) {
|
|
|
- executionMethod.value = priceData.value.executionMethod;
|
|
|
- if (detailData.value.usageMode === "根部施") {
|
|
|
- executionMethod.value = 2;
|
|
|
- }
|
|
|
- detailData.value.prescriptionList.forEach((prescription) => {
|
|
|
- if (prescription.pesticideFertilizerList) {
|
|
|
- prescription.pesticideFertilizerList.forEach((pesticide) => {
|
|
|
- const priceItem = priceData.value.itemsList.find(
|
|
|
- (item) => item.pesticideFertilizerId === pesticide.pesticideFertilizerId
|
|
|
- );
|
|
|
- if (priceItem) {
|
|
|
- pesticide.price = Number(priceItem.price) || null;
|
|
|
- pesticide.brand = priceItem.brand || "";
|
|
|
- } else {
|
|
|
- pesticide.price = null;
|
|
|
- pesticide.brand = "";
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化服务费用
|
|
|
- if (priceData.value?.farmWorkServiceCost && detailData.value?.area) {
|
|
|
- servicePricePerMu.value = priceData.value.farmWorkServiceCost || null;
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-// 清空数据
|
|
|
-const clearData = () => {
|
|
|
- executeDate.value = null;
|
|
|
- detailData.value = {};
|
|
|
- priceData.value = {};
|
|
|
- servicePricePerMu.value = null;
|
|
|
- executionMethod.value = null;
|
|
|
-};
|
|
|
-
|
|
|
-// 离开页面时清空数据
|
|
|
-onBeforeUnmount(() => {
|
|
|
- clearData();
|
|
|
-});
|
|
|
-
|
|
|
-onDeactivated(() => {
|
|
|
- clearData();
|
|
|
-});
|
|
|
-
|
|
|
-// 根据执行方式获取单亩用量:1=无人机用muUsage2,2=人工用muUsage
|
|
|
-const getMuUsage = (pesticide) => {
|
|
|
- if (!pesticide) return 0;
|
|
|
- // 如果是叶面施且有执行方式选择,根据执行方式判断
|
|
|
- if (
|
|
|
- detailData.value?.usageMode === "叶面施" &&
|
|
|
- executionMethod.value !== null &&
|
|
|
- executionMethod.value !== undefined
|
|
|
- ) {
|
|
|
- // 1 = 无人机,使用 muUsage2
|
|
|
- if (executionMethod.value == 1) {
|
|
|
- return pesticide.muUsage2 || pesticide.muUsage || 0;
|
|
|
- }
|
|
|
- // 2 = 人工,使用 muUsage
|
|
|
- if (executionMethod.value == 2) {
|
|
|
- return pesticide.muUsage || 0;
|
|
|
- }
|
|
|
- }
|
|
|
- // 默认使用 muUsage(非叶面施的情况)
|
|
|
- return pesticide.muUsage || 0;
|
|
|
-};
|
|
|
-
|
|
|
-// 计算单个药肥的总计:单价 * 单亩用量 * 亩数
|
|
|
-const getPesticideTotal = (pesticide) => {
|
|
|
- const muUsage = getMuUsage(pesticide);
|
|
|
- if (!pesticide.price || !muUsage || !detailData.value.area) return "0.00";
|
|
|
- const total = (pesticide.price * muUsage * detailData.value.area).toFixed(2);
|
|
|
- return total;
|
|
|
-};
|
|
|
-
|
|
|
-// 计算服务费用总计:亩单价 * 亩数
|
|
|
-const getServiceTotal = () => {
|
|
|
- if (!servicePricePerMu.value || !detailData.value.area) return "0.00";
|
|
|
- const total = (servicePricePerMu.value * detailData.value.area).toFixed(2);
|
|
|
- return total;
|
|
|
-};
|
|
|
-
|
|
|
-// 计算总合计:所有药肥总计 + 服务费用总计
|
|
|
-const getTotalCost = () => {
|
|
|
- let pesticideTotal = 0;
|
|
|
- if (detailData.value.prescriptionList) {
|
|
|
- detailData.value.prescriptionList.forEach((prescription) => {
|
|
|
- if (prescription.pesticideFertilizerList) {
|
|
|
- prescription.pesticideFertilizerList.forEach((pesticide) => {
|
|
|
- const muUsage = getMuUsage(pesticide);
|
|
|
- if (pesticide.price && muUsage && detailData.value.area) {
|
|
|
- pesticideTotal += pesticide.price * muUsage * detailData.value.area;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- const serviceTotal =
|
|
|
- servicePricePerMu.value && detailData.value.area ? servicePricePerMu.value * detailData.value.area : 0;
|
|
|
-
|
|
|
- return (pesticideTotal + serviceTotal).toFixed(2);
|
|
|
-};
|
|
|
-
|
|
|
-const confirmPrice = () => {
|
|
|
- if (!executionMethod.value) {
|
|
|
- ElMessage.error("请选择执行方式");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 检查服务费用是否有价格
|
|
|
- if (!servicePricePerMu.value || servicePricePerMu.value <= 0) {
|
|
|
- ElMessage.error("请填写服务费用");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否所有药肥都有价格和品牌
|
|
|
- if (detailData.value?.prescriptionList) {
|
|
|
- const emptyItems = [];
|
|
|
- detailData.value.prescriptionList.forEach((prescription) => {
|
|
|
- (prescription.pesticideFertilizerList || []).forEach((pesticide) => {
|
|
|
- const pesticideName = pesticide.pesticideFertilizerName || "药肥";
|
|
|
- const hasPrice = pesticide.price && pesticide.price > 0;
|
|
|
- const hasBrand = pesticide.brand && pesticide.brand.trim() !== "";
|
|
|
-
|
|
|
- if (!hasPrice || !hasBrand) {
|
|
|
- let errorMsg = "";
|
|
|
- if (!hasPrice && !hasBrand) {
|
|
|
- errorMsg = `${pesticideName}的品牌和单价`;
|
|
|
- } else if (!hasPrice) {
|
|
|
- errorMsg = `${pesticideName}的单价`;
|
|
|
- } else if (!hasBrand) {
|
|
|
- errorMsg = `${pesticideName}的品牌`;
|
|
|
- }
|
|
|
- emptyItems.push(errorMsg);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- if (emptyItems.length > 0) {
|
|
|
- ElMessage.error(`请填写${emptyItems[0]}`);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const pesticideFertilizerQuoteList = [];
|
|
|
- if (detailData.value?.prescriptionList) {
|
|
|
- detailData.value.prescriptionList.forEach((prescription) => {
|
|
|
- (prescription.pesticideFertilizerList || []).forEach((pesticide) => {
|
|
|
- pesticideFertilizerQuoteList.push({
|
|
|
- pesticideFertilizerId: pesticide.pesticideFertilizerId,
|
|
|
- price: Number(pesticide.price || 0),
|
|
|
- brand: pesticide.brand || "",
|
|
|
- });
|
|
|
- });
|
|
|
- });
|
|
|
- }
|
|
|
- const payload = {
|
|
|
- farmWorkRecordId: detailData.value?.id,
|
|
|
- pesticideFertilizerQuoteList,
|
|
|
- executeDate: executeDate.value,
|
|
|
- servicePrice: servicePricePerMu.value,
|
|
|
- executionMethod: executionMethod.value,
|
|
|
- };
|
|
|
- VE_API.z_farm_work_record.acceptFarmWorkRecord(payload).then(({ data, code, msg }) => {
|
|
|
- if (code === 0) {
|
|
|
- ElMessage.success("确认报价成功");
|
|
|
- // router.push({
|
|
|
- // path: "/task_condition",
|
|
|
- // });
|
|
|
- router.back();
|
|
|
- } else {
|
|
|
- ElMessage.error(msg);
|
|
|
- }
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
-const handleExecutionMethodChange = (val) => {
|
|
|
- if (val == 1) {
|
|
|
- servicePricePerMu.value = priceData.value.uavServicePrice;
|
|
|
- } else {
|
|
|
- servicePricePerMu.value = priceData.value.manualServicePrice;
|
|
|
- }
|
|
|
-};
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.price-detail {
|
|
|
- height: 100vh;
|
|
|
- position: relative;
|
|
|
- font-size: 14px;
|
|
|
- background: #f2f3f5;
|
|
|
- color: #000;
|
|
|
- .price-content {
|
|
|
- padding: 12px;
|
|
|
- box-sizing: border-box;
|
|
|
- height: calc(100% - 40px - 74px);
|
|
|
- overflow: auto;
|
|
|
- ::v-deep {
|
|
|
- .el-input__wrapper,
|
|
|
- .el-select__wrapper {
|
|
|
- box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
|
|
|
- }
|
|
|
- .el-input__inner {
|
|
|
- color: #2199f8;
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
- .el-select__placeholder {
|
|
|
- color: #2199f8;
|
|
|
- &.is-transparent {
|
|
|
- color: rgba(33, 153, 248, 0.6);
|
|
|
- }
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
- .el-input__prefix {
|
|
|
- color: #2199f8;
|
|
|
- }
|
|
|
- .el-select__caret {
|
|
|
- color: #2199f8;
|
|
|
- }
|
|
|
- .el-input {
|
|
|
- --el-input-placeholder-color: rgba(33, 153, 248, 0.6);
|
|
|
- }
|
|
|
- .el-input-number__decrease,
|
|
|
- .el-input-number__increase {
|
|
|
- display: none;
|
|
|
- }
|
|
|
- .el-input-number .el-input__wrapper {
|
|
|
- padding-left: 12px;
|
|
|
- padding-right: 12px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .box-wrap {
|
|
|
- background: #fff;
|
|
|
- padding: 10px;
|
|
|
- border-radius: 8px;
|
|
|
- }
|
|
|
- .price-info {
|
|
|
- height: 32px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- .info-val {
|
|
|
- color: #474747;
|
|
|
- width: 132px;
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
- }
|
|
|
- .price-info + .price-info {
|
|
|
- padding-top: 6px;
|
|
|
- }
|
|
|
-
|
|
|
- .medicine-box {
|
|
|
- padding-top: 10px;
|
|
|
- .item-title {
|
|
|
- padding-left: 5px;
|
|
|
- font-size: 16px;
|
|
|
- color: #000000;
|
|
|
- font-weight: 500;
|
|
|
- padding-bottom: 10px;
|
|
|
- }
|
|
|
- .medicine-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- height: 32px;
|
|
|
- .item-name {
|
|
|
- color: rgba(0, 0, 0, 0.4);
|
|
|
- }
|
|
|
- .item-val {
|
|
|
- min-width: 142px;
|
|
|
- text-align: center;
|
|
|
- color: #474747;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- gap: 4px;
|
|
|
- .price-unit {
|
|
|
- font-size: 12px;
|
|
|
- color: rgba(0, 0, 0, 0.4);
|
|
|
- white-space: nowrap;
|
|
|
- }
|
|
|
- ::v-deep {
|
|
|
- .el-input__wrapper {
|
|
|
- box-shadow: none;
|
|
|
- }
|
|
|
- .el-input-group__append {
|
|
|
- padding: 0 10px;
|
|
|
- background: none;
|
|
|
- box-shadow: none;
|
|
|
- }
|
|
|
- .el-input-group__append {
|
|
|
- color: rgba(33, 153, 248, 0.5);
|
|
|
- }
|
|
|
- .el-input {
|
|
|
- border: 1px solid rgba(33, 153, 248, 0.3);
|
|
|
- border-radius: 5px;
|
|
|
- height: 30px;
|
|
|
- box-sizing: border-box;
|
|
|
- }
|
|
|
- .el-input__wrapper {
|
|
|
- padding: 0 2px 0 10px;
|
|
|
- height: 28px;
|
|
|
- line-height: 28px;
|
|
|
- min-height: 28px;
|
|
|
- }
|
|
|
- .el-input__inner {
|
|
|
- --el-input-inner-height: 28px;
|
|
|
- height: 28px;
|
|
|
- line-height: 28px;
|
|
|
- min-height: 28px;
|
|
|
- color: #2199f8;
|
|
|
- --el-input-placeholder-color: rgba(33, 153, 248, 0.43);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .item-total {
|
|
|
- font-size: 16px;
|
|
|
- color: #000;
|
|
|
- }
|
|
|
- .item-price {
|
|
|
- color: #2199f8;
|
|
|
- font-size: 20px;
|
|
|
- font-weight: bold;
|
|
|
- .item-unit {
|
|
|
- font-size: 14px;
|
|
|
- font-weight: normal;
|
|
|
- padding-left: 2px;
|
|
|
- color: #474747;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .medicine-item + .medicine-item {
|
|
|
- padding-top: 2px;
|
|
|
- }
|
|
|
- .mt-8 {
|
|
|
- margin-top: 8px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .bottom-btn {
|
|
|
- height: 74px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- background: #fff;
|
|
|
- padding: 12px;
|
|
|
- box-sizing: border-box;
|
|
|
- box-shadow: 0 -1px 11px rgba(0, 0, 0, 0.1);
|
|
|
- .bottom-l {
|
|
|
- color: #000000;
|
|
|
- font-size: 16px;
|
|
|
- .main-val {
|
|
|
- color: #2199f8;
|
|
|
- font-size: 24px;
|
|
|
- font-weight: bold;
|
|
|
- padding-right: 4px;
|
|
|
- }
|
|
|
- }
|
|
|
- .bottom-r {
|
|
|
- background: linear-gradient(136deg, #9fd5ff, #2199f8);
|
|
|
- padding: 8px 32px;
|
|
|
- border-radius: 20px;
|
|
|
- color: #fff;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|