zhengyiming
2025-10-28 ab8d587bef7462378e8c4a93d7088fe17cb13845
feat: init
4个文件已修改
406 ■■■■■ 已修改文件
src/components/Form/ProFromAddressSelectV2.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/common/common.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CustomerManage/components/AddOrEditCustomerView.vue 363 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/ProFromAddressSelectV2.vue
@@ -24,7 +24,7 @@
});
type Props = {
  areaList: number[];
  areaList: string[];
  areaListPlaceholder?: string;
  disabled?: boolean;
  layer?: AreaType;
@@ -36,7 +36,7 @@
});
const emit = defineEmits<{
  (e: 'update:areaList', val: number[]): void;
  (e: 'update:areaList', val: string[]): void;
}>();
const { areaList: innerAreaList } = useVModels(props, emit);
src/router/index.ts
@@ -124,8 +124,8 @@
      {
        path: '/AddOrEditCustomer/:id?',
        name: 'AddOrEditCustomer',
        hidden: false,
        alwaysShow: true,
        hidden: true,
        alwaysShow: false,
        component: () => import('@/views/CustomerManage/AddOrEditCustomer.vue'),
        meta: {
          rank: 10011,
@@ -135,8 +135,8 @@
      {
        path: '/CustomerDetail/:id',
        name: 'CustomerDetail',
        hidden: false,
        alwaysShow: true,
        hidden: true,
        alwaysShow: false,
        component: () => import('@/views/CustomerManage/CustomerDetail.vue'),
        meta: {
          rank: 10011,
src/utils/common/common.ts
@@ -130,3 +130,34 @@
  }
  return null;
}
/**
 * 剔除对象中值为 ''、undefined、null 的键,支持嵌套对象
 * @param {Object} obj - 需要处理的对象
 * @returns {Object} 处理后的新对象
 */
export function removeEmptyKeys<T extends object>(obj: T) {
  // 如果不是对象或为null,直接返回原值
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  // 处理数组(递归处理每个元素)
  if (Array.isArray(obj)) {
    return obj.map((item) => removeEmptyKeys(item));
  }
  // 处理对象
  const result = {} as T;
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      //@ts-ignore
      const value = removeEmptyKeys(obj[key]); // 递归处理嵌套对象
      // 只保留非空值(排除''、undefined、null)
      if (value !== '' && value !== undefined && value !== null) {
        result[key] = value;
      }
    }
  }
  return result;
}
src/views/CustomerManage/components/AddOrEditCustomerView.vue
@@ -1,10 +1,248 @@
<template>
  <div></div>
  <LoadingLayout :loading="isEdit && isLoading">
    <AppScrollContainer>
      <ChunkCell title="企业基本信息">
        <ProForm :model="form" ref="formRef" label-width="140px" :is-read="isDetail">
          <ProFormCol>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="企业名称:"
                prop="enterpriseName"
                :check-rules="[{ message: '请输入企业名称' }]"
              >
                <ProFormText
                  v-model.trim="form.enterpriseName"
                  :maxlength="30"
                  placeholder="请输入企业名称"
                />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2 label="法人姓名:" prop="legalPerson">
                <ProFormText
                  v-model.trim="form.legalPerson"
                  :maxlength="30"
                  placeholder="请输入法人姓名"
                />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2 label="法人身份证号:" prop="legalIdentity">
                <ProFormText
                  v-model.trim="form.legalIdentity"
                  :maxlength="30"
                  placeholder="请输入法人身份证号"
                />
              </ProFormItemV2>
            </ProFormColItem>
          </ProFormCol>
          <ProFormCol>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="统一社会信用代码:"
                prop="societyCreditCode"
                :check-rules="[{ message: '请输入统一社会信用代码', type: 'societyCreditCode' }]"
              >
                <ProFormText
                  v-model.trim="form.societyCreditCode"
                  placeholder="请输入统一社会信用代码"
                />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="注册资本:"
                prop="societyCreditCode"
                :check-rules="[{ message: '请输入注册资本', type: 'societyCreditCode' }]"
              >
                <ProFormText v-model.trim="form.societyCreditCode" placeholder="请输入注册资本" />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="企业类型:"
                prop="societyCreditCode"
                :check-rules="[{ message: '请输入企业类型', type: 'societyCreditCode' }]"
              >
                <ProFormText v-model.trim="form.societyCreditCode" placeholder="请输入企业类型" />
              </ProFormItemV2>
            </ProFormColItem>
          </ProFormCol>
          <ProFormCol>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="成立日期:"
                prop="date"
                :check-rules="[{ message: '请选择成立日期' }]"
              >
                <ProFormDatePicker v-model="form.date" type="date" placeholder="请选择成立日期" />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="所在省份:"
                prop="areaList"
                :check-rules="[
                  {
                    type: 'array',
                    message: '请选择',
                  },
                ]"
              >
                <ProFromAddressSelectV2
                  v-model:areaList="form.areaList"
                  areaListPlaceholder="请选择"
                  :layer="AreaType.City"
                />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="所在城市:"
                prop="areaList"
                :check-rules="[
                  {
                    type: 'array',
                    message: '请选择',
                  },
                ]"
              >
                <ProFromAddressSelectV2
                  v-model:areaList="form.areaList"
                  areaListPlaceholder="请选择"
                  :layer="AreaType.City"
                />
              </ProFormItemV2>
            </ProFormColItem>
          </ProFormCol>
          <ProFormCol>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="详细地址:"
                prop="societyCreditCode"
                :check-rules="[{ message: '请输入详细地址' }]"
              >
                <ProFormText v-model.trim="form.societyCreditCode" placeholder="请输入详细地址" />
              </ProFormItemV2>
            </ProFormColItem>
          </ProFormCol>
          <ProFormItemV2
            label="经营范围:"
            prop="mainBusiness"
            :check-rules="[{ message: '请输入经营范围' }]"
          >
            <ProFormTextArea
              v-model="form.mainBusiness"
              maxlength="200"
              :rows="6"
              show-word-limit
              placeholder="请输入经营范围"
            />
          </ProFormItemV2>
        </ProForm>
      </ChunkCell>
      <ChunkCell title="合作信息">
        <ProForm
          :model="form"
          ref="settingFormRef"
          label-width="140px"
          :scroll-to-error="false"
          :is-read="isDetail"
        >
          <ProFormCol>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="联系人:"
                prop="contacts"
                :check-rules="[{ message: '请输入联系人' }]"
              >
                <ProFormText
                  v-model.trim="form.contacts"
                  :maxlength="30"
                  placeholder="请输入联系人"
                />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="联系电话:"
                prop="contactPhoneNumber"
                :check-rules="[{ message: '请输入联系电话', type: 'phone' }]"
              >
                <ProFormText v-model.trim="form.contactPhoneNumber" placeholder="请输入联系电话" />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2 label="联系邮箱:" prop="contactEmail">
                <ProFormText
                  v-model.trim="form.contactEmail"
                  :maxlength="30"
                  placeholder="请输入联系邮箱"
                  :formatter="filterCN"
                />
              </ProFormItemV2>
            </ProFormColItem>
          </ProFormCol>
          <ProFormCol>
            <ProFormColItem :span="8">
              <ProFormItemV2 label="合作状态:" prop="contacts"> </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2 label="签约状态:" prop="contacts"> </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2 label="合作协议:" prop="contacts"> </ProFormItemV2>
            </ProFormColItem>
          </ProFormCol>
        </ProForm>
      </ChunkCell>
      <ChunkCell title="账号信息">
        <ProForm
          :model="form"
          ref="accountFormRef"
          label-width="140px"
          :scroll-to-error="false"
          :is-read="isDetail"
        >
          <ProFormCol>
            <ProFormColItem :span="8">
              <ProFormItemV2
                label="账号:"
                prop="userName"
                :check-rules="[{ message: '请输入账号' }]"
              >
                <ProFormText
                  v-model.trim="form.userName"
                  :maxlength="30"
                  placeholder="请输入账号"
                />
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8" v-if="!isEdit">
              <ProFormItemV2
                label="密码:"
                prop="password"
                :check-rules="[{ message: '请输入密码' }]"
              >
                <ProFormText
                  v-model.trim="form.password"
                  :maxlength="30"
                  placeholder="请输入密码"
                />
              </ProFormItemV2>
            </ProFormColItem>
          </ProFormCol>
          <div class="chuck-add-or-edit-actions">
            <el-button @click="handleBack">返回</el-button>
            <el-button v-if="!isDetail" type="primary" @click="handleSubmit">确认</el-button>
          </div>
        </ProForm>
      </ChunkCell>
    </AppScrollContainer>
  </LoadingLayout>
</template>
<script setup lang="ts">
import { Message, BoleRegExp } from '@bole-core/core';
import { useQuery } from '@tanstack/vue-query';
import {
  LoadingLayout,
  AppScrollContainer,
@@ -16,32 +254,127 @@
  ProFormTextArea,
  ProFormCol,
  ProFormColItem,
  ProFormDatePicker,
} from '@bole-core/components';
import { FormRules, FormInstance } from 'element-plus';
import * as enterpriseServices from '@/services/api/enterprise';
import { useRouteView, useGlobalEventContext, GlobalEvent } from '@/hooks';
import _ from 'lodash';
import { validateFormList, filterCN, removeEmptyKeys } from '@/utils';
import { Message, BoleRegExp } from '@bole-core/core';
import { useQuery } from '@tanstack/vue-query';
import { AreaType } from '@/constants';
defineOptions({
  name: 'AddOrEditCustomerView',
})
});
type Props = {
  isDetail: boolean;
}
};
const props = withDefaults(defineProps<Props>(), {
})
const props = withDefaults(defineProps<Props>(), {});
const route = useRoute();
const id = route.params.id as string;
const isEdit =  !!id;
const isEdit = !!id;
const { closeViewPush } = useRouteView();
const eventContext = useGlobalEventContext();
const form = reactive({
  id: '',
  enterpriseName: '',
  legalPerson: '',
  legalIdentity: '',
  societyCreditCode: '',
  industryTypeCode: '',
  mainBusiness: '',
  areaList: [] as string[],
  contacts: '',
  contactPhoneNumber: '',
  contactEmail: '',
  userName: '',
  password: '',
  date: '',
});
const { isLoading } = useQuery({
  queryKey: ['enterpriseServices/getEnterprise', id],
  queryFn: async () => {
    return await enterpriseServices.getEnterprise(
      { id: id },
      {
        showLoading: false,
      }
    );
  },
  onSuccess(data) {
    form.id = data.id;
    form.enterpriseName = data.enterpriseName;
    form.legalPerson = data.legalPerson;
    form.legalIdentity = data.legalIdentity;
    form.societyCreditCode = data.societyCreditCode;
    form.industryTypeCode = data.industryTypeCode ?? '';
    form.mainBusiness = data.mainBusiness;
    form.contacts = data.contacts;
    form.contactPhoneNumber = data.contactPhoneNumber;
    form.contactEmail = data.contactEmail;
    form.userName = data.userName;
    form.areaList = [data.provinceCode, data.cityCode].filter(Boolean);
  },
  enabled: computed(() => !!id),
});
const formRef = ref<FormInstance>();
const settingFormRef = ref<FormInstance>();
const accountFormRef = ref<FormInstance>();
async function handleSubmit() {
  try {
    const valid = await validateFormList([
      formRef.value,
      settingFormRef.value,
      accountFormRef.value,
    ]);
    if (valid) {
      handleCreateOrEditFlexEnterprise();
    }
  } catch (error) {}
}
async function handleCreateOrEditFlexEnterprise() {
  try {
    let params: API.SaveEnterpriseCommand = {
      enterpriseName: form.enterpriseName,
      legalPerson: form.legalPerson,
      legalIdentity: form.legalIdentity,
      societyCreditCode: form.societyCreditCode,
      provinceCode: form.areaList[0],
      cityCode: form.areaList[1],
      industryTypeCode: form.industryTypeCode,
      mainBusiness: form.mainBusiness,
      contacts: form.contacts,
      contactPhoneNumber: form.contactPhoneNumber,
      contactEmail: form.contactEmail,
      userName: form.userName,
      password: form.password,
    };
    if (isEdit) {
      params.id = id;
    }
    let res = await enterpriseServices.saveEnterprise(removeEmptyKeys(params));
    if (res) {
      Message.successMessage(isEdit ? '编辑成功' : '发布成功');
      eventContext.emit(isEdit ? 'customerManage:edit' : 'customerManage:add');
      handleBack();
    }
  } catch (error) {}
}
function handleBack() {
  closeViewPush(route, {
    name: 'EnterpriseManageList',
  });
}
</script>
<style lang="scss" scoped>
@use '@/style/common.scss' as *;
</style>