zhangwencui
2026-04-28 1a1de1517a88afe8c9f8981ebf677de406f8960b
基础参数模块开发
已添加3个文件
已修改2个文件
699 ■■■■■ 文件已修改
src/api/basicData/parameterMaintenance.js 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages.json 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/productionDesign/basicParameters/edit.vue 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/productionDesign/basicParameters/index.vue 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/works.vue 114 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicData/parameterMaintenance.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
import request from "@/utils/request";
// æŸ¥è¯¢åŸºç¡€å‚数列表
export function getBaseParamList(query) {
  return request({
    url: "/technologyParam/list",
    method: "get",
    params: query,
  });
}
// æ–°å¢žåŸºç¡€å‚æ•°
export function addBaseParam(data) {
  return request({
    url: "/technologyParam/add",
    method: "post",
    data: data,
  });
}
// ç¼–辑基础参数
export function editBaseParam(data) {
  return request({
    url: "/technologyParam/edit",
    method: "put",
    data: data,
  });
}
// åˆ é™¤åŸºç¡€å‚æ•°
export function removeBaseParam(id) {
  return request({
    url: "/technologyParam/remove/" + id,
    method: "delete",
  });
}
src/pages.json
@@ -367,6 +367,20 @@
      }
    },
    {
      "path": "pages/productionDesign/basicParameters/index",
      "style": {
        "navigationBarTitleText": "基础参数",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/productionDesign/basicParameters/edit",
      "style": {
        "navigationBarTitleText": "参数详情",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/cooperativeOffice/collaborativeApproval/index1",
      "style": {
        "navigationBarTitleText": "公出管理",
src/pages/productionDesign/basicParameters/edit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,290 @@
<template>
  <view class="basic-parameters-edit">
    <PageHeader :title="pageTitle"
                @back="goBack" />
    <up-form ref="formRef"
             :model="form"
             :rules="rules"
             :errorType="['none']"
             label-width="110">
      <up-form-item label="参数编码"
                    prop="paramCode">
        <up-input v-model="form.paramCode"
                  disabled
                  placeholder="自动生成" />
      </up-form-item>
      <up-form-item label="参数名称"
                    prop="paramName"
                    required>
        <up-input v-model="form.paramName"
                  placeholder="请输入参数名称"
                  clearable />
      </up-form-item>
      <up-form-item label="参数类型"
                    prop="paramType"
                    required>
        <up-input v-model="paramTypeText"
                  placeholder="请选择参数类型"
                  readonly
                  @click="showParamTypeSheet = true" />
        <template #right>
          <up-icon name="arrow-right"
                   @click="showParamTypeSheet = true"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="单位"
                    prop="unit"
                    :required="form.paramType === 1">
        <up-input v-model="form.unit"
                  placeholder="请输入单位"
                  clearable />
      </up-form-item>
      <up-form-item label="取值格式"
                    v-if="form.paramType === 1 || form.paramType === 2"
                    prop="paramFormat">
        <up-input v-model="form.paramFormat"
                  placeholder="请输入取值格式"
                  clearable />
      </up-form-item>
      <up-form-item label="下拉字典"
                    v-else-if="form.paramType === 3"
                    prop="paramFormat">
        <up-input v-model="dictTypeText"
                  placeholder="请选择下拉字典"
                  readonly
                  @click="showDictTypeSheet = true" />
        <template #right>
          <up-icon name="arrow-right"
                   @click="showDictTypeSheet = true"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="时间格式"
                    v-else-if="form.paramType === 4"
                    prop="paramFormat">
        <up-input v-model="form.paramFormat"
                  placeholder="请选择时间格式"
                  readonly
                  @click="showTimeFormatSheet = true" />
        <template #right>
          <up-icon name="arrow-right"
                   @click="showTimeFormatSheet = true"></up-icon>
        </template>
      </up-form-item>
      <up-form-item label="是否必填"
                    prop="isRequired">
        <view style="display: flex; justify-content: flex-end; width: 100%;">
          <up-switch v-model="form.isRequired"
                     :activeValue="1"
                     :inactiveValue="0" />
        </view>
      </up-form-item>
      <up-form-item label="备注"
                    prop="remark">
        <up-textarea v-model="form.remark"
                     placeholder="请输入备注"
                     autoHeight />
      </up-form-item>
    </up-form>
    <FooterButtons :loading="loading"
                   :confirmText="paramId ? '保存' : '新增'"
                   @cancel="goBack"
                   @confirm="handleSubmit" />
    <!-- å‚数类型选择 -->
    <up-action-sheet :show="showParamTypeSheet"
                     title="选择参数类型"
                     :actions="paramTypeActions"
                     @select="onSelectParamType"
                     @close="showParamTypeSheet = false" />
    <!-- ä¸‹æ‹‰å­—典选择 -->
    <up-action-sheet :show="showDictTypeSheet"
                     title="选择下拉字典"
                     :actions="dictTypeActions"
                     @select="onSelectDictType"
                     @close="showDictTypeSheet = false" />
    <!-- æ—¶é—´æ ¼å¼é€‰æ‹© -->
    <up-action-sheet :show="showTimeFormatSheet"
                     title="选择时间格式"
                     :actions="timeFormatActions"
                     @select="onSelectTimeFormat"
                     @close="showTimeFormatSheet = false" />
  </view>
</template>
<script setup>
  import { computed, nextTick, onMounted, ref } from "vue";
  import { onLoad, onReady } from "@dcloudio/uni-app";
  import FooterButtons from "@/components/FooterButtons.vue";
  import PageHeader from "@/components/PageHeader.vue";
  import {
    addBaseParam,
    editBaseParam,
  } from "@/api/basicData/parameterMaintenance";
  import { listType } from "@/api/system/dict/type";
  const formRef = ref();
  const loading = ref(false);
  const paramId = ref("");
  const showParamTypeSheet = ref(false);
  const showDictTypeSheet = ref(false);
  const showTimeFormatSheet = ref(false);
  const dictTypes = ref([]);
  const form = ref({
    id: null,
    paramCode: "",
    paramName: "",
    paramType: "",
    unit: "",
    remark: "",
    isRequired: 0,
    paramFormat: "",
  });
  const rules = {
    paramName: [{ required: true, message: "请输入参数名称" }],
    paramType: [{ required: true, message: "请选择参数类型" }],
    unit: [
      {
        validator: (rule, value, callback) => {
          if (form.value.paramType === 1 && !value) {
            callback(new Error("数值类型必须填写单位"));
          } else {
            callback();
          }
        },
      },
    ],
  };
  const paramTypeActions = [
    { name: "数值格式", value: 1 },
    { name: "文本格式", value: 2 },
    { name: "下拉选项", value: 3 },
    { name: "时间格式", value: 4 },
  ];
  const timeFormatActions = [
    { name: "YYYY-MM-DD", value: "YYYY-MM-DD" },
    { name: "YYYY-MM-DD HH:mm:ss", value: "YYYY-MM-DD HH:mm:ss" },
  ];
  const dictTypeActions = computed(() => {
    return dictTypes.value.map(item => ({
      name: item.dictName,
      value: item.dictType,
    }));
  });
  const pageTitle = computed(() => (paramId.value ? "编辑参数" : "新增参数"));
  const paramTypeText = computed(() => {
    const action = paramTypeActions.find(
      item => item.value === form.value.paramType
    );
    return action ? action.name : "";
  });
  const dictTypeText = computed(() => {
    const action = dictTypes.value.find(
      item => item.dictType === form.value.paramFormat
    );
    return action ? action.dictName : form.value.paramFormat || "";
  });
  const goBack = () => {
    uni.navigateBack();
  };
  const getDictTypes = () => {
    listType({ pageNum: 1, pageSize: 1000 }).then(res => {
      dictTypes.value = res.rows || [];
    });
  };
  const onSelectParamType = action => {
    form.value.paramType = action.value;
    if (action.value === 1) {
      form.value.paramFormat = "#.00000";
    } else if (action.value === 4) {
      form.value.paramFormat = "YYYY-MM-DD HH:mm:ss";
    } else {
      form.value.paramFormat = "";
    }
    showParamTypeSheet.value = false;
  };
  const onSelectDictType = action => {
    form.value.paramFormat = action.value;
    showDictTypeSheet.value = false;
  };
  const onSelectTimeFormat = action => {
    form.value.paramFormat = action.value;
    showTimeFormatSheet.value = false;
  };
  const handleSubmit = () => {
    formRef.value
      .validate()
      .then(() => {
        if (form.value.paramType === 3 && !form.value.paramFormat) {
          uni.showToast({ title: "请选择下拉字典", icon: "none" });
          return;
        }
        loading.value = true;
        const action = paramId.value ? editBaseParam : addBaseParam;
        action({ ...form.value, id: paramId.value || undefined })
          .then(() => {
            uni.showToast({ title: "保存成功", icon: "success" });
            setTimeout(() => {
              goBack();
            }, 1500);
          })
          .catch(() => {
            uni.showToast({ title: "保存失败", icon: "none" });
          })
          .finally(() => {
            loading.value = false;
          });
      })
      .catch(errors => {
        if (errors && errors.length > 0) {
          uni.showToast({
            title: errors[0].message,
            icon: "none",
          });
        }
      });
  };
  onReady(() => {
    if (formRef.value) {
      formRef.value.setRules(rules);
    }
  });
  onMounted(() => {
    getDictTypes();
  });
  onLoad(options => {
    if (options?.item) {
      const item = JSON.parse(decodeURIComponent(options.item));
      paramId.value = item.id;
      if (item.paramType) {
        item.paramType = Number(item.paramType);
      }
      Object.assign(form.value, item);
    }
  });
</script>
<style scoped lang="scss">
  @import "@/static/scss/form-common.scss";
  .basic-parameters-edit {
    min-height: 100vh;
    background: #f5f5f5;
  }
</style>
src/pages/productionDesign/basicParameters/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,245 @@
<template>
  <view class="sales-account">
    <PageHeader title="基础参数"
                @back="goBack" />
    <view class="search-section">
      <view class="search-bar">
        <view class="search-input">
          <up-input class="search-text"
                    v-model="paramName"
                    placeholder="请输入参数名称"
                    clearable
                    @change="handleSearch" />
        </view>
        <view class="filter-button"
              @click="handleSearch">
          <up-icon name="search"
                   size="24"
                   color="#999999"></up-icon>
        </view>
      </view>
    </view>
    <view v-if="list.length > 0"
          class="ledger-list">
      <view v-for="item in list"
            :key="item.id"
            class="ledger-item">
        <view class="item-header">
          <view class="item-left">
            <view class="document-icon">
              <up-icon name="setting-fill"
                       size="16"
                       color="#ffffff"></up-icon>
            </view>
            <text class="item-id">{{ item.paramName || "-" }}</text>
          </view>
          <text class="item-index">{{ item.paramCode || "-" }}</text>
        </view>
        <up-divider></up-divider>
        <view class="item-details">
          <view class="detail-row">
            <text class="detail-label">参数类型</text>
            <up-tag :text="getParamTypeLabel(item.paramType)"
                    :type="getParamTypeTag(item.paramType)"
                    size="mini" />
          </view>
          <view class="detail-row">
            <text class="detail-label">单位</text>
            <text class="detail-value">{{ item.unit || "-" }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">是否必填</text>
            <up-tag :text="item.isRequired === 1 ? '是' : '否'"
                    :type="item.isRequired === 1 ? 'success' : 'info'"
                    size="mini" />
          </view>
          <view class="detail-row">
            <text class="detail-label">取值格式</text>
            <text class="detail-value">{{ item.paramFormat || "-" }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">备注</text>
            <text class="detail-value">{{ item.remark || "-" }}</text>
          </view>
        </view>
        <view class="action-buttons">
          <up-button class="action-btn"
                     size="small"
                     type="primary"
                     @click="goEdit(item)">编辑</up-button>
          <up-button class="action-btn"
                     size="small"
                     type="error"
                     @click="handleDelete(item)">删除</up-button>
        </view>
      </view>
      <up-loadmore :status="page.status" />
    </view>
    <view v-else
          class="no-data">
      <text>暂无基础参数数据</text>
    </view>
    <view class="fab-button"
          @click="goAdd">
      <up-icon name="plus"
               size="28"
               color="#ffffff"></up-icon>
    </view>
  </view>
</template>
<script setup>
  import { reactive, ref } from "vue";
  import { onReachBottom, onShow } from "@dcloudio/uni-app";
  import {
    getBaseParamList,
    removeBaseParam,
  } from "@/api/basicData/parameterMaintenance";
  const paramName = ref("");
  const list = ref([]);
  const page = reactive({
    current: 1,
    size: 100,
    total: 0,
    status: "loadmore", // loadmore, loading, nomore
  });
  const goBack = () => {
    uni.navigateBack();
  };
  const getParamTypeLabel = type => {
    const map = {
      1: "数值格式",
      2: "文本格式",
      3: "下拉选项",
      4: "时间格式",
    };
    return map[type] || type;
  };
  const getParamTypeTag = type => {
    const map = {
      1: "primary",
      2: "info",
      3: "warning",
      4: "success",
    };
    return map[type] || "info";
  };
  const goAdd = () => {
    uni.navigateTo({ url: "/pages/productionDesign/basicParameters/edit" });
  };
  const goEdit = item => {
    uni.navigateTo({
      url: `/pages/productionDesign/basicParameters/edit?item=${encodeURIComponent(
        JSON.stringify(item)
      )}`,
    });
  };
  const handleDelete = item => {
    uni.showModal({
      title: "提示",
      content: "确定要删除该参数吗?",
      success: res => {
        if (res.confirm) {
          removeBaseParam(item.id).then(() => {
            uni.showToast({ title: "删除成功" });
            handleSearch();
          });
        }
      },
    });
  };
  const handleSearch = () => {
    page.current = 1;
    page.status = "loadmore";
    list.value = [];
    getList();
  };
  const getList = () => {
    if (page.status === "loading" || page.status === "nomore") return;
    page.status = "loading";
    getBaseParamList({
      current: page.current,
      size: page.size,
      paramName: paramName.value,
    })
      .then(res => {
        const records = res?.data?.records || res?.records || [];
        const total = res?.data?.total || res?.total || 0;
        if (page.current === 1) {
          list.value = records;
        } else {
          list.value = [...list.value, ...records];
        }
        page.total = total;
        if (list.value.length >= total) {
          page.status = "nomore";
        } else {
          page.status = "loadmore";
          page.current++;
        }
      })
      .catch(() => {
        uni.showToast({ title: "查询失败", icon: "error" });
        page.status = "loadmore";
      });
  };
  onReachBottom(() => {
    getList();
  });
  onShow(() => {
    handleSearch();
  });
</script>
<style scoped lang="scss">
  @import "@/styles/procurement-common.scss";
  .no-data {
    padding-top: 100rpx;
    text-align: center;
    color: #999;
    font-size: 28rpx;
  }
  .action-buttons {
    display: flex;
    justify-content: flex-end;
    gap: 20rpx;
    padding-bottom: 30rpx;
  }
  .action-btn {
    width: 140rpx;
    margin: 0 !important;
  }
  .fab-button {
    position: fixed;
    right: 40rpx;
    bottom: 60rpx;
    width: 100rpx;
    height: 100rpx;
    background: #2979ff;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4rpx 12rpx rgba(41, 121, 255, 0.4);
    z-index: 100;
  }
</style>
src/pages/works.vue
@@ -15,7 +15,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -37,7 +38,31 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
        </up-grid>
      </view>
    </view>
    <!-- å·¥è‰ºè®¾è®¡ -->
    <view class="common-module design-module"
          v-if="hasDesignItems">
      <view class="module-header">
        <view class="module-title-container">
          <text class="module-title">工艺设计</text>
        </view>
      </view>
      <view class="module-content">
        <up-grid :border="false"
                 col="4">
          <up-grid-item v-for="(item, index) in designItems"
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -59,7 +84,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -81,7 +107,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -103,7 +130,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -125,7 +153,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -147,7 +176,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -169,7 +199,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -191,7 +222,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -213,7 +245,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -235,7 +268,8 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
@@ -257,14 +291,14 @@
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container">
              <image :src="item.icon" class="item-icon"></image>
              <image :src="item.icon"
                     class="item-icon"></image>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
        </up-grid>
      </view>
    </view>
    <DownloadProgressMask />
  </view>
</template>
@@ -299,6 +333,25 @@
      currentStatus.value = statusList[statusIndex];
    }, 3000);
  };
  // å·¥è‰ºè®¾è®¡åŠŸèƒ½æ•°æ®
  const designItems = reactive([
    {
      icon: "/static/images/icon/xiaoshoubaojia.svg",
      label: "基础参数",
    },
    {
      icon: "/static/images/icon/xiaoshoubaojia.svg",
      label: "工序管理",
    },
    {
      icon: "/static/images/icon/xiaoshoubaojia.svg",
      label: "BOM",
    },
    {
      icon: "/static/images/icon/xiaoshoubaojia.svg",
      label: "工艺路线",
    },
  ]);
  // è¥é”€ç®¡ç†åŠŸèƒ½æ•°æ®
  const marketingItems = reactive([
@@ -397,8 +450,8 @@
    {
      icon: "/static/images/icon/hetongguanli.svg",
      label: "归还登记",
    }
  ])
    },
  ]);
  // å”®åŽæœåŠ¡åŠŸèƒ½æ•°æ®
  const afterSalesServiceItems = reactive([
@@ -938,6 +991,11 @@
          url: "/pages/fileManagement/return/index",
        });
        break;
      case "基础参数":
        uni.navigateTo({
          url: "/pages/productionDesign/basicParameters/index",
        });
        break;
      default:
        uni.showToast({
          title: `点击了${item.label}`,
@@ -1125,10 +1183,13 @@
    // å®šä¹‰èœå•配置映射
    const menuMapping = {
      collaboration: { target: collaborationItems, specialMapping: { "规章制度": "规章制度管理" } },
      purchase: { specialMapping: { "供应商档案": "供应商管理" } },
      collaboration: {
        target: collaborationItems,
        specialMapping: { è§„章制度: "规章制度管理" },
      },
      purchase: { specialMapping: { ä¾›åº”商档案: "供应商管理" } },
    };
    console.log(allowedMenuTitles)
    console.log(allowedMenuTitles);
    // é€šç”¨è¿‡æ»¤å‡½æ•°
    const filterArray = (targetArray, specialMapping) => {
      const filtered = targetArray.filter(item => {
@@ -1157,17 +1218,26 @@
  // æ£€æŸ¥æ¨¡å—是否有菜单项需要显示
  const hasMarketingItems = computed(() => marketingItems.length > 0);
  const hasDesignItems = computed(() => designItems.length > 0);
  const hasPurchaseItems = computed(() => purchaseItems.length > 0);
  const hasFinanceManagementItems = computed(() => financeManagementItems.length > 0);
  const hasAfterSalesServiceItems = computed(() => afterSalesServiceItems.length > 0);
  const hasFinanceManagementItems = computed(
    () => financeManagementItems.length > 0
  );
  const hasAfterSalesServiceItems = computed(
    () => afterSalesServiceItems.length > 0
  );
  const hasCollaborationItems = computed(() => collaborationItems.length > 0);
  const hasSafetyItems = computed(() => safetyItems.length > 0);
  const hasQualityItems = computed(() => qualityItems.length > 0);
  const hasHumanResourcesItems = computed(() => humanResourcesItems.length > 0);
  const hasWarehouseLogisticsItems = computed(() => warehouseLogisticsItems.length > 0);
  const hasWarehouseLogisticsItems = computed(
    () => warehouseLogisticsItems.length > 0
  );
  const hasProductionItems = computed(() => productionItems.length > 0);
  const hasEquipmentItems = computed(() => equipmentItems.length > 0);
  const hasArchiveManagementItems = computed(() => archiveManagementItems.length > 0);
  const hasArchiveManagementItems = computed(
    () => archiveManagementItems.length > 0
  );
  onMounted(() => {
    // æ¯æ¬¡è¿›å…¥é¦–页都强制刷新用户信息和路由权限,不做本地缓存判断