|
|
@@ -0,0 +1,539 @@
|
|
|
+import { add, update, getDetail } from '@/api/order/order'
|
|
|
+import {
|
|
|
+ ORDER_TYPES,
|
|
|
+ ORDER_STATUS,
|
|
|
+ ORDER_TYPE_OPTIONS,
|
|
|
+ ORDER_STATUS_OPTIONS
|
|
|
+} from '@/constants/order'
|
|
|
+
|
|
|
+/**
|
|
|
+ * @typedef {Object} OrderFormModel
|
|
|
+ * @property {string|number|null} id - 订单唯一标识
|
|
|
+ * @property {string} orderCode - 订单编码
|
|
|
+ * @property {string} orgCode - 组织编码
|
|
|
+ * @property {string} orgName - 组织名称
|
|
|
+ * @property {string} customerCode - 客户编码
|
|
|
+ * @property {string} customerName - 客户名称
|
|
|
+ * @property {number} orderType - 订单类型
|
|
|
+ * @property {number|null} totalAmount - 订单总金额
|
|
|
+ * @property {number|null} totalQuantity - 订单总数量
|
|
|
+ * @property {string} receiverName - 收货人姓名
|
|
|
+ * @property {string} receiverPhone - 收货人电话
|
|
|
+ * @property {string} receiverAddress - 收货地址
|
|
|
+ * @property {number} status - 订单状态
|
|
|
+ * @property {string} remark - 备注信息
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @typedef {Object} ValidationRule
|
|
|
+ * @property {boolean} [required] - 是否必填
|
|
|
+ * @property {string} [message] - 验证失败提示信息
|
|
|
+ * @property {string} [trigger] - 触发验证的事件
|
|
|
+ * @property {number} [min] - 最小长度
|
|
|
+ * @property {number} [max] - 最大长度
|
|
|
+ * @property {string} [type] - 数据类型
|
|
|
+ * @property {number} [minimum] - 最小值
|
|
|
+ * @property {number} [maximum] - 最大值
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @typedef {Object.<string, ValidationRule[]>} OrderFormRules
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @typedef {Object} ApiResponse
|
|
|
+ * @property {number} code - 响应状态码
|
|
|
+ * @property {string} message - 响应消息
|
|
|
+ * @property {*} data - 响应数据
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @typedef {Object} OrderSelectOption
|
|
|
+ * @property {string} label - 显示标签
|
|
|
+ * @property {number} value - 选项值
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * 订单表单混入组件
|
|
|
+ * @description 提供订单表单的数据管理、验证规则和业务逻辑的混入组件
|
|
|
+ * @author 系统开发团队
|
|
|
+ * @version 2.0.0
|
|
|
+ * @since 2024-01-15
|
|
|
+ * @mixin
|
|
|
+ */
|
|
|
+export default {
|
|
|
+ /**
|
|
|
+ * 组件响应式数据
|
|
|
+ * @description 定义组件的响应式数据状态
|
|
|
+ * @returns {Object} 组件数据对象
|
|
|
+ */
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ /**
|
|
|
+ * 订单表单数据模型
|
|
|
+ * @description 存储订单表单的所有字段数据
|
|
|
+ * @type {OrderFormModel}
|
|
|
+ */
|
|
|
+ formData: this.createInitialFormData(),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存操作加载状态
|
|
|
+ * @description 控制保存按钮的加载状态,防止重复提交
|
|
|
+ * @type {boolean}
|
|
|
+ */
|
|
|
+ saveLoading: false,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单类型选项列表
|
|
|
+ * @description 订单类型下拉选择器的选项数据
|
|
|
+ * @type {OrderSelectOption[]}
|
|
|
+ */
|
|
|
+ orderTypeOptions: Object.freeze([...ORDER_TYPE_OPTIONS]),
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单状态选项列表
|
|
|
+ * @description 订单状态下拉选择器的选项数据
|
|
|
+ * @type {OrderSelectOption[]}
|
|
|
+ */
|
|
|
+ orderStatusOptions: Object.freeze([...ORDER_STATUS_OPTIONS])
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算属性
|
|
|
+ * @description 组件的响应式计算属性
|
|
|
+ */
|
|
|
+ computed: {
|
|
|
+ /**
|
|
|
+ * 订单表单验证规则
|
|
|
+ * @description 定义订单表单各字段的验证规则,支持必填、长度、格式等验证
|
|
|
+ * @returns {OrderFormRules} 完整的表单验证规则对象
|
|
|
+ */
|
|
|
+ formRules() {
|
|
|
+ return {
|
|
|
+ orderCode: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入订单编码',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ min: 3,
|
|
|
+ max: 50,
|
|
|
+ message: '订单编码长度在 3 到 50 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ orgCode: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入组织编码',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ min: 2,
|
|
|
+ max: 20,
|
|
|
+ message: '组织编码长度在 2 到 20 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ orgName: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入组织名称',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ min: 2,
|
|
|
+ max: 100,
|
|
|
+ message: '组织名称长度在 2 到 100 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ customerCode: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入客户编码',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ min: 3,
|
|
|
+ max: 50,
|
|
|
+ message: '客户编码长度在 3 到 50 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ customerName: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入客户名称',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ min: 2,
|
|
|
+ max: 100,
|
|
|
+ message: '客户名称长度在 2 到 100 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ orderType: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请选择订单类型',
|
|
|
+ trigger: 'change'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ totalAmount: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入订单总金额',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'number',
|
|
|
+ min: 0.01,
|
|
|
+ message: '订单总金额必须大于0',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ totalQuantity: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入订单总数量',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'number',
|
|
|
+ min: 0.0001,
|
|
|
+ message: '订单总数量必须大于0',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ receiverName: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入收货人姓名',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ min: 2,
|
|
|
+ max: 50,
|
|
|
+ message: '收货人姓名长度在 2 到 50 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ receiverPhone: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入收货人电话',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ pattern: /^1[3-9]\d{9}$/,
|
|
|
+ message: '请输入正确的手机号码',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ receiverAddress: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入收货地址',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ min: 5,
|
|
|
+ max: 500,
|
|
|
+ message: '收货地址长度在 5 到 500 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ remark: [
|
|
|
+ {
|
|
|
+ max: 1000,
|
|
|
+ message: '备注信息不能超过 1000 个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 组件方法
|
|
|
+ * @description 组件的业务逻辑方法集合
|
|
|
+ */
|
|
|
+ methods: {
|
|
|
+ /**
|
|
|
+ * 创建初始表单数据
|
|
|
+ * @description 创建订单表单的初始数据结构
|
|
|
+ * @returns {OrderFormModel} 初始化的表单数据对象
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ createInitialFormData() {
|
|
|
+ return {
|
|
|
+ id: null,
|
|
|
+ orderCode: '',
|
|
|
+ orgCode: '',
|
|
|
+ orgName: '',
|
|
|
+ customerCode: '',
|
|
|
+ customerName: '',
|
|
|
+ orderType: ORDER_TYPES.NORMAL,
|
|
|
+ totalAmount: null,
|
|
|
+ totalQuantity: null,
|
|
|
+ receiverName: '',
|
|
|
+ receiverPhone: '',
|
|
|
+ receiverAddress: '',
|
|
|
+ status: ORDER_STATUS.DRAFT,
|
|
|
+ remark: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化表单数据
|
|
|
+ * @description 根据编辑模式初始化表单,编辑模式加载数据,新增模式重置表单
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ * @public
|
|
|
+ */
|
|
|
+ async initForm() {
|
|
|
+ try {
|
|
|
+ if (this.isEdit && this.orderId) {
|
|
|
+ await this.loadOrderDetail(this.orderId)
|
|
|
+ } else {
|
|
|
+ this.resetForm()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('初始化表单失败:', error)
|
|
|
+ this.$message.error('初始化表单失败,请刷新页面重试')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重置表单数据
|
|
|
+ * @description 将表单数据重置为初始状态,并清除所有验证错误信息
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ * @public
|
|
|
+ */
|
|
|
+ async resetForm() {
|
|
|
+ try {
|
|
|
+ // 重置表单数据为初始状态
|
|
|
+ this.formData = this.createInitialFormData()
|
|
|
+
|
|
|
+ // 等待DOM更新后清除表单验证
|
|
|
+ await this.$nextTick()
|
|
|
+
|
|
|
+ if (this.$refs.orderForm && typeof this.$refs.orderForm.clearValidate === 'function') {
|
|
|
+ this.$refs.orderForm.clearValidate()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.warn('重置表单时发生错误:', error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加载订单详情数据
|
|
|
+ * @description 根据订单ID从服务器获取订单详情并填充到表单中
|
|
|
+ * @param {string|number} orderId - 订单唯一标识
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ * @throws {Error} 当API调用失败或数据格式错误时抛出异常
|
|
|
+ * @public
|
|
|
+ */
|
|
|
+ async loadOrderDetail(orderId) {
|
|
|
+ if (!orderId) {
|
|
|
+ throw new Error('订单ID不能为空')
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await getDetail(orderId)
|
|
|
+
|
|
|
+ if (!response || !response.data || !response.data.data) {
|
|
|
+ throw new Error('服务器返回数据格式错误')
|
|
|
+ }
|
|
|
+
|
|
|
+ const orderData = response.data.data
|
|
|
+
|
|
|
+ // 安全地映射订单数据到表单,确保数据类型正确
|
|
|
+ this.formData = this.mapOrderDataToForm(orderData)
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ const errorMessage = error.message || '加载订单详情失败'
|
|
|
+ console.error('加载订单详情失败:', error)
|
|
|
+ this.$message.error(`${errorMessage},请重试`)
|
|
|
+ throw error
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 映射订单数据到表单格式
|
|
|
+ * @description 将API返回的订单数据安全地映射为表单数据格式
|
|
|
+ * @param {Object} orderData - 从API获取的原始订单数据
|
|
|
+ * @returns {OrderFormModel} 格式化后的表单数据
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ mapOrderDataToForm(orderData) {
|
|
|
+ return {
|
|
|
+ id: orderData.id || null,
|
|
|
+ orderCode: String(orderData.orderCode || ''),
|
|
|
+ orgCode: String(orderData.orgCode || ''),
|
|
|
+ orgName: String(orderData.orgName || ''),
|
|
|
+ customerCode: String(orderData.customerCode || ''),
|
|
|
+ customerName: String(orderData.customerName || ''),
|
|
|
+ orderType: Number(orderData.orderType) || ORDER_TYPES.NORMAL,
|
|
|
+ totalAmount: orderData.totalAmount ? Number(orderData.totalAmount) : null,
|
|
|
+ totalQuantity: orderData.totalQuantity ? Number(orderData.totalQuantity) : null,
|
|
|
+ receiverName: String(orderData.receiverName || ''),
|
|
|
+ receiverPhone: String(orderData.receiverPhone || ''),
|
|
|
+ receiverAddress: String(orderData.receiverAddress || ''),
|
|
|
+ status: Number(orderData.status) || ORDER_STATUS.DRAFT,
|
|
|
+ remark: String(orderData.remark || '')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理返回列表操作
|
|
|
+ * @description 触发返回列表事件,通知父组件关闭表单
|
|
|
+ * @returns {void}
|
|
|
+ * @public
|
|
|
+ * @emits back 返回列表事件
|
|
|
+ */
|
|
|
+ handleBack() {
|
|
|
+ /**
|
|
|
+ * 返回列表事件
|
|
|
+ * @event back
|
|
|
+ * @description 用户点击返回按钮时触发
|
|
|
+ */
|
|
|
+ this.$emit('back')
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理表单保存操作
|
|
|
+ * @description 验证表单数据并提交到服务器,支持新增和编辑模式
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ * @throws {Error} 当表单验证失败或API调用失败时抛出异常
|
|
|
+ * @public
|
|
|
+ * @emits save-success 保存成功事件
|
|
|
+ */
|
|
|
+ async handleSave() {
|
|
|
+ if (this.saveLoading) {
|
|
|
+ return // 防止重复提交
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 表单验证
|
|
|
+ const isValid = await this.validateForm()
|
|
|
+ if (!isValid) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ this.saveLoading = true
|
|
|
+
|
|
|
+ // 准备提交数据
|
|
|
+ const submitData = this.prepareSubmitData()
|
|
|
+
|
|
|
+ // 调用相应的API
|
|
|
+ const response = await this.submitOrderData(submitData)
|
|
|
+
|
|
|
+ // 显示成功提示
|
|
|
+ const successMessage = this.isEdit ? '订单更新成功' : '订单创建成功'
|
|
|
+ this.$message.success(successMessage)
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存成功事件
|
|
|
+ * @event save-success
|
|
|
+ * @param {Object} data - 保存后的订单数据
|
|
|
+ * @description 订单保存成功后触发,携带最新的订单数据
|
|
|
+ */
|
|
|
+ this.$emit('save-success', response.data.data)
|
|
|
+
|
|
|
+ // 返回列表
|
|
|
+ this.handleBack()
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ const errorMessage = this.isEdit ? '订单更新失败,请重试' : '订单创建失败,请重试'
|
|
|
+ console.error('保存订单失败:', error)
|
|
|
+ this.$message.error(errorMessage)
|
|
|
+ throw error
|
|
|
+ } finally {
|
|
|
+ this.saveLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 提交订单数据到服务器
|
|
|
+ * @description 根据编辑模式调用相应的API接口
|
|
|
+ * @param {Object} submitData - 要提交的订单数据
|
|
|
+ * @returns {Promise<ApiResponse>} API响应结果
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ async submitOrderData(submitData) {
|
|
|
+ if (this.isEdit) {
|
|
|
+ return await update(submitData)
|
|
|
+ } else {
|
|
|
+ return await add(submitData)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证表单数据
|
|
|
+ * @description 使用AvueJS表单的验证功能验证所有字段
|
|
|
+ * @returns {Promise<boolean>} 验证结果,true表示验证通过,false表示验证失败
|
|
|
+ * @public
|
|
|
+ */
|
|
|
+ async validateForm() {
|
|
|
+ if (!this.$refs.orderForm) {
|
|
|
+ console.warn('表单引用不存在,无法进行验证')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const valid = await this.$refs.orderForm.validate()
|
|
|
+ return Boolean(valid)
|
|
|
+ } catch (error) {
|
|
|
+ console.warn('表单验证失败:', error)
|
|
|
+ this.$message.warning('请检查表单填写是否正确')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 准备提交数据
|
|
|
+ * @description 处理表单数据,移除空值字段并确保数据类型正确
|
|
|
+ * @returns {Object} 格式化后的提交数据对象
|
|
|
+ * @public
|
|
|
+ */
|
|
|
+ prepareSubmitData() {
|
|
|
+ const submitData = { ...this.formData }
|
|
|
+
|
|
|
+ // 清理和格式化数据
|
|
|
+ return this.cleanAndFormatSubmitData(submitData)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清理和格式化提交数据
|
|
|
+ * @description 移除空值字段并确保数据类型正确
|
|
|
+ * @param {OrderFormModel} data - 原始表单数据
|
|
|
+ * @returns {Object} 清理后的数据对象
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ cleanAndFormatSubmitData(data) {
|
|
|
+ const cleanedData = {}
|
|
|
+
|
|
|
+ Object.keys(data).forEach(key => {
|
|
|
+ const value = data[key]
|
|
|
+
|
|
|
+ // 跳过null、undefined和空字符串,但保留备注字段
|
|
|
+ if (value === null || value === undefined || (value === '' && key !== 'remark')) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保数字类型字段的正确性
|
|
|
+ if (['totalAmount', 'totalQuantity', 'orderType', 'status'].includes(key)) {
|
|
|
+ cleanedData[key] = Number(value) || 0
|
|
|
+ } else {
|
|
|
+ cleanedData[key] = value
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return cleanedData
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|