gaoluyang
4 天以前 f4a4737d69746268f3648effcf66e1c1c83e64e1
公司7004
1.标书台账页面开发与联调
2.客户管理添加客户类型字段
已添加2个文件
已修改2个文件
846 ■■■■■ 文件已修改
src/api/salesManagement/bidWinningLedger.js 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/customerFile/index.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/bidWinningLedger/index.vue 724 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/opportunityManagement/index.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/salesManagement/bidWinningLedger.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
import request from "@/utils/request";
export function getProvinceList() {
  return request({
    url: "/sales/bidWinningLedger/getProvinceList",
    method: "get",
  });
}
export function getCityList(params) {
  return request({
    url: "/sales/bidWinningLedger/getCityList",
    method: "get",
    params,
  });
}
export function bidWinningLedgerListPage(params) {
  return request({
    url: "/sales/bidWinningLedger/listPage",
    method: "get",
    params,
  });
}
export function bidWinningLedgerDetail(params) {
  return request({
    url: "/sales/bidWinningLedger/detail",
    method: "get",
    params,
  });
}
export function bidWinningLedgerAdd(data) {
  return request({
    url: "/sales/bidWinningLedger/add",
    method: "post",
    data,
  });
}
export function bidWinningLedgerUpdate(data) {
  return request({
    url: "/sales/bidWinningLedger/update",
    method: "post",
    data,
  });
}
export function bidWinningLedgerDelete(data) {
  return request({
    url: "/sales/bidWinningLedger/delete",
    method: "delete",
    data,
  });
}
src/views/basicData/customerFile/index.vue
@@ -122,6 +122,19 @@
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户类型:" prop="customerType">
              <el-select
                v-model="form.customerType"
                placeholder="请选择"
                clearable
                style="width: 100%"
              >
                <el-option label="普通客户" :value="1" />
                <el-option label="中小客户" :value="2" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
                <el-row :gutter="30" v-for="(contact, index) in formYYs.contactList" :key="index">
                    <el-col :span="12">
@@ -248,6 +261,22 @@
const tableColumn = ref([
  {
        label: "客户类型",
        prop: "customerType",
        width: 120,
        dataType: "tag",
        formatData: (value) => {
            if (String(value) === "1") return "普通客户";
            if (String(value) === "2") return "中小客户";
            return "";
        },
        formatType: (value) => {
            if (String(value) === "1") return "primary";
            if (String(value) === "2") return "success";
            return "info";
        },
    },
  {
    label: "客户名称",
    prop: "customerName",
    width: 220,
@@ -342,6 +371,7 @@
  },
  form: {
    customerName: "",
    customerType: undefined,
    taxpayerIdentificationNumber: "",
    companyAddress: "",
    companyPhone: "",
@@ -355,6 +385,7 @@
  },
  rules: {
    customerName: [{ required: true, message: "请输入", trigger: "blur" }],
    customerType: [{ required: true, message: "请选择", trigger: "change" }],
    taxpayerIdentificationNumber: [
      { required: true, message: "请输入", trigger: "blur" },
    ],
src/views/salesManagement/bidWinningLedger/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,724 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :model="searchForm" :inline="true">
        <el-form-item label="省份">
          <el-select
            v-model="searchForm.provinceId"
            placeholder="请选择省份"
            clearable
            filterable
            style="width: 180px"
            @change="handleSearchProvinceChange"
          >
            <el-option
              v-for="item in provinceOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="城市">
          <el-select
            v-model="searchForm.cityId"
            placeholder="请选择城市"
            clearable
            filterable
            style="width: 180px"
            @change="handleQuery"
          >
            <el-option
              v-for="item in searchCityOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="客户名称">
          <el-select
            v-model="searchForm.customerName"
            placeholder="请选择客户名称"
            clearable
            filterable
            style="width: 200px"
            @change="handleQuery"
          >
            <el-option
              v-for="item in customerOptions"
              :key="item.id || item.customerName"
              :label="item.customerName"
              :value="item.customerName"
            >
              {{ item.customerName }}{{ item.taxpayerIdentificationNumber ? ` - ${item.taxpayerIdentificationNumber}` : "" }}
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="录入人">
          <el-input
            v-model="searchForm.entryPerson"
            placeholder="请输入录入人"
            clearable
            style="width: 180px"
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item label="录入日期">
          <el-date-picker
            v-model="searchForm.entryDateRange"
            type="daterange"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            range-separator="-"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            clearable
            @change="changeDateRange"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">搜索</el-button>
          <el-button @click="resetQuery">重置</el-button>
          <el-button type="primary" @click="handleAdd">新增</el-button>
          <el-button type="danger" plain @click="handleDelete">删除</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="table_list">
      <el-table
        :data="tableData"
        border
        stripe
        v-loading="tableLoading"
        height="calc(100vh - 18.5em)"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" fixed="left" />
        <el-table-column type="index" label="序号" width="60" align="center" fixed="left" />
        <el-table-column prop="province" label="省份" min-width="120" />
        <el-table-column prop="city" label="城市" min-width="120" />
        <el-table-column prop="customerName" label="客户名称" min-width="220" show-overflow-tooltip />
        <el-table-column prop="contractAmount" label="中标金额" min-width="130" />
        <el-table-column prop="bidBond" label="投标保证金" min-width="130" />
        <el-table-column prop="winningServiceFee" label="中标服务费" min-width="130" />
        <el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip />
        <el-table-column prop="entryPerson" label="录入人" min-width="100" />
        <el-table-column prop="entryDate" label="录入日期" min-width="120" />
        <el-table-column prop="updateTime" label="修改时间" min-width="170" />
        <el-table-column fixed="right" label="操作" width="180" align="center">
          <template #default="{ row }">
                        <el-button link type="primary" size="small" @click="handleEdit(row)">
                            ç¼–辑
                        </el-button>
            <el-button link type="primary" size="small" @click="handleDetail(row)">
              è¯¦æƒ…
            </el-button>
            <el-button link type="danger" size="small" @click="handleDelete(row)">
              åˆ é™¤
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="900px"
      @close="closeDialog"
    >
      <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
        :disabled="dialogMode === 'detail'"
      >
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="客户名称" prop="customerName">
              <el-select
                v-model="form.customerName"
                placeholder="请选择客户名称"
                clearable
                filterable
                style="width: 100%"
              >
                <el-option
                  v-for="item in customerOptions"
                  :key="item.id || item.customerName"
                  :label="item.customerName"
                  :value="item.customerName"
                >
                  {{ item.customerName }}{{ item.taxpayerIdentificationNumber ? ` - ${item.taxpayerIdentificationNumber}` : "" }}
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="省份" prop="provinceId">
              <el-select
                v-model="form.provinceId"
                placeholder="请选择省份"
                filterable
                style="width: 100%"
                @change="handleFormProvinceChange"
              >
                <el-option
                  v-for="item in provinceOptions"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="城市" prop="cityId">
              <el-select
                v-model="form.cityId"
                placeholder="请选择城市"
                filterable
                style="width: 100%"
              >
                <el-option
                  v-for="item in cityOptions"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="中标金额" prop="contractAmount">
              <el-input-number
                v-model="form.contractAmount"
                :min="0"
                :precision="2"
                style="width: 100%"
                controls-position="right"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="投标保证金" prop="bidBond">
              <el-input-number
                v-model="form.bidBond"
                :min="0"
                :precision="2"
                style="width: 100%"
                controls-position="right"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="中标服务费" prop="winningServiceFee">
              <el-input-number
                v-model="form.winningServiceFee"
                :min="0"
                :precision="2"
                style="width: 100%"
                controls-position="right"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="录入人" prop="entryPerson">
              <el-select
                v-model="form.entryPerson"
                placeholder="请选择录入人"
                filterable
                allow-create
                default-first-option
                style="width: 100%"
              >
                <el-option
                  v-for="item in userOptions"
                  :key="item.userId || item.nickName"
                  :label="item.nickName"
                  :value="item.nickName"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="录入日期" prop="entryDate">
              <el-date-picker
                v-model="form.entryDate"
                type="date"
                value-format="YYYY-MM-DD"
                format="YYYY-MM-DD"
                placeholder="请选择录入日期"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="form.remark"
            type="textarea"
            :rows="3"
            placeholder="请输入备注"
          />
        </el-form-item>
        <el-form-item label="附件" v-if="dialogMode !== 'detail'">
          <el-upload
            ref="fileUploadRef"
            v-model:file-list="fileList"
            :action="upload.url"
            :headers="upload.headers"
            :data="upload.data"
            multiple
            auto-upload
            :before-upload="handleBeforeUpload"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            :on-remove="handleRemove"
          >
            <el-button type="primary">上传附件</el-button>
            <template #tip>
              <div class="el-upload__tip">支持常见办公文档与图片格式</div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <div v-if="dialogMode === 'detail'">
        <el-divider content-position="left">附件</el-divider>
        <el-table :data="form.commonFiles || []" border stripe empty-text="暂无附件">
          <el-table-column prop="name" label="附件名称" min-width="300" show-overflow-tooltip />
          <el-table-column label="操作" width="160" align="center">
            <template #default="{ row }">
              <el-button link type="primary" size="small" @click="downloadFile(row)">
                ä¸‹è½½
              </el-button>
              <el-button link type="primary" size="small" @click="previewFile(row)">
                é¢„览
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <filePreview ref="filePreviewRef" />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
          <el-button type="primary" v-if="dialogMode !== 'detail'" @click="submitForm">
            ç¡®å®š
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { computed, getCurrentInstance, onMounted, reactive, ref } from "vue";
import dayjs from "dayjs";
import { ElMessageBox } from "element-plus";
import pagination from "@/components/PIMTable/Pagination.vue";
import filePreview from "@/components/filePreview/index.vue";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth";
import { userListNoPage } from "@/api/system/user";
import { customerList } from "@/api/salesManagement/salesLedger";
import {
  bidWinningLedgerAdd,
  bidWinningLedgerDelete,
  bidWinningLedgerDetail,
  bidWinningLedgerListPage,
  bidWinningLedgerUpdate,
  getCityList,
  getProvinceList,
} from "@/api/salesManagement/bidWinningLedger";
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const tableData = ref([]);
const tableLoading = ref(false);
const selectedRows = ref([]);
const total = ref(0);
const userOptions = ref([]);
const customerOptions = ref([]);
const provinceOptions = ref([]);
const cityOptions = ref([]);
const searchCityOptions = ref([]);
const dialogVisible = ref(false);
const dialogMode = ref("add");
const formRef = ref();
const fileUploadRef = ref();
const filePreviewRef = ref();
const fileList = ref([]);
const upload = reactive({
  url: `${import.meta.env.VITE_APP_BASE_API}/file/upload`,
  headers: {
    Authorization: `Bearer ${getToken()}`,
  },
  data: {
    type: 10,
  },
});
const page = reactive({
  current: 1,
  size: 20,
});
const createSearchForm = () => ({
  provinceId: "",
  cityId: "",
  customerName: "",
  entryPerson: "",
  entryDateRange: [],
  entryDateStart: "",
  entryDateEnd: "",
});
const createFormData = () => ({
  id: undefined,
  province: "",
  city: "",
  provinceId: "",
  cityId: "",
  customerName: "",
  contractAmount: undefined,
  bidBond: undefined,
  winningServiceFee: undefined,
  remark: "",
  entryPerson: userStore.nickName || "",
  entryDate: dayjs().format("YYYY-MM-DD"),
  commonFiles: [],
  tempFileIds: [],
});
const searchForm = reactive(createSearchForm());
const form = reactive(createFormData());
const rules = reactive({
  provinceId: [{ required: true, message: "请选择省份", trigger: "change" }],
  cityId: [{ required: true, message: "请选择城市", trigger: "change" }],
  customerName: [{ required: true, message: "请选择客户名称", trigger: "change" }],
  entryPerson: [{ required: true, message: "请选择录入人", trigger: "change" }],
  entryDate: [{ required: true, message: "请选择录入日期", trigger: "change" }],
});
const dialogTitle = computed(() => {
  if (dialogMode.value === "add") return "新增中标台账";
  if (dialogMode.value === "edit") return "编辑中标台账";
  return "中标台账详情";
});
const getOptionName = (options, id) => {
  const target = options.find((item) => String(item.id) === String(id));
  return target?.name || "";
};
const buildQueryParams = () => {
  const params = {
    current: page.current,
    size: page.size,
    customerName: searchForm.customerName,
    entryPerson: searchForm.entryPerson,
    province: getOptionName(provinceOptions.value, searchForm.provinceId),
    city: getOptionName(searchCityOptions.value, searchForm.cityId),
  };
  if (searchForm.entryDateStart) {
    params.entryDateStart = searchForm.entryDateStart;
  }
  if (searchForm.entryDateEnd) {
    params.entryDateEnd = searchForm.entryDateEnd;
  }
  Object.keys(params).forEach((key) => {
    if (params[key] === "" || params[key] === undefined || params[key] === null) {
      delete params[key];
    }
  });
  return params;
};
const getList = async () => {
  tableLoading.value = true;
  try {
    const res = await bidWinningLedgerListPage(buildQueryParams());
    tableData.value = res?.data?.records || [];
    total.value = res?.data?.total || 0;
  } finally {
    tableLoading.value = false;
  }
};
const loadProvinceOptions = async () => {
  const res = await getProvinceList();
  provinceOptions.value = res?.data || [];
};
const loadCityOptions = async (provinceId, target = "form") => {
  if (!provinceId) {
    if (target === "form") {
      cityOptions.value = [];
    } else {
      searchCityOptions.value = [];
    }
    return [];
  }
  const res = await getCityList({ provinceId });
  const list = res?.data || [];
  if (target === "form") {
    cityOptions.value = list;
  } else {
    searchCityOptions.value = list;
  }
  return list;
};
const loadUserOptions = async () => {
  const res = await userListNoPage();
  userOptions.value = res?.data || [];
};
const loadCustomerOptions = async () => {
  const res = await customerList();
  customerOptions.value = res || [];
};
const changeDateRange = (value) => {
  if (value?.length === 2) {
    searchForm.entryDateStart = value[0];
    searchForm.entryDateEnd = value[1];
  } else {
    searchForm.entryDateStart = "";
    searchForm.entryDateEnd = "";
  }
  handleQuery();
};
const handleSearchProvinceChange = async () => {
  searchForm.cityId = "";
  await loadCityOptions(searchForm.provinceId, "search");
  handleQuery();
};
const handleFormProvinceChange = async () => {
  form.cityId = "";
  await loadCityOptions(form.provinceId, "form");
};
const handleQuery = () => {
  page.current = 1;
  getList();
};
const resetQuery = async () => {
  Object.assign(searchForm, createSearchForm());
  searchCityOptions.value = [];
  page.current = 1;
  await getList();
};
const paginationChange = ({ page: current, limit }) => {
  page.current = current;
  page.size = limit;
  getList();
};
const handleSelectionChange = (rows) => {
  selectedRows.value = rows;
};
const resetFormState = () => {
  Object.assign(form, createFormData());
  cityOptions.value = [];
  fileList.value = [];
  formRef.value?.clearValidate();
};
const mapNameToId = (options, name) => {
  const target = options.find((item) => item.name === name);
  return target?.id || "";
};
const openDialog = async (mode, row) => {
  dialogMode.value = mode;
  resetFormState();
  await Promise.all([loadUserOptions(), loadProvinceOptions(), loadCustomerOptions()]);
  if (mode === "add") {
    dialogVisible.value = true;
    return;
  }
  const res = await bidWinningLedgerDetail({ id: row.id });
  const detail = res?.data || {};
  Object.assign(form, detail, {
    entryDate: detail.entryDate ? dayjs(detail.entryDate).format("YYYY-MM-DD") : "",
    commonFiles: detail.commonFiles || [],
  });
  form.provinceId = mapNameToId(provinceOptions.value, detail.province);
  await loadCityOptions(form.provinceId, "form");
  form.cityId = mapNameToId(cityOptions.value, detail.city);
  fileList.value = (detail.commonFiles || []).map((item) => ({
    name: item.name,
    url: item.url,
    id: item.id,
  }));
  dialogVisible.value = true;
};
const handleAdd = () => {
  openDialog("add");
};
const handleEdit = (row) => {
  openDialog("edit", row);
};
const handleDetail = (row) => {
  openDialog("detail", row);
};
const buildSubmitData = () => {
  const tempFileIds = fileList.value
    .map((item) => item.tempId)
    .filter((item) => item !== undefined && item !== null && item !== "");
  return {
    id: form.id,
    province: getOptionName(provinceOptions.value, form.provinceId),
    city: getOptionName(cityOptions.value, form.cityId),
    customerName: form.customerName,
    contractAmount: form.contractAmount,
    bidBond: form.bidBond,
    winningServiceFee: form.winningServiceFee,
    remark: form.remark,
    entryPerson: form.entryPerson,
    entryDate: form.entryDate,
    tempFileIds,
  };
};
const submitForm = () => {
  formRef.value.validate(async (valid) => {
    if (!valid) {
      return;
    }
    const api = dialogMode.value === "edit" ? bidWinningLedgerUpdate : bidWinningLedgerAdd;
    await api(buildSubmitData());
    proxy.$modal.msgSuccess(dialogMode.value === "edit" ? "修改成功" : "新增成功");
    closeDialog();
    getList();
  });
};
const handleDelete = (row) => {
  const ids = row ? [row.id] : selectedRows.value.map((item) => item.id);
  if (!ids.length) {
    proxy.$modal.msgWarning("请选择要删除的中标台账");
    return;
  }
  ElMessageBox.confirm("确认删除选中的中标台账吗?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      await bidWinningLedgerDelete(ids);
      proxy.$modal.msgSuccess("删除成功");
      getList();
    })
    .catch(() => {});
};
const closeDialog = () => {
  dialogVisible.value = false;
  resetFormState();
};
const handleBeforeUpload = () => {
  proxy.$modal.loading("正在上传文件,请稍候...");
  return true;
};
const handleUploadSuccess = (res, file) => {
  proxy.$modal.closeLoading();
  if (res.code === 200) {
    file.tempId = res.data?.tempId;
    proxy.$modal.msgSuccess("上传成功");
  } else {
    proxy.$modal.msgError(res.msg || "上传失败");
    fileUploadRef.value?.handleRemove(file);
  }
};
const handleUploadError = () => {
  proxy.$modal.closeLoading();
  proxy.$modal.msgError("上传失败");
};
const handleRemove = () => {};
const downloadFile = (row) => {
  if (row?.url) {
    proxy.$download.name(row.url);
  }
};
const previewFile = (row) => {
  if (row?.url) {
    filePreviewRef.value.open(row.url);
  }
};
onMounted(async () => {
  await Promise.all([loadProvinceOptions(), loadUserOptions(), loadCustomerOptions()]);
  getList();
});
</script>
<style scoped lang="scss">
.table_list {
  margin-top: unset;
}
.dialog-footer {
  text-align: right;
}
:deep(.el-input-number) {
  width: 100%;
}
</style>
src/views/salesManagement/opportunityManagement/index.vue
@@ -456,7 +456,9 @@
const userList = ref([])
const customerOption = ref([])
const DEFAULT_USER_QUERY = { postCode: 'Market_Sales' }
const DEFAULT_CUSTOMER_QUERY = { customerType: 2 }
let userListPromise = null
let customerListPromise = null
const loadUserList = async (query = DEFAULT_USER_QUERY) => {
  if (userListPromise) return userListPromise
@@ -473,6 +475,23 @@
    }
  })()
  return userListPromise
}
const loadCustomerList = async (query = DEFAULT_CUSTOMER_QUERY) => {
  if (customerListPromise) return customerListPromise
  customerListPromise = (async () => {
    try {
      const res = await customerList(query)
      customerOption.value = res || []
      return customerOption.value
    } catch (err) {
      console.error('获取客户列表失败:', err)
      customerOption.value = []
      customerListPromise = null
      throw err
    }
  })()
  return customerListPromise
}
// åˆ†é¡µé…ç½®
@@ -703,9 +722,7 @@
  
  // åŠ è½½ç”¨æˆ·åˆ—è¡¨å’Œå®¢æˆ·åˆ—è¡¨
  await loadUserList()
  customerList().then((res) => {
    customerOption.value = res
  })
  await loadCustomerList()
    getProvinceList().then(res => {
        provinceOptions.value = res.data
    })
@@ -724,9 +741,7 @@
  
  // åŠ è½½ç”¨æˆ·åˆ—è¡¨å’Œå®¢æˆ·åˆ—è¡¨
  await loadUserList()
  customerList().then((res) => {
    customerOption.value = res
  })
  await loadCustomerList()
  
  // ä½¿ç”¨å½“前行数据作为基础,但只能修改状态和拜访记录;付款描述、改造内容等保留反显
  Object.assign(form, row, {
@@ -745,9 +760,7 @@
  
  // åŠ è½½ç”¨æˆ·åˆ—è¡¨å’Œå®¢æˆ·åˆ—è¡¨
  await loadUserList()
  customerList().then((res) => {
    customerOption.value = res
  })
  await loadCustomerList()
  
  // ä½¿ç”¨updateTime作为录入时间反显
  Object.assign(form, row, {
@@ -787,9 +800,7 @@
  
  // åŠ è½½ç”¨æˆ·åˆ—è¡¨å’Œå®¢æˆ·åˆ—è¡¨
  await loadUserList()
  customerList().then((res) => {
    customerOption.value = res
  })
  await loadCustomerList()
  
  // åŠ è½½çœä»½åˆ—è¡¨
  await getProvinceList().then(res => {