spring
2025-11-19 1187936c713bae2ad43063900c7bee80502e091d
fix: 重构拉丝报工
已添加1个文件
已修改9个文件
1454 ■■■■ 文件已修改
src/api/product/wire.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/product_card/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/index/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/detail/twistDetail.vue 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/detail/wireDetail.vue 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/list/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/twist/report/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/wire/report/reportManage.vue 655 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/wire/report/wire.vue 627 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/product/wire.ts
@@ -19,6 +19,59 @@
      data: data,
    });
  },
  // èŽ·å–æ‹‰ä¸æŠ¥å·¥æ ‘å½¢æ•°æ®
  getWireOutputTree(params: any) {
    return request<BaseResult<any>>({
      url: "/app/getWireOutputTree",
      method: "GET",
      data: params,
    });
  },
  // æ–°å¢žæ†åŒ…
  addRodBagTree(data: any) {
    return request<BaseResult<any>>({
      url: "/app/addRodBagTree",
      method: "POST",
      data: data,
    });
  },
  // åˆ é™¤æ†åŒ…
  deleteRodBagTree(data: any) {
    return request<BaseResult<any>>({
      url: "/app/deleteRodBagTree",
      method: "DELETE",
      data: data,
    });
  },
  // æ›´æ–°æ†åŒ…
  updateRodBagTree(data: any) {
    return request<BaseResult<any>>({
      url: "/wireOutput/updateRodBagTree",
      method: "POST",
      data: data,
    });
  },
  // æ‰¹é‡æ–°å¢žæ‹‰ä¸æŠ¥å·¥
  addWireOutputList(data: any) {
    return request<BaseResult<any>>({
      url: "/wireDrawing/addWireOutputList",
      method: "POST",
      data: data,
    });
  },
  // åˆ é™¤æ‹‰ä¸æŠ¥å·¥
  deleteWireOutput(params: any) {
    return request<BaseResult<any>>({
      url: `/app/deleteWireOutput?id=${params.id}`,
      method: "DELETE",
    });
  },
};
export default WireApi;
src/components/product_card/index.vue
@@ -21,6 +21,32 @@
        </view>
      </wd-col>
    </wd-row>
    <wd-row class="my-2" v-if="data.type === '拉丝' && data.poleModel">
      <wd-col :span="24">
        <view class="flex">
          <view class="icon_box">
            <wd-icon name="folder" color="#0D867F"></wd-icon>
          </view>
          <text class="text-[#646874] mx-2">
            é“æ†åž‹å·:
            <text class="text-[#252525]">{{ data.poleModel }}</text>
          </text>
        </view>
      </wd-col>
    </wd-row>
    <wd-row class="my-2" v-if="data.type === '拉丝' && data.contractNo">
      <wd-col :span="24">
        <view class="flex">
          <view class="icon_box">
            <wd-icon name="folder" color="#0D867F"></wd-icon>
          </view>
          <text class="text-[#646874] mx-2">
            åˆåŒå·:
            <text class="text-[#252525]">{{ data.contractNo }}</text>
          </text>
        </view>
      </wd-col>
    </wd-row>
    <wd-row class="my-2">
      <wd-col :span="12">
        <view class="flex">
src/pages.json
@@ -164,6 +164,12 @@
      }
    },
    {
      "path": "pages/production/wire/report/reportManage",
      "style": {
        "navigationBarTitleText": "报工管理"
      }
    },
    {
      "path": "pages/production/wire/attachment/index",
      "style": {
        "navigationBarTitleText": "拉丝附件"
src/pages/index/index.vue
@@ -252,8 +252,8 @@
  // å­˜å‚¨ç­ç»„ID和生产准备ID
  if (data) {
    if (data.team) {
      setTeamId(data.team);
    if (data.id) {
      setTeamId(data.id);
    }
    if (data.prepareId) {
      setPrepareId(data.prepareId);
src/pages/production/detail/twistDetail.vue
@@ -41,7 +41,7 @@
import { onLoad } from "@dcloudio/uni-app";
import ProductCard from "@/components/product_card/index.vue";
import TwistApi from "@/api/product/twist";
import { getPrepareId, setPrepareId } from "@/utils/cache";
import { getPrepareId, setPrepareId, clearPrepareId } from "@/utils/cache";
import HomeApi from "@/api/home";
const paramsId = ref();
@@ -72,9 +72,14 @@
    const { data } = await HomeApi.getIndex();
    if (data && data.prepareId) {
      setPrepareId(data.prepareId);
    } else {
      // å¦‚果没有 prepareId,清空缓存
      clearPrepareId();
    }
  } catch (error) {
    console.error("获取生产准备ID失败:", error);
    // èŽ·å–å¤±è´¥æ—¶ä¹Ÿæ¸…ç©ºç¼“å­˜
    clearPrepareId();
  }
};
src/pages/production/detail/wireDetail.vue
@@ -9,16 +9,13 @@
        totalAmount: 'totalAmount',
        amount: 'amount',
        unAmount: 'unAmount',
        poleModel: 'poleModel',
        contractNo: 'contractNo',
      }"
    />
    <view class="mx-3">
      <wd-grid class="rounded-lg" clickable>
        <wd-grid-item
          icon="computer"
          link-type="navigateTo"
          :url="`/pages/production/wire/report/wire?id=${paramsId}&model=${cardData.model}&oneLength=${cardData.oneLength}`"
          text="报工"
        />
        <wd-grid-item icon="computer" @click="handleReportClick" text="报工" />
        <!-- <wd-grid-item
          icon="chart"
          text="自检"
@@ -46,6 +43,8 @@
import { onLoad } from "@dcloudio/uni-app";
import ProductCard from "@/components/product_card/index.vue";
import WireApi from "@/api/product/wire";
import { getPrepareId, setPrepareId, clearPrepareId } from "@/utils/cache";
import HomeApi from "@/api/home";
const paramsId = ref();
const cardData = reactive({
@@ -56,6 +55,9 @@
  amount: undefined,
  unAmount: undefined,
  oneLength: undefined,
  poleModel: undefined,
  contractNo: undefined,
  type: "拉丝",
});
const getDetailData = async (id: string) => {
@@ -69,11 +71,59 @@
  cardData.amount = data.amount;
  cardData.unAmount = data.unAmount;
  cardData.oneLength = data.oneLength;
  cardData.poleModel = data.poleModel;
  cardData.contractNo = data.contractNo;
  cardData.type = data.type || "拉丝";
};
onLoad((options: any) => {
// èŽ·å–å¹¶ç¼“å­˜ç”Ÿäº§å‡†å¤‡ID
const initPrepareId = async () => {
  try {
    const { data } = await HomeApi.getIndex();
    if (data && data.prepareId) {
      setPrepareId(data.prepareId);
    } else {
      // å¦‚果没有 prepareId,清空缓存
      clearPrepareId();
    }
  } catch (error) {
    console.error("获取生产准备ID失败:", error);
    // èŽ·å–å¤±è´¥æ—¶ä¹Ÿæ¸…ç©ºç¼“å­˜
    clearPrepareId();
  }
};
// å¤„理报工点击
const handleReportClick = () => {
  const prepareId = getPrepareId();
  console.log("拉丝表格报工检查 - prepareId值:", prepareId);
  // å¦‚æžœprepareId为空或未定义,说明生产准备未完成
  if (!prepareId) {
    console.log("拉丝表格报工阻止 - ç”Ÿäº§å‡†å¤‡æœªå®Œæˆ");
    uni.showModal({
      title: "提示",
      content: "请在电脑端完成生产准备确认,再进行报工操作",
      showCancel: false,
      confirmText: "确定",
      success: () => {
        // ç”¨æˆ·ç‚¹å‡»ç¡®å®šåŽï¼Œä¸åšä»»ä½•操作
      },
    });
    return;
  }
  // å¦‚果有 prepareId,正常跳转
  uni.navigateTo({
    url: `/pages/production/wire/report/wire?id=${paramsId.value}&model=${cardData.model}&oneLength=${cardData.oneLength}`,
  });
};
onLoad(async (options: any) => {
  paramsId.value = options.id;
  getDetailData(options.id);
  await getDetailData(options.id);
  // èŽ·å–å¹¶ç¼“å­˜ç”Ÿäº§å‡†å¤‡ID
  await initPrepareId();
});
</script>
src/pages/production/list/index.vue
@@ -41,6 +41,8 @@
  amount: "amount",
  unAmount: "unAmount",
  unit: "unit",
  poleModel: "poleModel",
  contractNo: "contractNo",
});
const props = defineProps({
  api: {
@@ -99,6 +101,8 @@
      map.totalAmount = "totalAmount";
      map.amount = "amount";
      map.unAmount = "unAmount";
      map.poleModel = "poleModel";
      map.contractNo = "contractNo";
    }
    if (data.data.total == 0) {
      pagingRef.value.complete(true);
src/pages/production/twist/report/index.vue
@@ -176,9 +176,9 @@
    const { data } = await HomeApi.getIndex();
    if (data) {
      // å­˜å‚¨ç­ç»„ID
      if (data.team) {
        teamId.value = data.team;
        setTeamId(data.team);
      if (data.id) {
        teamId.value = data.id;
        setTeamId(data.id);
      }
      // å­˜å‚¨ç”Ÿäº§å‡†å¤‡ID
      if (data.prepareId) {
src/pages/production/wire/report/reportManage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,655 @@
<template>
  <view class="report-manage-page">
    <view class="pt-2">
      <wd-card class="card_bg">
        <template #title>
          <view class="flex justify-between w-full">
            <text class="font-medium text-[#252525]">报工管理</text>
            <wd-button
              icon="file-add"
              :round="false"
              size="small"
              custom-class="add_btn"
              @click="handleAdd"
            >
              æ–°å¢ž
            </wd-button>
          </view>
        </template>
        <wd-row class="my-2">
          <wd-col :span="24">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                é¢†ç”¨æ†å·:
                <text class="text-[#252525]">{{ parentData?.poleNumber || "" }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="24">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                æ†åž‹å·:
                <text class="text-[#252525]">{{ parentData?.poleModel || "" }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="24">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                æ†åŒ…号:
                <text class="text-[#252525]">{{ parentData?.polePackageNumber || "" }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="24">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                æ†é‡:
                <text class="text-[#252525]">{{ parentData?.poleWeight || "" }}kg</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
      </wd-card>
    </view>
    <view class="page-content">
      <wd-card
        v-for="(child, childIndex) in childList"
        :key="child.id || child.tempId || childIndex"
        class="card_bg"
      >
        <template #title>
          <text class="font-medium text-[#252525]">单丝盘号: {{ child.monofilamentNumber }}</text>
        </template>
        <wd-row class="my-2" v-if="child.model">
          <wd-col :span="12">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                è§„格型号:
                <text class="text-[#252525]">{{ child.model }}</text>
              </text>
            </view>
          </wd-col>
          <wd-col :span="12">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                ç›˜åž‹å·:
                <text class="text-[#252525]">{{ child.dishModel }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="12" v-if="child.oneLength">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                ç›˜é•¿(m):
                <text class="text-[#252525]">{{ child.oneLength }}</text>
              </text>
            </view>
          </wd-col>
          <wd-col :span="12" v-if="child.isJoint !== undefined && child.isJoint !== null">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                æ˜¯å¦æŽ¥å¤´:
                <text class="text-[#252525]">
                  {{ child.isJoint === 1 ? "是" : child.isJoint === 0 ? "否" : "" }}
                </text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="14" v-if="child.actuallyLength">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                å®žé™…长度(m):
                <text class="text-[#252525]">{{ child.actuallyLength }}</text>
              </text>
            </view>
          </wd-col>
          <wd-col :span="10" v-if="child.productUser">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                ç”Ÿäº§äºº:
                <text class="text-[#252525]">{{ child.productUser }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="24" v-if="child.actuallyWeight">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                å®žé™…重量(kg):
                <text class="text-[#252525]">{{ child.actuallyWeight }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="24" v-if="child.productTime">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                ç”Ÿäº§æ—¥æœŸ:
                <text class="text-[#252525]">{{ child.productTime }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <wd-row class="my-2">
          <wd-col :span="24" v-if="child.processHour">
            <view class="flex">
              <view class="icon_box">
                <wd-icon name="folder" color="#0D867F"></wd-icon>
              </view>
              <text class="text-[#646874] mx-2">
                åŠ å·¥æ—¶é—´(h):
                <text class="text-[#252525]">{{ child.processHour }}</text>
              </text>
            </view>
          </wd-col>
        </wd-row>
        <template #footer>
          <view class="flex gap-2">
            <wd-button plain size="small" @click="toAttachment(child)">附件</wd-button>
            <wd-button plain type="error" size="small" @click="handleDeleteSingle(child)">
              åˆ é™¤
            </wd-button>
          </view>
        </template>
      </wd-card>
    </view>
    <!-- æ–°å¢žæŠ¥å·¥å¼¹æ¡† -->
    <wd-popup v-model="addDialogVisible" position="bottom" custom-class="yl-popup">
      <view class="add-dialog">
        <view class="dialog-header">
          <text class="dialog-title">新增报工</text>
          <wd-icon name="close" class="close-icon" @click="closeAddDialog"></wd-icon>
        </view>
        <view class="dialog-content">
          <wd-cell-group>
            <wd-input
              v-model="newChildData.dishModel"
              label="盘型号"
              label-width="100px"
              placeholder="请输入盘型号"
            />
            <wd-input
              v-model="newChildData.actuallyLength"
              label="实际长度(m)"
              label-width="100px"
              type="number"
              placeholder="请输入实际长度"
            />
            <wd-input
              v-model="newChildData.actuallyWeight"
              label="实际重量(kg)"
              label-width="100px"
              type="number"
              placeholder="请输入实际重量"
            />
            <wd-cell title="是否接头" label-width="100px">
              <wd-radio-group v-model="newChildData.isJoint">
                <wd-radio :value="1">是</wd-radio>
                <wd-radio :value="0">否</wd-radio>
              </wd-radio-group>
            </wd-cell>
          </wd-cell-group>
        </view>
        <view class="dialog-footer">
          <wd-button plain @click="closeAddDialog">取消</wd-button>
          <wd-button type="primary" class="ml-2" @click="handleSaveNewChild">保存</wd-button>
        </view>
      </view>
    </wd-popup>
    <wd-toast />
  </view>
</template>
<script setup lang="ts">
import { ref, watch, nextTick } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { useToast, dayjs } from "wot-design-uni";
import WireApi from "@/api/product/wire";
import { getTeamId } from "@/utils/cache";
import { useUserStore } from "@/store/modules/user";
const toast = useToast();
const userStore = useUserStore();
const paramsId = ref();
const parentData = ref<any>(null);
const childList = ref<any[]>([]);
const model = ref();
const oneLength = ref();
const allChildDataList = ref<any[]>([]);
const wireDetail = ref<any>(null);
// æ–°å¢žå¼¹æ¡†ç›¸å…³
const addDialogVisible = ref(false);
const newChildData = ref({
  dishModel: "",
  actuallyLength: "",
  actuallyWeight: "",
  isJoint: 0,
  meterWeight: 0, // ç±³é‡
});
// èŽ·å–è¯¦æƒ…æ•°æ®
const getDetailData = async (id: string) => {
  try {
    const { data } = await WireApi.getWireDetailById({ id });
    wireDetail.value = data;
    model.value = data.model;
    oneLength.value = data.oneLength;
  } catch (error) {
    console.error("获取详情失败:", error);
  }
};
// åˆå§‹åŒ–数据
const getData = async () => {
  try {
    const { code, data } = await WireApi.getWireOutputTree({
      wireId: paramsId.value,
    });
    if (code == 200) {
      allChildDataList.value = [];
      const parentMap = new Map();
      data.forEach((item: any) => {
        const parentKey = `${item.poleNumber}-${item.poleModel}-${item.polePackageNumber}`;
        if (item.node && Array.isArray(item.node)) {
          item.node.forEach((child: any) => {
            const childData = {
              ...child,
              parentKey: parentKey,
              poleNumber: item.poleNumber,
              poleModel: item.poleModel,
              polePackageNumber: item.polePackageNumber,
              supplier: item.supplier,
            };
            allChildDataList.value.push(childData);
          });
        }
      });
      // åˆ·æ–°å½“前页面的子级列表
      const parentKey = `${parentData.value.poleNumber}-${parentData.value.poleModel}-${parentData.value.polePackageNumber}`;
      childList.value = allChildDataList.value
        .filter((child) => child.parentKey === parentKey)
        .map((child, index) => ({
          ...child,
          customIndex: index + 1,
          selected: false,
        }));
    }
  } catch (error) {
    console.error("获取数据失败:", error);
    toast.error("获取数据失败");
  }
};
// æ‰“开新增弹框
const handleAdd = () => {
  const lastChild = childList.value[childList.value.length - 1];
  // ä»Žè¯¦æƒ…数据中获取米重
  const meterWeight =
    Number(wireDetail.value?.meterWeight) ||
    Number(wireDetail.value?.weight) ||
    Number(wireDetail.value?.theoryWeight) ||
    0;
  // åˆå§‹åŒ–新数据,如果有最后一条数据,使用其值作为默认值
  newChildData.value = {
    dishModel: lastChild?.dishModel || "",
    actuallyLength: lastChild?.actuallyLength || "",
    actuallyWeight: lastChild?.actuallyWeight || "",
    isJoint: lastChild?.isJoint || 0,
    meterWeight: meterWeight,
  };
  addDialogVisible.value = true;
};
// ä¿å­˜æ–°å¢žçš„子级数据
const handleSaveNewChild = async () => {
  if (!newChildData.value.actuallyLength || !newChildData.value.actuallyWeight) {
    toast.error("请输入完整信息(实际长度和重量为必填项)");
    return;
  }
  const lastChild = childList.value[childList.value.length - 1];
  // ç”Ÿæˆæ–°çš„单丝盘号
  const newMonofilamentNumber = addMonofilamentNumber(lastChild?.monofilamentNumber, "拉丝");
  const newChild = {
    id: null,
    tempId: `temp_${Date.now()}`,
    parentKey: `${parentData.value.poleNumber}-${parentData.value.poleModel}-${parentData.value.polePackageNumber}`,
    teamId: getTeamId(),
    type: "拉丝",
    wireId: paramsId.value,
    poleNumber: parentData.value.poleNumber,
    poleModel: parentData.value.poleModel,
    supplier: parentData.value.supplier,
    polePackageNumber: parentData.value.polePackageNumber,
    dishModel: newChildData.value.dishModel || null,
    poleWeight: parentData.value.poleWeight,
    monofilamentNumber: newMonofilamentNumber,
    model: model.value || "",
    oneLength: oneLength.value || null,
    theoryWeight: lastChild?.theoryWeight || null,
    actuallyLength: newChildData.value.actuallyLength,
    actuallyWeight: newChildData.value.actuallyWeight,
    processHour: lastChild?.processHour || null,
    productUser: userStore.userInfo?.nickname || userStore.userInfo?.nickName || "",
    productTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
    customIndex: childList.value.length + 1,
    isJoint: newChildData.value.isJoint,
    selected: false,
  };
  // ä¸ºæ¯ä¸ªå­çº§æ•°æ®æ·»åŠ æ†é‡ä¿¡æ¯
  const childrenWithPoleWeight = [
    {
      ...newChild,
      poleWeight: parentData.value.poleWeight,
    },
  ];
  try {
    const { code, data } = await WireApi.addWireOutputList(childrenWithPoleWeight);
    if (code == 200) {
      if (data) {
        toast.warning(data);
      } else {
        toast.success("保存成功");
      }
      closeAddDialog();
      await getData();
    }
  } catch (error) {
    console.error("保存失败:", error);
    toast.error("保存失败");
  }
};
// å…³é—­æ–°å¢žå¼¹æ¡†
const closeAddDialog = () => {
  addDialogVisible.value = false;
  // é‡ç½®è¡¨å•数据
  newChildData.value = {
    dishModel: "",
    actuallyLength: "",
    actuallyWeight: "",
    isJoint: 0,
    meterWeight: 0,
  };
};
// ç”Ÿæˆæ–°çš„单丝盘号
const addMonofilamentNumber = (val: string, type: string) => {
  if (val) {
    if (type == "拉丝") {
      const arr = val.split("-");
      if (arr.length >= 3) {
        const prefix = `${arr[0]}-${arr[1]}`;
        let count = 0;
        allChildDataList.value.forEach((child) => {
          if (child.monofilamentNumber) {
            const childArr = child.monofilamentNumber.split("-");
            if (childArr.length >= 3) {
              const childPrefix = `${childArr[0]}-${childArr[1]}`;
              if (childPrefix === prefix) {
                count++;
              }
            }
          }
        });
        childList.value.forEach((child) => {
          if (child.monofilamentNumber && !child.id) {
            const childArr = child.monofilamentNumber.split("-");
            if (childArr.length >= 3) {
              const childPrefix = `${childArr[0]}-${childArr[1]}`;
              if (childPrefix === prefix) {
                count++;
              }
            }
          }
        });
        const a = count + 1;
        const paddedA = a < 10 ? `0${a}` : `${a}`;
        return `${prefix}-${paddedA}`;
      }
    }
  }
  return "";
};
// è·³è½¬åˆ°é™„件页面
const toAttachment = (item: any) => {
  uni.navigateTo({
    url: "/pages/production/wire/attachment/index",
    success: () => {
      // é¡µé¢è·³è½¬æˆåŠŸåŽå‘é€äº‹ä»¶ä¼ é€’æ•°æ®
      uni.$emit("detailData", item);
    },
    fail: (error) => {
      console.error("跳转附件页面失败:", error);
      toast.error("跳转失败");
    },
  });
};
// åˆ é™¤å•个子级数据
const handleDeleteSingle = async (child: any) => {
  try {
    const res = await uni.showModal({
      title: "提示",
      content: `确定删除这条数据吗?`,
    });
    if (res.confirm) {
      // å¦‚果是已保存的数据,调用删除接口
      if (child.id) {
        await WireApi.deleteWireOutput({ id: child.id });
        await getData();
        toast.success("删除成功");
      } else {
        // å¦‚果是未保存的数据,直接从列表中移除
        const index = childList.value.findIndex((row) => row.tempId === child.tempId);
        if (index !== -1) {
          childList.value.splice(index, 1);
          // é‡æ–°è®¡ç®—序号
          childList.value.forEach((item, idx) => {
            item.customIndex = idx + 1;
          });
          toast.success("删除成功");
        }
      }
    }
  } catch (error) {
    console.error("删除失败:", error);
    toast.error("删除失败");
  }
};
// è‡ªåŠ¨è®¡ç®—å®žé™…é‡é‡
const handleCalculateWeight = (row: any) => {
  // ä»Ž newChildData å¯¹è±¡ä¸­èŽ·å–ç±³é‡
  const meterWeight = Number(row.meterWeight) || 0;
  const actuallyLength = Number(row.actuallyLength);
  if (meterWeight > 0 && actuallyLength > 0) {
    const calculatedWeight = (meterWeight * actuallyLength) / 1000;
    row.actuallyWeight = Number(calculatedWeight.toFixed(3));
  }
  console.log("row", meterWeight, actuallyLength);
};
// ç›‘听实际长度变化,自动计算重量
watch(
  () => newChildData.value.actuallyLength,
  (newValue, oldValue) => {
    console.log("实际长度变化:", { newValue, oldValue, newChildData: newChildData.value });
    if (newValue && String(newValue).trim() !== "") {
      // ä½¿ç”¨ nextTick ç¡®ä¿ v-model å·²ç»æ›´æ–°
      nextTick(() => {
        handleCalculateWeight(newChildData.value);
      });
    }
  },
  { immediate: false, deep: true }
);
onLoad(async (options: any) => {
  paramsId.value = options.wireId;
  // ä»Žé¡µé¢å‚数中获取父级数据
  parentData.value = {
    id: options.parentId,
    poleNumber: options.poleNumber,
    poleModel: options.poleModel,
    polePackageNumber: options.polePackageNumber,
    poleWeight: options.poleWeight,
    supplier: options.supplier,
  };
  await getDetailData(options.wireId);
  await getData();
});
</script>
<style lang="scss" scoped>
.report-manage-page {
  min-height: 100vh;
  background: #f3f9f8;
  padding-bottom: 20px;
}
.card_bg {
  box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
  padding-bottom: 10px;
}
.icon_box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  background: #e7f4ec99;
  border-radius: 50%;
}
:deep() {
  .add_btn {
    border-radius: 4px;
  }
}
.add-dialog {
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 12px 12px 0 0;
}
.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #e6e6e6;
  position: sticky;
  top: 0;
  background: #fff;
  z-index: 10;
}
.dialog-title {
  font-size: 16px;
  color: #333;
  font-weight: 500;
}
.close-icon {
  font-size: 20px;
  color: #999;
  padding: 4px;
}
.dialog-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  padding: 16px;
  border-top: 1px solid #e6e6e6;
  gap: 8px;
}
.page-content {
  padding: 12px;
  margin-top: 12px;
}
</style>
src/pages/production/wire/report/wire.vue
@@ -1,41 +1,181 @@
<template>
  <view class="list">
    <z-paging ref="pagingRef" v-model="wireReportList" :fixed="false" @query="getWireReportList">
      <template #top>
        <CardTitle title="报工信息" :hideAction="true" :full="false" @action="addReport" />
    <CardTitle title="报工信息" :hideAction="false" :full="false">
      <template #action>
        <wd-button
          icon="file-add"
          :round="false"
          size="small"
          custom-class="add_btn"
          @click="handleAddParent"
        >
          æ–°å¢žæ†åŒ…
        </wd-button>
      </template>
      <wd-card
        v-for="(item, index) in wireReportList"
        :key="index"
        type="rectangle"
        custom-class="round"
      >
    </CardTitle>
    <!-- çˆ¶çº§åˆ—表(杆包) -->
    <view class="parent-list">
      <wd-card v-for="(item, index) in parentDataList" :key="item.id || index" class="card_bg">
        <template #title>
          <view class="flex justify-between">
            <view>
              <wd-icon name="user" color="#0D867F"></wd-icon>
              <text class="text-[#0D867F] ml-2 font-medium">生产人</text>
              <text class="text-[#333333] ml-2">{{ item.productUser }}</text>
          <view class="flex justify-between w-full">
            <view class="flex items-center">
              <text class="font-medium text-[#252525]">杆包信息</text>
              <view v-if="item.isAutoAdd == 1" class="text-xs text-blue-500 ml-2">自动添加</view>
            </view>
            <!-- <view class="text-[#A8A8A8]" @click="toEdit">编辑</view> -->
            <wd-button plain type="error" size="small" @click="handleDeleteRodBag(item)">
              åˆ é™¤
            </wd-button>
          </view>
        </template>
        <ProductionCard :data="cardAttr" :value="item" />
        <view>
          <wd-row class="my-2" v-if="item.poleNumber">
            <wd-col :span="24">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  é¢†ç”¨æ†å·:
                  <text class="text-[#252525]">{{ item.poleNumber }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2" v-if="item.poleModel">
            <wd-col :span="12">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  æ†åž‹å·:
                  <text class="text-[#252525]">{{ item.poleModel }}</text>
                </text>
              </view>
            </wd-col>
            <wd-col :span="12">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  æ†åŒ…号:
                  <text class="text-[#252525]">{{ item.polePackageNumber }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2">
            <wd-col :span="24" v-if="item.poleWeight">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  æ†é‡(kg):
                  <text class="text-[#252525]">{{ item.poleWeight }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2">
            <wd-col :span="24" v-if="item.supplier">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  ä¾›åº”商:
                  <text class="text-[#252525]">{{ item.supplier }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2" v-if="item.isConsumed !== undefined">
            <wd-col :span="24">
              <view class="flex items-center">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">消耗情况:</text>
                <wd-switch
                  v-model="item.isConsumed"
                  :disabled="false"
                  active-text="已耗完"
                  inactive-text="还剩余"
                  :active-value="1"
                  :inactive-value="0"
                  size="20"
                  @change="handleConsumedChange(item, $event)"
                />
              </view>
            </wd-col>
          </wd-row>
        </view>
        <template #footer>
          <wd-button size="small" plain style="margin-right: 10px" @click="toAttachment(item)">
            é™„ä»¶
          </wd-button>
          <wd-button size="small" plain @click="toCheck(item.id)">自检</wd-button>
          <view class="flex justify-start">
            <wd-button plain size="small" type="primary" @click="openChildDialog(item)">
              æŠ¥å·¥ç®¡ç†
            </wd-button>
          </view>
        </template>
      </wd-card>
    </z-paging>
    <wd-popup v-model="dialog.visible" position="bottom" custom-class="yl-popup">
      <view class="action px-3">
        <wd-button type="text" @click="cancel">取消</wd-button>
        <wd-button type="text" @click="submit">确定</wd-button>
    </view>
    <!-- æ–°å¢žæ†åŒ…弹框 -->
    <wd-popup v-model="parentDialogVisible" position="bottom" custom-class="yl-popup">
      <view class="parent-dialog">
        <view class="dialog-header">
          <text class="dialog-title">新增杆包</text>
          <wd-icon name="close" class="close-icon" @click="closeParentDialog"></wd-icon>
        </view>
        <view class="dialog-content">
          <wd-cell-group>
            <wd-input
              v-model="newParentData.poleNumber"
              label="领用杆号"
              label-width="100px"
              placeholder="请输入领用杆号"
            />
            <wd-input
              v-model="newParentData.poleModel"
              label="杆型号"
              label-width="100px"
              placeholder="请输入杆型号"
            />
            <wd-input
              v-model="newParentData.polePackageNumber"
              label="杆包号"
              label-width="100px"
              placeholder="请输入杆包号"
            />
            <wd-input
              v-model="newParentData.poleWeight"
              label="杆重(kg)"
              label-width="100px"
              type="number"
              placeholder="请输入杆重"
            />
            <wd-picker
              v-model="newParentData.supplier"
              label="供应商"
              label-width="100px"
              :columns="supplierOptions"
              placeholder="请选择供应商"
            />
          </wd-cell-group>
        </view>
        <view class="dialog-footer">
          <wd-button plain @click="closeParentDialog">取消</wd-button>
          <wd-button type="primary" class="ml-2" @click="handleSaveNewParent">保存</wd-button>
        </view>
      </view>
      <WireForm ref="wireFormRef" />
    </wd-popup>
    <!-- Draw组件(领用自检) -->
    <wd-popup v-model="drawFormRef.visible" position="bottom" custom-class="yl-popup">
      <Draw
        :wire-id="drawData.wireId"
@@ -43,172 +183,324 @@
        @close="handleDrawClose"
      />
    </wd-popup>
    <wd-toast />
  </view>
</template>
<script setup lang="ts">
import CardTitle from "@/components/card-title/index.vue";
import WireForm from "./wireForm.vue";
import { useToast } from "wot-design-uni";
import ProductionCard from "../../components/ProductionCard.vue";
import zPaging from "@/components/z-paging/z-paging.vue";
import { useToast, dayjs } from "wot-design-uni";
import { onLoad } from "@dcloudio/uni-app";
import { onMounted, nextTick } from "vue";
import WireApi from "@/api/product/wire";
import ManageApi from "@/api/product/manage";
import Draw from "./rawMaterial.vue";
import { getTeamId } from "@/utils/cache";
import { useUserStore } from "@/store/modules/user";
import WireDetailApi from "@/api/product/wire";
const pagingRef = ref();
const wireFormRef = ref();
const paramsId = ref();
const toast = useToast();
const dialog = reactive({
  visible: false,
const userStore = useUserStore();
const paramsId = ref();
const model = ref();
const oneLength = ref();
// çˆ¶çº§æ•°æ®åˆ—表
const parentDataList = ref<any[]>([]);
// å­çº§æ•°æ®åˆ—表(所有子级数据的扁平化列表)
const childDataList = ref<any[]>([]);
// ä¾›åº”商选项
const supplierOptions = ref<any[]>([]);
// çˆ¶çº§å¼¹æ¡†ç›¸å…³
const parentDialogVisible = ref(false);
const newParentData = ref({
  poleNumber: "",
  poleModel: "",
  polePackageNumber: "",
  poleWeight: undefined as number | undefined,
  supplier: "",
  isConsumed: 1,
});
// Draw组件相关
const drawFormRef = reactive({
  visible: false,
});
// å¤„理draw组件关闭事件
const handleDrawClose = () => {
  // ç¡®ä¿å¼¹çª—被正确关闭
  drawFormRef.visible = false;
};
const drawData = ref({
  wireId: "",
  poleNumber: "",
});
const showDrawPopup = async () => {
  console.log("进入该方法!");
// èŽ·å–è¯¦æƒ…æ•°æ®
const getDetailData = async (id: string) => {
  try {
    const { data } = await ManageApi.queryWireRawMaterialInspect({
      wireId: paramsId.value,
      poleNumber: drawData.value.poleNumber,
    });
    console.log("data", data);
    // é€‚配不同的数据结构返回格式
    if (data == null) {
      drawData.value = {
        wireId: paramsId.value,
        poleNumber: drawData.value.poleNumber,
      };
      // æ˜¾ç¤ºDraw弹窗
      drawFormRef.visible = true;
      toast.success("请填写领用信息!");
    } else {
      // toast.error("已存在领用信息,无需填报!");
    const { data } = await WireDetailApi.getWireDetailById({ id });
    model.value = data.model;
    oneLength.value = data.oneLength;
  } catch (error) {
    console.error("获取详情失败:", error);
  }
};
// åŠ è½½ä¾›åº”å•†å­—å…¸
const loadSupplierDict = async () => {
  try {
    const res = await ManageApi.dictAPI("al_supplier");
    if (res.data && Array.isArray(res.data)) {
      supplierOptions.value = res.data.map((item: any) => ({
        label: item.dictLabel || "",
        value: item.dictValue || item.value || "",
      }));
    }
  } catch (error) {
    console.error("获取领用信息失败:", error);
    toast.error("获取信息失败,请重试");
    console.error("加载供应商字典失败:", error);
  }
};
const cardAttr = ref<any[]>([
  {
    label: "领用杆号",
    prop: "poleNumber",
    span: 24,
  },
  {
    label: "单丝盘号",
    prop: "monofilamentNumber",
    span: 24,
  },
  {
    label: "杆型号",
    prop: "poleModel",
  },
  {
    label: "杆包号",
    prop: "polePackageNumber",
  },
  {
    label: "杆重(kg)",
    prop: "poleWeight",
  },
  {
    label: "规格型号",
    prop: "model",
  },
  {
    label: "盘型号",
    prop: "dishModel",
  },
  {
    label: "盘长(m)",
    prop: "oneLength",
  },
  {
    label: "实际长度",
    prop: "actuallyLength",
  },
  {
    label: "实际重量(kg)",
    prop: "actuallyWeight",
  },
]);
// åˆå§‹åŒ–数据
const getData = async () => {
  try {
    const { code, data } = await WireApi.getWireOutputTree({
      wireId: paramsId.value,
    });
const wireReportList = ref<any[]>([]);
    if (code == 200) {
      parentDataList.value = [];
      childDataList.value = [];
// const toEdit = () => {
//   uni.navigateTo({
//     url: "/pages/production/wire/report/wireEdit",
//   });
// };
      const parentMap = new Map();
const addReport = () => {
  dialog.visible = true;
};
      data.forEach((item: any) => {
        const parentKey = `${item.poleNumber}-${item.poleModel}-${item.polePackageNumber}`;
const submit = async () => {
  const result = await wireFormRef.value.submit();
  dialog.visible = !result.success;
  // è®¾ç½®poleNumber到drawData中
  if (result.success) {
    drawData.value.poleNumber = result.poleNumber;
    showDrawPopup();
        if (!parentMap.has(parentKey)) {
          const parentData = {
            id: parentKey,
            poleNumber: item.poleNumber,
            poleModel: item.poleModel,
            polePackageNumber: item.polePackageNumber,
            dishModel: item.dishModel,
            poleWeight: item.poleWeight,
            supplier: item.supplier,
            isConsumed: item.isConsumed === true || item.isConsumed === 1 ? 1 : 0,
            treeId: item.id,
            isAutoAdd: item.isAutoAdd,
          };
          parentMap.set(parentKey, parentData);
          parentDataList.value.push(parentData);
        }
        if (item.node && Array.isArray(item.node)) {
          item.node.forEach((child: any) => {
            const childData = {
              ...child,
              parentKey: parentKey,
              poleNumber: item.poleNumber,
              poleModel: item.poleModel,
              polePackageNumber: item.polePackageNumber,
              supplier: item.supplier,
              selected: false,
            };
            childDataList.value.push(childData);
          });
        }
      });
    }
  } catch (error) {
    console.error("获取数据失败:", error);
    toast.error("获取数据失败");
  }
  pagingRef.value.reload();
};
const cancel = () => {
  toast.show("取消");
  dialog.visible = false;
// æ–°å¢žçˆ¶çº§æ•°æ® - æ‰“开弹框
const handleAddParent = () => {
  const lastParent = parentDataList.value[0];
  // åˆå§‹åŒ–新数据,如果有最后一条数据,使用其值作为默认值
  newParentData.value = {
    poleNumber: lastParent?.poleNumber || "",
    poleModel: lastParent?.poleModel || "",
    polePackageNumber: lastParent?.polePackageNumber || "",
    poleWeight: lastParent?.poleWeight || null,
    supplier: lastParent?.supplier || "",
    isConsumed: 1,
  };
  parentDialogVisible.value = true;
};
const toAttachment = (item: any) => {
// ä¿å­˜æ–°çˆ¶çº§æ•°æ®
const handleSaveNewParent = async () => {
  if (
    !newParentData.value.poleNumber ||
    !newParentData.value.poleModel ||
    !newParentData.value.polePackageNumber ||
    !newParentData.value.poleWeight
  ) {
    toast.error("请填写完整的父级信息(领用杆号、杆型号、杆包号、杆重为必填项)");
    return;
  }
  try {
    const { code } = await WireApi.addRodBagTree({
      wireId: paramsId.value,
      poleNumber: newParentData.value.poleNumber,
      poleModel: newParentData.value.poleModel,
      polePackageNumber: newParentData.value.polePackageNumber,
      supplier: newParentData.value.supplier,
      poleWeight: newParentData.value.poleWeight,
      isConsumed: newParentData.value.isConsumed,
    });
    if (code == 200) {
      toast.success("保存成功");
      closeParentDialog();
      await getData();
    }
  } catch (error) {
    console.error("保存失败:", error);
    toast.error("保存失败");
  }
};
// å…³é—­çˆ¶çº§å¼¹æ¡†
const closeParentDialog = () => {
  parentDialogVisible.value = false;
  // é‡ç½®è¡¨å•数据
  newParentData.value = {
    poleNumber: "",
    poleModel: "",
    polePackageNumber: "",
    poleWeight: undefined,
    supplier: "",
    isConsumed: 1,
  };
};
// åˆ é™¤æ†åŒ…
const handleDeleteRodBag = async (row: any) => {
  try {
    const res = await uni.showModal({
      title: "提示",
      content: `确定删除杆包:${row.poleNumber} - ${row.poleModel} - ${row.polePackageNumber} å—?`,
    });
    if (res.confirm) {
      const { code } = await WireApi.deleteRodBagTree({
        wireId: paramsId.value,
        poleModel: row.poleModel,
        poleNumber: row.poleNumber,
        polePackageNumber: row.polePackageNumber,
      });
      if (code === 200) {
        toast.success("删除成功");
        await getData();
      } else {
        toast.error("删除失败");
      }
    }
  } catch (error) {
    console.error("删除杆包失败:", error);
    toast.error("删除失败");
  }
};
// æ¶ˆè€—情况变化
const handleConsumedChange = async (row: any, value: any) => {
  if (row.treeId) {
    // ä¿å­˜æ—§å€¼ï¼Œç”¨äºŽå¤±è´¥æ—¶æ¢å¤
    const oldValue = row.isConsumed;
    // å¤„理 value,可能是数字、对象或其他格式
    let isConsumedValue: number;
    if (typeof value === "object" && value !== null && "value" in value) {
      // å¦‚果是对象格式 {value: 1}
      isConsumedValue = value.value;
    } else if (typeof value === "number") {
      // å¦‚果是数字
      isConsumedValue = value;
    } else if (typeof value === "boolean") {
      // å¦‚果是布尔值
      isConsumedValue = value ? 1 : 0;
    } else {
      // å…¶ä»–情况,尝试转换
      isConsumedValue = value === 1 || value === "1" || value === true ? 1 : 0;
    }
    // å…ˆæ›´æ–° UI
    row.isConsumed = isConsumedValue;
    try {
      const { code } = await WireApi.updateRodBagTree({
        treeId: row.treeId,
        isConsumed: isConsumedValue,
      });
      if (code != 200) {
        toast.error("更新失败");
        // æ›´æ–°å¤±è´¥æ—¶æ¢å¤åŽŸå€¼
        row.isConsumed = oldValue;
      }
    } catch (error) {
      console.error("更新消耗情况失败:", error);
      toast.error("更新失败");
      // æ›´æ–°å¤±è´¥æ—¶æ¢å¤åŽŸå€¼
      row.isConsumed = oldValue;
    }
  }
};
// æ‰“开子级页面
const openChildDialog = async (parentRow: any) => {
  // æ£€æŸ¥æ˜¯å¦æœ‰é¢†ç”¨ä¿¡æ¯
  try {
    const { code, data } = await ManageApi.queryWireRawMaterialInspect({
      wireId: paramsId.value,
      poleNumber: parentRow.poleNumber,
    });
    if (code == 200) {
      if (data == null) {
        // æ˜¾ç¤ºDraw组件
        drawData.value = {
          wireId: paramsId.value,
          poleNumber: parentRow.poleNumber,
        };
        drawFormRef.visible = true;
        toast.warning("请先填写领用信息");
        return;
      }
    }
  } catch (error) {
    console.error("检查领用信息失败:", error);
  }
  // è·³è½¬åˆ°æŠ¥å·¥ç®¡ç†é¡µé¢
  uni.navigateTo({
    url: "/pages/production/wire/attachment/index",
    success: () => {
      // é¡µé¢è·³è½¬æˆåŠŸåŽå‘é€äº‹ä»¶ä¼ é€’æ•°æ®
      uni.$emit("detailData", item);
    },
    url: `/pages/production/wire/report/reportManage?wireId=${paramsId.value}&parentId=${parentRow.id}&poleNumber=${parentRow.poleNumber}&poleModel=${parentRow.poleModel}&polePackageNumber=${parentRow.polePackageNumber}&poleWeight=${parentRow.poleWeight}&supplier=${parentRow.supplier || ""}`,
  });
};
const toCheck = (id: number) => {
  uni.navigateTo({
    url: `/pages/production/wire/selfInspect/index?id=${id}`,
  });
// å¤„理draw组件关闭事件
const handleDrawClose = () => {
  drawFormRef.visible = false;
};
// èŽ·å–æ‹‰ä¸æŠ¥å·¥åˆ—è¡¨
const getWireReportList = async () => {
  const { data } = await ManageApi.getReportList({
    wireId: paramsId.value,
    type: "拉丝",
  });
  pagingRef.value.complete(data);
};
onLoad((options: any) => {
onLoad(async (options: any) => {
  paramsId.value = options.id;
  await getDetailData(options.id);
  await loadSupplierDict();
  await getData();
});
</script>
<style lang="scss" scoped>
.list {
  height: calc(100vh - 30px);
  min-height: calc(100vh - 30px);
  padding: 12px;
  background: #f3f9f8;
@@ -219,8 +511,49 @@
  }
}
.action {
.parent-list {
  margin-top: 12px;
}
.card_bg {
  box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
  padding-bottom: 10px;
  margin-bottom: 12px;
}
.icon_box {
  display: flex;
  justify-content: space-between;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  background: #e7f4ec99;
  border-radius: 50%;
}
.edit-form {
  padding: 12px 0;
}
.parent-dialog {
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 12px 12px 0 0;
}
.dialog-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  padding: 16px;
  border-top: 1px solid #e6e6e6;
  gap: 8px;
}
</style>