ソースを参照

feat(forecast): 添加销售预测汇总表单验证规则和类型定义

yz 1 ヶ月 前
コミット
d83b55e9fc

+ 121 - 94
src/api/forecast/forecast-summary.js

@@ -1,103 +1,13 @@
 import request from '@/router/axios'
 
-/**
- * 预测汇总查询参数类型定义
- * @typedef {Object} ForecastSummaryQueryParams
- * @property {number} [current=1] - 当前页码
- * @property {number} [size=10] - 每页数量
- * @property {number} [year] - 年份
- * @property {number} [month] - 月份
- * @property {number} [customerId] - 客户ID
- * @property {string} [customerCode] - 客户编码
- * @property {string} [customerName] - 客户名称
- * @property {number} [brandId] - 品牌ID
- * @property {string} [brandCode] - 品牌编码
- * @property {string} [brandName] - 品牌名称
- * @property {number} [itemId] - 物料ID
- * @property {string} [itemCode] - 物料编码
- * @property {string} [itemName] - 物料名称
- * @property {number} [approvalStatus] - 审批状态 0未审批 1已通过 2已拒绝
- */
-
-/**
- * 预测汇总数据项类型定义
- * @typedef {Object} ForecastSummaryItem
- * @property {string} id - 预测汇总ID
- * @property {string} createUser - 创建用户ID
- * @property {string} createDept - 创建部门ID
- * @property {string} createTime - 创建时间
- * @property {string} updateUser - 更新用户ID
- * @property {string} updateTime - 更新时间
- * @property {number} status - 状态
- * @property {number} isDeleted - 是否删除
- * @property {number} year - 年份
- * @property {number} month - 月份
- * @property {number} customerId - 客户ID
- * @property {string} customerCode - 客户编码
- * @property {string} customerName - 客户名称
- * @property {number} brandId - 品牌ID
- * @property {string} brandCode - 品牌编码
- * @property {string} brandName - 品牌名称
- * @property {number} itemId - 物料ID
- * @property {string} itemCode - 物料编码
- * @property {string} itemName - 物料名称
- * @property {string} specs - 规格
- * @property {string} pattern - 花纹
- * @property {string} forecastQuantity - 预测数量
- * @property {number} approvalStatus - 审批状态 0未审批 1已通过 2已拒绝
- * @property {number|null} approvedBy - 审批人ID
- * @property {string|null} approvedName - 审批人姓名
- * @property {string|null} approvedTime - 审批时间
- */
-
-/**
- * 预测汇总分页响应数据类型定义
- * @typedef {Object} ForecastSummaryPageResponse
- * @property {ForecastSummaryItem[]} records - 预测汇总数据记录
- * @property {number} total - 总记录数
- * @property {number} size - 每页数量
- * @property {number} current - 当前页码
- * @property {Array} orders - 排序信息
- * @property {boolean} optimizeCountSql - 是否优化count查询
- * @property {boolean} hitCount - 是否命中count缓存
- * @property {string|null} countId - count查询ID
- * @property {number|null} maxLimit - 最大限制
- * @property {boolean} searchCount - 是否查询count
- * @property {number} pages - 总页数
- */
-
-/**
- * API响应数据类型定义
- * @template T
- * @typedef {Object} ApiResponse
- * @property {ApiResponseData<T>} data
- * @property {ApiResponseData<T>} data
- * @property {string} statusText - HTTP状态文本 (来自AxiosResponse)
- * @property {Object} headers - 响应头信息 (来自AxiosResponse)
- * @property {string} [headers.content-type] - 内容类型
- * @property {Object} config - 请求配置信息 (来自AxiosResponse)
- * @property {string} [config.method] - 请求方法
- * @property {string} [config.url] - 请求URL
- * @property {Record<string, any>} [config.params] - 请求参数
- * @property {Record<string, any>} [config.headers] - 请求头
- */
-
-/**
- * API响应内层data类型定义
- * @template T
- * @typedef {Object} ApiResponseData
- * @property {number} code - 响应码
- * @property {boolean} success - 是否成功
- * @property {T} data - 响应数据
- * @property {string} msg - 响应消息
- */
+// 导入类型定义
 
 /**
  * 获取预测汇总列表
  * @param {number} [current=1] - 当前页码
  * @param {number} [size=10] - 每页数量
- * @param {ForecastSummaryQueryParams} [params={}] - 查询参数
- * @returns {Promise<AxiosResponse<ForecastSummaryPageResponse>>} 预测汇总列表响应
+ * @param {import('../types/forecast').ForecastSummaryQueryParams} [params={}] - 查询参数
+ * @returns {Promise<import('../types/forecast').ForecastSummaryListResponse>} 预测汇总列表响应
  * @description 获取经销商销售预测汇总列表,支持多条件查询和分页
  * @example
  * // 获取第一页10条数据
@@ -127,7 +37,7 @@ export const getForecastSummaryList = async (current = 1, size = 10, params = {}
 /**
  * 获取预测汇总详情
  * @param {string|number} forecastSummaryId - 预测汇总ID
- * @returns {Promise<AxiosResponse<ForecastSummaryItem>>} 预测汇总详情响应
+ * @returns {Promise<import('../types/forecast').ForecastSummaryOperationResponse>} 预测汇总详情响应
  * @description 根据ID获取预测汇总的详细信息
  * @example
  * const result = await getForecastSummaryDetail('1954819531796865026')
@@ -144,3 +54,120 @@ export const getForecastSummaryDetail = async (forecastSummaryId) => {
     method: 'get'
   })
 }
+
+/**
+ * 添加预测汇总
+ * @param {import('../types/forecast').ForecastSummaryForm} data - 预测汇总表单数据
+ * @returns {Promise<import('../types/forecast').ForecastSummaryOperationResponse>} 添加预测汇总响应
+ * @description 创建新的销售预测汇总记录
+ * @example
+ * const formData = {
+ *   year: 2023,
+ *   month: 8,
+ *   customerId: 1001,
+ *   customerCode: 'DLR001',
+ *   customerName: '上海轮胎经销商',
+ *   brandId: 2001,
+ *   brandCode: 'BRD001',
+ *   brandName: '米其林',
+ *   itemId: 3001,
+ *   itemCode: 'ITEM001',
+ *   itemName: '轮胎A型号',
+ *   specs: '225/65R17',
+ *   pattern: 'Primacy SUV',
+ *   forecastQuantity: 150,
+ *   approvalStatus: 0
+ * }
+ * const result = await addForecastSummary(formData)
+ */
+export const addForecastSummary = async (data) => {
+  return request({
+    url: '/api/blade-factory/api/factory/forecast-summary',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 更新预测汇总
+ * @param {Object} data - 预测汇总表单数据(必须包含id)
+ * @returns {Promise<import('../types/forecast').ForecastSummaryOperationResponse>} 更新预测汇总响应
+ * @description 更新现有的销售预测汇总记录
+ * @example
+ * const formData = {
+ *   id: '1954819531796865026',
+ *   year: 2023,
+ *   month: 8,
+ *   customerId: 1001,
+ *   customerCode: 'DLR001',
+ *   customerName: '上海轮胎经销商',
+ *   brandId: 2001,
+ *   brandCode: 'BRD001',
+ *   brandName: '米其林',
+ *   itemId: 3001,
+ *   itemCode: 'ITEM001',
+ *   itemName: '轮胎A型号',
+ *   specs: '225/65R17',
+ *   pattern: 'Primacy SUV',
+ *   forecastQuantity: 180,
+ *   approvalStatus: 0
+ * }
+ * const result = await updateForecastSummary(formData)
+ */
+export const updateForecastSummary = async (data) => {
+  return request({
+    url: '/api/blade-factory/api/factory/forecast-summary',
+    method: 'put',
+    data
+  })
+}
+
+/**
+ * 删除预测汇总
+ * @param {string|number} id - 预测汇总ID
+ * @returns {Promise<import('../types/forecast').ForecastSummaryOperationResponse>} 删除预测汇总响应
+ * @description 根据ID删除销售预测汇总记录
+ * @example
+ * const result = await removeForecastSummary('1954819531796865026')
+ */
+export const removeForecastSummary = async (id) => {
+  return request({
+    url: `/api/blade-factory/api/factory/forecast-summary/${id}`,
+    method: 'delete'
+  })
+}
+
+/**
+ * 批量删除预测汇总
+ * @param {Array<string|number>} ids - 预测汇总ID数组
+ * @returns {Promise<import('../types/forecast').ForecastSummaryBatchOperationResponse>} 批量删除预测汇总响应
+ * @description 批量删除多个销售预测汇总记录
+ * @example
+ * const result = await batchRemoveForecastSummary(['1954819531796865026', '1954819531796865027'])
+ */
+export const batchRemoveForecastSummary = async (ids) => {
+  return request({
+    url: '/api/blade-factory/api/factory/forecast-summary/batch',
+    method: 'delete',
+    data: ids
+  })
+}
+
+/**
+ * 审批预测汇总
+ * @param {Object} data - 审批数据
+ * @param {string|number} data.id - 预测汇总ID
+ * @param {number} data.approvalStatus - 审批状态 1-通过 2-拒绝
+ * @param {string} [data.approvalComment] - 审批意见
+ * @returns {Promise<import('../types/forecast').ForecastSummaryOperationResponse>} 审批预测汇总响应
+ * @description 审批销售预测汇总记录
+ * @example
+ * const result = await approveForecastSummary({ id: '1954819531796865026', approvalStatus: 1, approvalComment: '同意申报' })
+ */
+export const approveForecastSummary = async (data) => {
+  return request({
+    url: '/api/blade-factory/api/factory/forecast-summary/approve',
+    method: 'post',
+    data
+  })
+}

+ 60 - 102
src/api/forecast/index.js

@@ -1,107 +1,15 @@
 import request from '@/router/axios'
 
-/**
- * 预测申报查询参数类型定义
- * @typedef {Object} ForecastQueryParams
- * @property {number} [current=1] - 当前页码
- * @property {number} [size=10] - 每页数量
- * @property {number} [year] - 年份
- * @property {number} [month] - 月份
- * @property {number} [customerId] - 客户ID
- * @property {string} [customerCode] - 客户编码
- * @property {string} [customerName] - 客户名称
- * @property {number} [brandId] - 品牌ID
- * @property {number} [itemId] - 物料ID
- * @property {number} [approvalStatus] - 审批状态
- */
-
-/**
- * 预测申报数据项类型定义
- * @typedef {Object} ForecastItem
- * @property {string} id - 预测申报ID
- * @property {string} createUser - 创建用户ID
- * @property {string} createDept - 创建部门ID
- * @property {string} createTime - 创建时间
- * @property {string} updateUser - 更新用户ID
- * @property {string} updateTime - 更新时间
- * @property {number} status - 状态
- * @property {number} isDeleted - 是否删除
- * @property {string} forecastCode - 预测编码
- * @property {number} year - 年份
- * @property {number} month - 月份
- * @property {number} customerId - 客户ID
- * @property {string} customerCode - 客户编码
- * @property {string} customerName - 客户名称
- * @property {number} brandId - 品牌ID
- * @property {string} brandCode - 品牌编码
- * @property {string} brandName - 品牌名称
- * @property {number} itemId - 物料ID
- * @property {string} itemCode - 物料编码
- * @property {string} itemName - 物料名称
- * @property {string} specs - 规格
- * @property {string} forecastQuantity - 预测数量
- * @property {string} currentInventory - 当前库存
- * @property {number} approvalStatus - 审批状态 0未审批 1已通过 2已拒绝
- * @property {number|null} approvedBy - 审批人ID
- * @property {string|null} approvedName - 审批人姓名
- * @property {string|null} approvedTime - 审批时间
- */
-
-/**
- * 预测申报表单数据类型定义
- * @typedef {Object} ForecastFormData
- * @property {string} [id] - 预测申报ID(修改时必需)
- * @property {string} forecastCode - 预测编码
- * @property {number} year - 年份
- * @property {number} month - 月份
- * @property {number} customerId - 客户ID
- * @property {string} customerCode - 客户编码
- * @property {string} customerName - 客户名称
- * @property {number} brandId - 品牌ID
- * @property {string} brandCode - 品牌编码
- * @property {string} brandName - 品牌名称
- * @property {number} itemId - 物料ID
- * @property {string} itemCode - 物料编码
- * @property {string} itemName - 物料名称
- * @property {string} specs - 规格
- * @property {number} forecastQuantity - 预测数量
- * @property {number} currentInventory - 当前库存
- * @property {number} approvalStatus - 审批状态
- * @property {number} [approvedBy] - 审批人ID
- * @property {string} [approvedName] - 审批人姓名
- * @property {string} [approvedTime] - 审批时间
- */
-
-/**
- * 分页响应数据类型定义
- * @typedef {Object} ForecastPageResponse
- * @property {ForecastItem[]} records - 预测申报数据记录
- * @property {number} total - 总记录数
- * @property {number} size - 每页数量
- * @property {number} current - 当前页码
- * @property {Array} orders - 排序信息
- * @property {boolean} optimizeCountSql - 是否优化count查询
- * @property {boolean} hitCount - 是否命中count缓存
- * @property {string|null} countId - count查询ID
- * @property {number|null} maxLimit - 最大限制
- * @property {boolean} searchCount - 是否查询count
- * @property {number} pages - 总页数
- */
-
-/**
- * API响应数据类型定义
- * @typedef {Object} ApiResponse
- * @property {number} code - 响应码
- * @property {string} statusText - 响应消息
- * @property {T} data - 响应数据
- */
+// 导入类型定义
+// import '../types/forecast'
+// 导入类型定义
 
 /**
  * 获取预测申报列表
  * @param {number} [current=1] - 当前页码
  * @param {number} [size=10] - 每页数量
- * @param {ForecastQueryParams} [params={}] - 查询参数
- * @returns {Promise<AxiosResponse<{records: ForecastItem[], total: number, size: number, current: number}>>} 分页查询结果响应
+ * @param {import('../types/forecast').ForecastQueryParams} [params={}] - 查询参数
+ * @returns {Promise<import('../types/forecast').ForecastListResponse>} 分页查询结果响应
  * @description 分页查询经销商销售预测申报列表,支持多种筛选条件
  * @example
  * // 基础查询
@@ -127,8 +35,8 @@ export const getForecastList = async (current = 1, size = 10, params = {}) => {
 
 /**
  * 添加预测申报
- * @param {ForecastFormData} data - 预测申报表单数据
- * @returns {Promise<AxiosResponse<boolean>>} 添加结果响应
+ * @param {import('../types/forecast').ForecastForm} data - 预测申报表单数据
+ * @returns {Promise<import('../types/forecast').ForecastOperationResponse>} 添加结果响应
  * @description 创建新的经销商销售预测申报记录
  * @example
  * const formData = {
@@ -161,8 +69,8 @@ export const addForecast = async (data) => {
 
 /**
  * 修改预测申报
- * @param {ForecastFormData} data - 预测申报表单数据(必须包含id)
- * @returns {Promise<AxiosResponse<boolean>>} 修改结果响应
+ * @param {import('../types/forecast').ForecastForm} data - 预测申报表单数据(必须包含id)
+ * @returns {Promise<import('../types/forecast').ForecastOperationResponse>} 修改结果响应
  * @description 更新现有的经销商销售预测申报记录,只有未审批状态的记录可以修改
  * @example
  * const formData = {
@@ -200,7 +108,7 @@ export const updateForecast = async (data) => {
 /**
  * 获取预测申报详情
  * @param {string|number} id - 预测申报ID
- * @returns {Promise<AxiosResponse<ForecastItem>>} 预测申报详情响应
+ * @returns {Promise<import('../types/forecast').ForecastOperationResponse>} 预测申报详情响应
  * @description 根据ID获取预测申报的详细信息
  * @example
  * const result = await getForecastDetail('1954789198347063298')
@@ -211,3 +119,53 @@ export const getForecastDetail = async (id) => {
     method: 'get'
   })
 }
+
+/**
+ * 删除预测申报
+ * @param {string|number} id - 预测申报ID
+ * @returns {Promise<import('../types/forecast').ForecastOperationResponse>} 删除结果响应
+ * @description 根据ID删除预测申报记录
+ * @example
+ * const result = await removeForecast('1954789198347063298')
+ */
+export const removeForecast = async (id) => {
+  return request({
+    url: `/api/blade-factory/api/factory/forecast/${id}`,
+    method: 'delete'
+  })
+}
+
+/**
+ * 批量删除预测申报
+ * @param {Array<string|number>} ids - 预测申报ID数组
+ * @returns {Promise<import('../types/forecast').ForecastBatchOperationResponse>} 批量删除结果响应
+ * @description 批量删除多个预测申报记录
+ * @example
+ * const result = await batchRemoveForecast(['1954789198347063298', '1954789198347063299'])
+ */
+export const batchRemoveForecast = async (ids) => {
+  return request({
+    url: '/api/blade-factory/api/factory/forecast/batch',
+    method: 'delete',
+    data: ids
+  })
+}
+
+/**
+ * 审批预测申报
+ * @param {Object} data - 审批数据
+ * @param {string|number} data.id - 预测申报ID
+ * @param {number} data.approvalStatus - 审批状态 1-通过 2-拒绝
+ * @param {string} [data.approvalComment] - 审批意见
+ * @returns {Promise<import('../types/forecast').ForecastOperationResponse>} 审批结果响应
+ * @description 审批预测申报记录
+ * @example
+ * const result = await approveForecast({ id: '1954789198347063298', approvalStatus: 1, approvalComment: '同意申报' })
+ */
+export const approveForecast = async (data) => {
+  return request({
+    url: '/api/blade-factory/api/factory/forecast/approve',
+    method: 'post',
+    data
+  })
+}

+ 322 - 0
src/api/types/forecast.d.ts

@@ -0,0 +1,322 @@
+/**
+ * 销售预测相关类型定义
+ * @description 为销售预测相关组件提供完整的TypeScript类型支持
+ */
+
+import { AxiosResponse } from 'axios';
+import { APPROVAL_STATUS } from '@/constants/forecast';
+
+/**
+ * 审批状态枚举
+ */
+export type ApprovalStatus = typeof APPROVAL_STATUS[keyof typeof APPROVAL_STATUS];
+
+/**
+ * 基础实体接口
+ */
+export interface BaseEntity {
+  /** 唯一标识 */
+  id: string | number;
+  /** 创建人 */
+  createBy?: string | number;
+  /** 创建人姓名 */
+  createName?: string;
+  /** 创建时间 */
+  createTime?: string;
+  /** 更新人 */
+  updateBy?: string | number;
+  /** 更新人姓名 */
+  updateName?: string;
+  /** 更新时间 */
+  updateTime?: string;
+}
+
+/**
+ * 基础查询参数接口
+ */
+export interface BaseQueryParams {
+  /** 当前页码 */
+  current?: number;
+  /** 每页大小 */
+  size?: number;
+  /** 排序字段 */
+  orderBy?: string;
+  /** 排序方向 */
+  orderDirection?: 'asc' | 'desc';
+}
+
+/**
+ * 分页结果接口
+ */
+export interface PageResult<T> {
+  /** 数据列表 */
+  records: T[];
+  /** 当前页码 */
+  current: number;
+  /** 每页大小 */
+  size: number;
+  /** 总记录数 */
+  total: number;
+  /** 总页数 */
+  pages: number;
+}
+
+/**
+ * API响应接口
+ */
+export interface ApiResponse<T = any> {
+  /** 响应状态码 */
+  code: number;
+  /** 响应消息 */
+  message: string;
+  /** 响应数据 */
+  data: T;
+  /** 是否成功 */
+  success?: boolean;
+  /** 时间戳 */
+  timestamp?: number;
+}
+
+/**
+ * 销售预测查询参数接口
+ */
+export interface ForecastQueryParams extends BaseQueryParams {
+  /** 预测编号 */
+  forecastCode?: string;
+  /** 年份 */
+  year?: number;
+  /** 月份 */
+  month?: number;
+  /** 客户ID */
+  customerId?: number;
+  /** 经销商编码 */
+  customerCode?: string;
+  /** 经销商名称 */
+  customerName?: string;
+  /** 品牌ID */
+  brandId?: number;
+  /** 品牌编码 */
+  brandCode?: string;
+  /** 品牌名称 */
+  brandName?: string;
+  /** 物料ID */
+  itemId?: number;
+  /** 物料编码 */
+  itemCode?: string;
+  /** 物料名称 */
+  itemName?: string;
+  /** 审批状态 */
+  approvalStatus?: ApprovalStatus;
+  /** 开始月份 */
+  startMonth?: string;
+  /** 结束月份 */
+  endMonth?: string;
+  /** 开始日期 */
+  startDate?: string;
+  /** 结束日期 */
+  endDate?: string;
+}
+
+/**
+ * 销售预测汇总查询参数接口
+ */
+export interface ForecastSummaryQueryParams extends BaseQueryParams {
+  /** 年份 */
+  year?: number;
+  /** 月份 */
+  month?: number;
+  /** 客户ID */
+  customerId?: number;
+  /** 客户编码 */
+  customerCode?: string;
+  /** 客户名称 */
+  customerName?: string;
+  /** 品牌ID */
+  brandId?: number;
+  /** 品牌编码 */
+  brandCode?: string;
+  /** 品牌名称 */
+  brandName?: string;
+  /** 物料ID */
+  itemId?: number;
+  /** 物料编码 */
+  itemCode?: string;
+  /** 物料名称 */
+  itemName?: string;
+  /** 审批状态 */
+  approvalStatus?: ApprovalStatus;
+}
+
+/**
+ * 销售预测数据项接口
+ */
+export interface ForecastItem extends BaseEntity {
+  /** 预测编码 */
+  forecastCode: string;
+  /** 年份 */
+  year: number;
+  /** 月份 */
+  month: number;
+  /** 客户ID */
+  customerId: number;
+  /** 客户编码 */
+  customerCode: string;
+  /** 客户名称 */
+  customerName: string;
+  /** 品牌ID */
+  brandId: number;
+  /** 品牌编码 */
+  brandCode: string;
+  /** 品牌名称 */
+  brandName: string;
+  /** 物料ID */
+  itemId: number;
+  /** 物料编码 */
+  itemCode: string;
+  /** 物料名称 */
+  itemName: string;
+  /** 规格 */
+  specs: string;
+  /** 预测数量 */
+  forecastQuantity: string;
+  /** 当前库存 */
+  currentInventory: string;
+  /** 审批状态 */
+  approvalStatus: number;
+  /** 审批人ID */
+  approvedBy?: number;
+  /** 审批人姓名 */
+  approvedName?: string;
+  /** 审批时间 */
+  approvedTime?: string;
+}
+
+/**
+ * 销售预测表单数据接口
+ */
+export interface ForecastForm {
+  /** 预测记录ID */
+  id?: string | number;
+  /** 预测编号 */
+  forecastCode: string;
+  /** 年份 */
+  year: number;
+  /** 月份 */
+  month: number;
+  /** 经销商ID */
+  customerId: string | number;
+  /** 经销商编码 */
+  customerCode: string;
+  /** 经销商名称 */
+  customerName: string;
+  /** 品牌ID */
+  brandId: string | number;
+  /** 品牌编码 */
+  brandCode: string;
+  /** 品牌名称 */
+  brandName: string;
+  /** 物料ID */
+  itemId: string | number;
+  /** 物料编码 */
+  itemCode: string;
+  /** 物料名称 */
+  itemName: string;
+  /** 规格 */
+  specs: string;
+  /** 预测销售量 */
+  forecastQuantity: number;
+  /** 当前库存量 */
+  currentInventory: number;
+  /** 审批状态 */
+  approvalStatus: ApprovalStatus;
+  /** 审批人ID */
+  approvedBy?: string | number;
+  /** 审批人姓名 */
+  approvedName?: string;
+  /** 审批时间 */
+  approvedTime?: string;
+}
+
+/**
+ * 销售预测记录接口
+ */
+export interface ForecastRecord extends ForecastForm, BaseEntity {}
+
+/**
+ * 销售预测汇总表单数据接口
+ */
+export interface ForecastSummaryForm {
+  /** 预测汇总ID */
+  id?: string | number;
+  /** 年份 */
+  year: number;
+  /** 月份 */
+  month: number;
+  /** 经销商ID */
+  customerId: string | number;
+  /** 经销商编码 */
+  customerCode: string;
+  /** 经销商名称 */
+  customerName: string;
+  /** 品牌ID */
+  brandId: string | number;
+  /** 品牌编码 */
+  brandCode: string;
+  /** 品牌名称 */
+  brandName: string;
+  /** 物料ID */
+  itemId: string | number;
+  /** 物料编码 */
+  itemCode: string;
+  /** 物料名称 */
+  itemName: string;
+  /** 规格 */
+  specs: string;
+  /** 花纹 */
+  pattern: string;
+  /** 预测数量 */
+  forecastQuantity: number;
+  /** 审批状态 */
+  approvalStatus: ApprovalStatus;
+  /** 审批人ID */
+  approvedBy?: string | number;
+  /** 审批人姓名 */
+  approvedName?: string;
+  /** 审批时间 */
+  approvedTime?: string;
+}
+
+/**
+ * 销售预测汇总记录接口
+ */
+export interface ForecastSummaryRecord extends ForecastSummaryForm, BaseEntity {}
+
+/**
+ * 销售预测操作响应接口
+ */
+export type ForecastOperationResponse = AxiosResponse<ApiResponse<ForecastRecord>>;
+
+/**
+ * 销售预测列表响应接口
+ */
+export type ForecastListResponse = AxiosResponse<ApiResponse<PageResult<ForecastRecord>>>;
+
+/**
+ * 销售预测汇总操作响应接口
+ */
+export type ForecastSummaryOperationResponse = AxiosResponse<ApiResponse<ForecastSummaryRecord>>;
+
+/**
+ * 销售预测汇总列表响应接口
+ */
+export type ForecastSummaryListResponse = AxiosResponse<ApiResponse<PageResult<ForecastSummaryRecord>>>;
+
+/**
+ * 销售预测批量操作响应接口
+ */
+export type ForecastBatchOperationResponse = AxiosResponse<ApiResponse<boolean>>;
+
+/**
+ * 销售预测汇总批量操作响应接口
+ */
+export type ForecastSummaryBatchOperationResponse = AxiosResponse<ApiResponse<boolean>>;

+ 63 - 6
src/constants/forecast.js

@@ -6,16 +6,15 @@
 /**
  * 审批状态枚举
  * @readonly
- * @enum {number}
  */
-export const APPROVAL_STATUS = {
+export const APPROVAL_STATUS = Object.freeze({
   /** 未审批 */
   PENDING: 0,
   /** 已通过 */
   APPROVED: 1,
   /** 已拒绝 */
   REJECTED: 2
-}
+})
 
 /**
  * 审批状态配置映射
@@ -193,15 +192,15 @@ export const AUDIT_ACTION_CONFIG = {
  */
 export function getAvailableAuditActions(approvalStatus) {
   const actions = [AUDIT_ACTION_TYPE.VIEW]
-  
+
   if (canApprove(approvalStatus)) {
     actions.push(AUDIT_ACTION_TYPE.APPROVE)
   }
-  
+
   if (canReject(approvalStatus)) {
     actions.push(AUDIT_ACTION_TYPE.REJECT)
   }
-  
+
   return actions
 }
 
@@ -506,3 +505,61 @@ export function formatYearMonth(year, month) {
 export function isReadOnlyMode() {
   return true
 }
+
+/**
+ * 销售预测汇总表单验证规则
+ * @readonly
+ * @type {Object}
+ */
+export const FORECAST_SUMMARY_FORM_RULES = {
+  year: [
+    { required: true, message: '请选择年份', trigger: 'change' }
+  ],
+  month: [
+    { required: true, message: '请选择月份', trigger: 'change' }
+  ],
+  customerId: [
+    { required: true, message: '请选择经销商', trigger: 'change' }
+  ],
+  brandId: [
+    { required: true, message: '请选择品牌', trigger: 'change' }
+  ],
+  itemId: [
+    { required: true, message: '请选择物料', trigger: 'change' }
+  ],
+  forecastQuantity: [
+    { required: true, message: '请输入预测数量', trigger: 'blur' },
+    { type: 'number', message: '预测数量必须为数字', trigger: 'blur' },
+    { validator: (rule, value, callback) => {
+      if (value < 0) {
+        callback(new Error('预测数量不能小于0'))
+      } else {
+        callback()
+      }
+    }, trigger: 'blur' }
+  ]
+}
+
+/**
+ * 销售预测汇总默认表单数据
+ * @readonly
+ * @type {Object}
+ */
+export const DEFAULT_FORECAST_SUMMARY_FORM = {
+  id: null,
+  year: new Date().getFullYear(),
+  month: new Date().getMonth() + 1,
+  customerId: null,
+  customerCode: '',
+  customerName: '',
+  brandId: null,
+  brandCode: '',
+  brandName: '',
+  itemId: null,
+  itemCode: '',
+  itemName: '',
+  specs: '',
+  pattern: '',
+  forecastQuantity: 0,
+  approvalStatus: APPROVAL_STATUS.PENDING
+}