feat: crm business status
							parent
							
								
									53e049241a
								
							
						
					
					
						commit
						faa303526d
					
				| 
						 | 
				
			
			@ -5,20 +5,19 @@ import { requestClient } from '#/api/request';
 | 
			
		|||
export namespace CrmBusinessStatusApi {
 | 
			
		||||
  /** 商机状态信息 */
 | 
			
		||||
  export interface BusinessStatusType {
 | 
			
		||||
    id: number;
 | 
			
		||||
    id?: number;
 | 
			
		||||
    name: string;
 | 
			
		||||
    percent: number;
 | 
			
		||||
    sort: number;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** 商机状态组信息 */
 | 
			
		||||
  export interface BusinessStatus {
 | 
			
		||||
    id: number;
 | 
			
		||||
    id?: number;
 | 
			
		||||
    name: string;
 | 
			
		||||
    deptIds: number[];
 | 
			
		||||
    deptNames: string[];
 | 
			
		||||
    creator: string;
 | 
			
		||||
    createTime: Date;
 | 
			
		||||
    deptIds?: number[];
 | 
			
		||||
    deptNames?: string[];
 | 
			
		||||
    creator?: string;
 | 
			
		||||
    createTime?: Date;
 | 
			
		||||
    statuses?: BusinessStatusType[];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
			
		|||
 | 
			
		||||
import { handleTree } from '@vben/utils';
 | 
			
		||||
 | 
			
		||||
import { z } from '#/adapter/form';
 | 
			
		||||
import { getDeptList } from '#/api/system/dept';
 | 
			
		||||
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
 | 
			
		||||
 | 
			
		||||
/** 新增/修改的表单 */
 | 
			
		||||
export function useFormSchema(): VbenFormSchema[] {
 | 
			
		||||
| 
						 | 
				
			
			@ -38,17 +36,13 @@ export function useFormSchema(): VbenFormSchema[] {
 | 
			
		|||
        placeholder: '请选择应用部门',
 | 
			
		||||
        treeDefaultExpandAll: true,
 | 
			
		||||
      },
 | 
			
		||||
      help: '不选择部门时,默认全公司生效',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      fieldName: 'status',
 | 
			
		||||
      label: '状态',
 | 
			
		||||
      component: 'RadioGroup',
 | 
			
		||||
      componentProps: {
 | 
			
		||||
        options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'),
 | 
			
		||||
        buttonStyle: 'solid',
 | 
			
		||||
        optionType: 'button',
 | 
			
		||||
      },
 | 
			
		||||
      rules: z.number().default(CommonStatusEnum.ENABLE),
 | 
			
		||||
      fieldName: 'statuses',
 | 
			
		||||
      label: '阶段设置',
 | 
			
		||||
      component: 'Input',
 | 
			
		||||
      rules: 'required',
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,11 +5,13 @@ import { computed, ref } from 'vue';
 | 
			
		|||
 | 
			
		||||
import { useVbenModal } from '@vben/common-ui';
 | 
			
		||||
 | 
			
		||||
import { message } from 'ant-design-vue';
 | 
			
		||||
import { Input, InputNumber, message } from 'ant-design-vue';
 | 
			
		||||
 | 
			
		||||
import { useVbenForm } from '#/adapter/form';
 | 
			
		||||
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
			
		||||
import {
 | 
			
		||||
  createBusinessStatus,
 | 
			
		||||
  DEFAULT_STATUSES,
 | 
			
		||||
  getBusinessStatus,
 | 
			
		||||
  updateBusinessStatus,
 | 
			
		||||
} from '#/api/crm/business/status';
 | 
			
		||||
| 
						 | 
				
			
			@ -62,30 +64,153 @@ const [Modal, modalApi] = useVbenModal({
 | 
			
		|||
  },
 | 
			
		||||
  async onOpenChange(isOpen: boolean) {
 | 
			
		||||
    if (!isOpen) {
 | 
			
		||||
      formData.value = undefined;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    // 加载数据
 | 
			
		||||
    const data = modalApi.getData<CrmBusinessStatusApi.BusinessStatus>();
 | 
			
		||||
    if (!data || !data.id) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    modalApi.lock();
 | 
			
		||||
    try {
 | 
			
		||||
      formData.value = await getBusinessStatus(data.id as number);
 | 
			
		||||
      // 设置到 values
 | 
			
		||||
      if (formData.value) {
 | 
			
		||||
        await formApi.setValues(formData.value);
 | 
			
		||||
      if (!data || !data.id) {
 | 
			
		||||
        formData.value = {
 | 
			
		||||
          id: undefined,
 | 
			
		||||
          name: '',
 | 
			
		||||
          deptIds: [],
 | 
			
		||||
          statuses: [],
 | 
			
		||||
        };
 | 
			
		||||
        addStatus();
 | 
			
		||||
      } else {
 | 
			
		||||
        formData.value = await getBusinessStatus(data.id as number);
 | 
			
		||||
        if (
 | 
			
		||||
          !formData.value?.statuses?.length ||
 | 
			
		||||
          formData.value?.statuses?.length === 0
 | 
			
		||||
        ) {
 | 
			
		||||
          addStatus();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      // 设置到 values
 | 
			
		||||
      await formApi.setValues(formData.value as any);
 | 
			
		||||
      formData.value!.statuses =
 | 
			
		||||
        formData.value?.statuses?.concat(DEFAULT_STATUSES);
 | 
			
		||||
      gridApi.grid.reloadData(formData.value!.statuses as any);
 | 
			
		||||
    } finally {
 | 
			
		||||
      modalApi.unlock();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/** 添加状态 */
 | 
			
		||||
function addStatus() {
 | 
			
		||||
  formData.value!.statuses!.push({
 | 
			
		||||
    name: '',
 | 
			
		||||
    percent: undefined,
 | 
			
		||||
  } as any);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 删除状态 */
 | 
			
		||||
function deleteStatusArea(row: any) {
 | 
			
		||||
  formData.value!.statuses!.splice(row.index, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 表格配置 */
 | 
			
		||||
const [Grid, gridApi] = useVbenVxeGrid({
 | 
			
		||||
  gridOptions: {
 | 
			
		||||
    editConfig: {
 | 
			
		||||
      trigger: 'click',
 | 
			
		||||
      mode: 'cell',
 | 
			
		||||
    },
 | 
			
		||||
    columns: [
 | 
			
		||||
      {
 | 
			
		||||
        field: 'defaultStatus',
 | 
			
		||||
        title: '阶段',
 | 
			
		||||
        minWidth: 100,
 | 
			
		||||
        slots: { default: 'defaultStatus' },
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        field: 'name',
 | 
			
		||||
        title: '阶段名称',
 | 
			
		||||
        minWidth: 100,
 | 
			
		||||
        slots: { default: 'name' },
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        field: 'percent',
 | 
			
		||||
        title: '赢单率(%)',
 | 
			
		||||
        minWidth: 100,
 | 
			
		||||
        slots: { default: 'percent' },
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        title: '操作',
 | 
			
		||||
        width: 130,
 | 
			
		||||
        fixed: 'right',
 | 
			
		||||
        slots: { default: 'actions' },
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
    data: formData.value?.statuses?.concat(DEFAULT_STATUSES),
 | 
			
		||||
    border: true,
 | 
			
		||||
    showOverflow: true,
 | 
			
		||||
    autoResize: true,
 | 
			
		||||
    keepSource: true,
 | 
			
		||||
    rowConfig: {
 | 
			
		||||
      keyField: 'row_id',
 | 
			
		||||
    },
 | 
			
		||||
    pagerConfig: {
 | 
			
		||||
      enabled: false,
 | 
			
		||||
    },
 | 
			
		||||
    toolbarConfig: {
 | 
			
		||||
      enabled: false,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Modal :title="getTitle" class="w-1/2">
 | 
			
		||||
    <Form class="mx-4" />
 | 
			
		||||
    <Form class="mx-4">
 | 
			
		||||
      <template #statuses>
 | 
			
		||||
        <Grid class="w-full">
 | 
			
		||||
          <template #defaultStatus="{ row, rowIndex }">
 | 
			
		||||
            <span>
 | 
			
		||||
              {{ row.defaultStatus ? '结束' : `阶段${rowIndex + 1}` }}
 | 
			
		||||
            </span>
 | 
			
		||||
          </template>
 | 
			
		||||
          <template #name="{ row }">
 | 
			
		||||
            <Input v-if="!row.endStatus" v-model:value="row.name" />
 | 
			
		||||
            <span v-else>{{ row.name }}</span>
 | 
			
		||||
          </template>
 | 
			
		||||
          <template #percent="{ row }">
 | 
			
		||||
            <InputNumber
 | 
			
		||||
              v-if="!row.endStatus"
 | 
			
		||||
              v-model:value="row.percent"
 | 
			
		||||
              :min="0"
 | 
			
		||||
              :max="100"
 | 
			
		||||
              :precision="2"
 | 
			
		||||
            />
 | 
			
		||||
            <span v-else>{{ row.percent }}</span>
 | 
			
		||||
          </template>
 | 
			
		||||
          <template #actions="{ row }">
 | 
			
		||||
            <TableAction
 | 
			
		||||
              :actions="[
 | 
			
		||||
                {
 | 
			
		||||
                  label: $t('ui.actionTitle.create'),
 | 
			
		||||
                  type: 'link',
 | 
			
		||||
                  ifShow: () => !row.endStatus,
 | 
			
		||||
                  onClick: addStatus,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  label: $t('common.delete'),
 | 
			
		||||
                  type: 'link',
 | 
			
		||||
                  danger: true,
 | 
			
		||||
                  ifShow: () => !row.endStatus,
 | 
			
		||||
                  popConfirm: {
 | 
			
		||||
                    title: $t('ui.actionMessage.deleteConfirm', [row.name]),
 | 
			
		||||
                    confirm: deleteStatusArea.bind(null, row),
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              ]"
 | 
			
		||||
            />
 | 
			
		||||
          </template>
 | 
			
		||||
        </Grid>
 | 
			
		||||
      </template>
 | 
			
		||||
    </Form>
 | 
			
		||||
  </Modal>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ export function useFormSchema(): VbenFormSchema[] {
 | 
			
		|||
      componentProps: {
 | 
			
		||||
        api: () => getCustomerSimpleList(),
 | 
			
		||||
        fieldNames: {
 | 
			
		||||
          label: 'nickname',
 | 
			
		||||
          label: 'name',
 | 
			
		||||
          value: 'id',
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,7 +112,7 @@ watch(
 | 
			
		|||
        item.sellingPrice = item.contractPrice;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    gridApi.grid?.loadData(tableData.value);
 | 
			
		||||
    gridApi.grid.reloadData(tableData.value);
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    immediate: true,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue