Просмотр исходного кода

refactor(订单地址管理): 重构订单地址管理组件,提取mixin并优化类型定义

yz 2 месяцев назад
Родитель
Сommit
259e894d6e

+ 2 - 4
src/api/order/address.js

@@ -61,15 +61,13 @@ export const getDetail = async (id) => {
 
 /**
  * 获取客户地址列表
- * @param {string|number} customerId - 客户ID
  * @returns {Promise<import('../types/address').CustomerAddressFullListResponse>} 客户地址列表
  */
-export const getAddressList = async (customerId) => {
+export const getAddressList = async () => {
   return request({
     url: '/api/blade-factory/api/factory/salesOrder/getAddressList',
     method: 'get',
     params: {
-      customerId
     }
   })
 }
@@ -130,4 +128,4 @@ export const deleteAddress = async (id) => {
       id
     }
   })
-}
+}

+ 619 - 0
src/views/order/address/addressMixin.js

@@ -0,0 +1,619 @@
+import { getList, getAddressList, add, update, getDetail } from '@/api/order/address'
+import { getCustomerList } from '@/api/common/index'
+import { mapGetters } from 'vuex'
+import RegionCascader from '@/components/region-cascader/index.vue'
+// @ts-check
+
+/**
+ * @typedef {import('./types').OrderAddressMixinComponent} OrderAddressMixinComponent
+ * @typedef {import('./types').CustomerAddressForm} CustomerAddressForm
+ * @typedef {import('./types').CustomerAddressQueryParams} CustomerAddressQueryParams
+ * @typedef {import('./types').CustomerAddressItem} CustomerAddressItem
+ * @typedef {import('./types').RegionData} RegionData
+ */
+
+export default {
+  name: 'OrderAddress',
+  components: {
+    RegionCascader
+  },
+  /**
+   * @returns {Object}
+   */
+  data() {
+    return {
+      customerOptions: [],
+      customerLoading: false,
+      customerSearchKeyword: '',
+      customerSearchTimer: null,
+      form: {},
+
+      query: {},
+      loading: true,
+      regionCascaderValue: [],
+      selectionList: [],
+      data: [],
+      option: {
+        height: 'auto',
+        calcHeight: 30,
+        tip: false,
+        searchShow: true,
+        searchMenuSpan: 6,
+        border: true,
+        index: true,
+        selection: true,
+        viewBtn: true,
+        dialogClickModal: false,
+        dialogWidth: 900,
+        page: false,
+        column: [
+          {
+            label: '客户',
+            prop: 'customerId',
+            type: 'select',
+            width: 200,
+            filterable: true,
+            remote: false,
+            reserveKeyword: true,
+            placeholder: '请选择客户',
+            dicData: [],
+            props: {
+              label: 'label',
+              value: 'value'
+            },
+            rules: [
+              {
+                required: true,
+                message: '请选择客户',
+                trigger: 'change'
+              }
+            ],
+            change: 'handleCustomerChange'
+          },
+          {
+            label: '客户编码',
+            prop: 'customerCode',
+            width: 120,
+            rules: [
+              {
+                required: true,
+                message: '请输入客户编码',
+                trigger: 'blur'
+              },
+              {
+                pattern: /^[A-Z0-9_-]+$/,
+                message: '客户编码只能包含大写字母、数字、下划线和中横线',
+                trigger: 'blur'
+              },
+            ]
+
+            // addDisplay: true,
+            // editDisplay: true
+          },
+          {
+            label: '客户名称',
+            prop: 'customerName',
+            width: 200,
+            rules: [
+              {
+                required: true,
+                message: '请输入客户名称',
+                trigger: 'blur'
+              },
+              {
+                max: 50,
+                message: '客户名称不能超过50个字符',
+                trigger: 'blur'
+              }
+            ]
+
+            // addDisplay: false,
+            // editDisplay: false
+          },
+          {
+            label: '收货人姓名',
+            prop: 'receiverName',
+            search: true,
+            width: 120,
+            rules: [
+              {
+                required: true,
+                message: '请输入收货人姓名',
+                trigger: 'blur'
+              },
+            ]
+          },
+          {
+            label: '收货人电话',
+            prop: 'receiverPhone',
+            search: true,
+            width: 130,
+            rules: [
+              {
+                required: true,
+                message: '请输入收货人电话',
+                trigger: 'blur'
+              },
+              {
+                pattern: /^1[3-9]\d{9}$/,
+                message: '请输入正确的手机号码',
+                trigger: 'blur'
+              }
+            ]
+          },
+          {
+            label: '地区',
+            prop: 'regionName',
+            search: true,
+            width: 150,
+            formSlot: true, // 启用表单插槽
+            rules: [
+              {
+                required: true,
+                message: '请选择地区',
+                trigger: 'change'
+              }
+            ]
+          },
+          {
+            label: '地区编码',
+            prop: 'regionCode',
+            hide: true,
+            rules: [
+              {
+                required: true,
+                message: '请输入地区编码',
+                trigger: 'blur'
+              }
+            ]
+          },
+          {
+            label: '详细地址',
+            prop: 'detailAddress',
+            width: 250,
+            overHidden: true,
+            span: 24,
+            rules: [
+              {
+                required: true,
+                message: '请输入详细地址',
+                trigger: 'blur'
+              },
+              {
+                min: 5,
+                max: 200,
+                message: '详细地址长度在5到200个字符',
+                trigger: 'blur'
+              }
+            ]
+          },
+          {
+            label: '邮政编码',
+            prop: 'postalCode',
+            width: 100,
+            rules: [
+              {
+                pattern: /^\d{6}$/,
+                message: '请输入正确的邮政编码',
+                trigger: 'blur'
+              }
+            ]
+          },
+          {
+            label: '默认地址',
+            prop: 'isDefault',
+            type: 'select',
+            dicData: [
+              { label: '否', value: 0 },
+              { label: '是', value: 1 }
+            ],
+            search: true,
+            slot: true,
+            width: 100,
+            value: 0
+          },
+          {
+            label: '状态',
+            prop: 'isActive',
+            type: 'select',
+            dicData: [
+              { label: '禁用', value: 0 },
+              { label: '启用', value: 1 }
+            ],
+            search: true,
+            slot: true,
+            width: 100,
+            value: 1
+          },
+          {
+            label: '创建时间',
+            prop: 'createTime',
+            type: 'datetime',
+            format: 'yyyy-MM-dd HH:mm:ss',
+            valueFormat: 'yyyy-MM-dd HH:mm:ss',
+            width: 160,
+            addDisplay: false,
+            editDisplay: false
+          },
+          {
+            label: '更新时间',
+            prop: 'updateTime',
+            type: 'datetime',
+            format: 'yyyy-MM-dd HH:mm:ss',
+            valueFormat: 'yyyy-MM-dd HH:mm:ss',
+            width: 160,
+            addDisplay: false,
+            editDisplay: false
+          }
+        ]
+      }
+    }
+  },
+  computed: {
+    ...mapGetters(['permission']),
+
+    /**
+     * 权限配置
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    permissionList() {
+      return {
+        // addBtn: this.vaildData(this.permission.order_address_add, false),
+        // viewBtn: this.vaildData(this.permission.order_address_view, false),
+        // delBtn: this.vaildData(this.permission.order_address_delete, false),
+        // editBtn: this.vaildData(this.permission.order_address_edit, false)
+        addBtn: true,
+        viewBtn: true,
+        delBtn: false,
+        editBtn: true
+      }
+    },
+
+    /**
+     * 选中的ID字符串
+     * @this {OrderAddressMixinComponent & Vue}
+     * @returns {string}
+     */
+    ids() {
+      /** @type {(string|number)[]} */
+      const ids = []
+      this.selectionList.forEach(ele => {
+        ids.push(ele.id)
+      })
+      return ids.join(',')
+    }
+  },
+  methods: {
+    /**
+     * 处理客户选择变化
+     * @param {Object} params - 参数对象
+     * @param {string|number} params.value - 选中的值
+     * @param {Object} params.column - 列配置
+     * @returns {void}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    handleCustomerChange({ value, column }) {
+      if (value) {
+        const selectedCustomer = this.customerOptions.find(option => option.value === value)
+        if (selectedCustomer) {
+          // 自动填充客户信息
+          this.form.customerId = Number(selectedCustomer.customerId)
+          this.form.customerCode = selectedCustomer.customerCode
+          this.form.customerName = selectedCustomer.customerName
+        } else {
+          this.clearCustomerData()
+        }
+      } else {
+        this.clearCustomerData()
+      }
+    },
+
+    /**
+     * 加载客户选项列表
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    /**
+     * 加载客户选项
+     * @param {string} keyword - 搜索关键词
+     * @returns {Promise<void>}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    async loadCustomerOptions(keyword = '') {
+      try {
+        /** @type {Record<string, string>} */
+        const params = {}
+
+        // 如果有搜索关键词,添加到查询参数中
+        if (keyword.trim()) {
+          params['Customer_CODE'] = keyword
+          params['Customer_NAME'] = keyword
+        }
+
+        const response = await getCustomerList(1, 50, params)
+
+        if (response.data && response.data.success) {
+          const customers = response.data.data.records || []
+          this.customerOptions = customers.map(customer => ({
+            value: customer['Customer_ID'],
+            label: `${customer['Customer_CODE']} - ${customer['Customer_NAME']}`,
+            customerCode: customer['Customer_CODE'],
+            customerName: customer['Customer_NAME'],
+            customerId: String(customer['Customer_ID'])
+          }))
+
+          // 更新表格配置中的选项数据
+          this.updateCustomerOptionsInColumn()
+        } else {
+          this.customerOptions = []
+          this.$message.warning('获取客户列表失败')
+        }
+      } catch (error) {
+        this.customerOptions = []
+        console.error('加载客户选项失败:', error)
+        this.$message.error('加载客户选项失败,请稍后重试')
+      } finally {
+        this.customerLoading = false
+      }
+    },
+
+    /**
+     * 搜索客户(防抖处理)
+     * @param {string} query - 搜索查询字符串
+     * @returns {void}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    searchCustomers(query) {
+      // 清除之前的定时器
+      if (this.customerSearchTimer) {
+        clearTimeout(this.customerSearchTimer)
+      }
+
+      if (query !== '') {
+        this.customerLoading = true
+        // 设置新的定时器,300ms后执行搜索
+        this.customerSearchTimer = Number(setTimeout(() => {
+          this.loadCustomerOptions(query)
+        }, 300))
+      } else {
+        this.customerOptions = []
+      }
+    },
+
+    /**
+     * 更新表格配置中的客户选项数据
+     * @returns {void}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    updateCustomerOptionsInColumn() {
+      if (this.option && this.option.column) {
+        const customerColumn = this.option.column.find(col => col.prop === 'customerId')
+        if (customerColumn) {
+          customerColumn.dicData = this.customerOptions
+        }
+      }
+    },
+
+    /**
+     * 清除客户相关数据
+     * @returns {void}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    clearCustomerData() {
+      this.form.customerCode = ''
+      this.form.customerName = ''
+      this.form.customerId = null
+    },
+
+    /**
+     * 地区选择改变事件
+     * @param {RegionData} data - 地区数据
+     * @returns {void}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    handleRegionChange(data) {
+      const { regionName } = data
+
+      // 只设置regionName,regionCode保持独立
+      this.form.regionName = regionName
+
+      // 手动触发表单验证
+      this.$nextTick(() => {
+        /** @type {any} */
+        const crudRef = this.$refs.crud
+        if (crudRef && crudRef.$refs && crudRef.$refs.dialogForm) {
+          crudRef.$refs.dialogForm.validateField('regionName')
+        }
+      })
+    },
+
+   /**
+     * 新增前的回调
+     * @this {OrderAddressMixinComponent & Vue}
+     * @param {Function} done - 完成回调
+     * @param {string} type - 操作类型
+     * @returns {Promise<void>}
+     */
+    async beforeOpen(done, type) {
+      // 确保客户选项已加载
+      if (this.customerOptions.length === 0) {
+        await this.loadCustomerOptions()
+      }
+
+      if (['edit', 'view'].includes(type)) {
+        try {
+          if (this.form.id) {
+            const res = await getDetail(this.form.id)
+            this.form = res.data.data
+
+            // 如果有客户信息,确保客户选项中包含当前客户
+            if (this.form.customerId && this.form.customerCode && this.form.customerName) {
+              const existingCustomer = this.customerOptions.find(option => option.value === this.form.customerId?.toString())
+              if (!existingCustomer) {
+                this.customerOptions.unshift({
+                  value: this.form.customerId,
+                  label: `${this.form.customerCode} - ${this.form.customerName}`,
+                  customerCode: this.form.customerCode,
+                  customerName: this.form.customerName,
+                  customerId: String(this.form.customerId)
+                })
+                this.updateCustomerOptionsInColumn()
+              }
+            }
+          }
+        } catch (error) {
+          window.console.log(error)
+        }
+      }
+      done()
+    },
+
+    /**
+     * 获取数据
+     * @param {Record<string, any>} params - 查询参数
+     * @returns {Promise<void>}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    async onLoad(params = {}) {
+      this.loading = true
+      try {
+        // const customerId = params['customerId'] || this.query['customerId']
+        const res = await getAddressList()
+        this.data = res.data.data || []
+        this.loading = false
+        this.selectionClear()
+      } catch (error) {
+        this.loading = false
+        window.console.log(error)
+      }
+    },
+
+    /**
+     * 新增保存
+     * @this {OrderAddressMixinComponent & Vue}
+     * @param {CustomerAddressForm} row - 表单数据
+     * @param {Function} done - 完成回调
+     * @param {Function} loading - 加载状态回调
+     * @returns {Promise<void>}
+     */
+    async rowSave(row, done, loading) {
+      try {
+        // 转换为API期望的类型
+        const apiData = {
+          ...row,
+          customerId: row.customerId || 0
+        }
+        await add(apiData)
+        done()
+        this.onLoad(this.query)
+        this.$message({
+          type: 'success',
+          message: '操作成功!'
+        })
+      } catch (error) {
+        loading()
+        window.console.log(error)
+      }
+    },
+
+    /**
+     * 编辑保存
+     * @this {OrderAddressMixinComponent & Vue}
+     * @param {CustomerAddressForm} row - 表单数据
+     * @param {number} index - 行索引
+     * @param {Function} done - 完成回调
+     * @param {Function} loading - 加载状态回调
+     * @returns {Promise<void>}
+     */
+    async rowUpdate(row, index, done, loading) {
+      try {
+        // 转换为API期望的类型
+        const apiData = {
+          ...row,
+          customerId: row.customerId || 0
+        }
+        await update(apiData)
+        done()
+        this.onLoad(this.query)
+        this.$message({
+          type: 'success',
+          message: '操作成功!'
+        })
+      } catch (error) {
+        loading()
+        window.console.log(error)
+      }
+    },
+
+    /**
+     * 搜索回调
+     * @this {OrderAddressMixinComponent & Vue}
+     * @param {CustomerAddressQueryParams} params - 查询参数
+     * @param {Function} done - 完成回调
+     * @returns {void}
+     */
+    searchChange(params, done) {
+      this.query = params
+      this.onLoad(params)
+      done()
+    },
+
+    /**
+     * 搜索重置回调
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    searchReset() {
+      this.query = {}
+      this.onLoad()
+    },
+
+    /**
+     * 选择改变时的回调
+     * @this {OrderAddressMixinComponent & Vue}
+     * @param {CustomerAddressItem[]} list - 选中的项目列表
+     * @returns {void}
+     */
+    selectionChange(list) {
+      this.selectionList = list
+    },
+
+    /**
+     * 清空选中
+     * @returns {void}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    selectionClear() {
+      this.selectionList = []
+      /** @type {any} */
+      const crudRef = this.$refs.crud
+      if (crudRef && crudRef.toggleSelection) {
+        crudRef.toggleSelection()
+      }
+    },
+
+    /**
+     * 刷新回调
+     * @returns {void}
+     * @this {OrderAddressMixinComponent & Vue}
+     */
+    refreshChange() {
+      this.onLoad(this.query)
+    }
+  },
+  /**
+   * 组件创建时加载客户选项
+   * @this {OrderAddressMixinComponent & Vue}
+   */
+  async created() {
+    await this.loadCustomerOptions()
+  },
+
+  /**
+   * 组件销毁前清理定时器
+   * @this {OrderAddressMixinComponent & Vue}
+   */
+  beforeDestroy() {
+    if (this.customerSearchTimer) {
+      clearTimeout(this.customerSearchTimer)
+    }
+  }
+}

+ 5 - 718
src/views/order/address/index.vue

@@ -5,7 +5,6 @@
       :data="data"
       ref="crud"
       v-model="form"
-      :page.sync="page"
       :permission="permissionList"
       :before-open="beforeOpen"
       :table-loading="loading"
@@ -15,8 +14,6 @@
       @search-change="searchChange"
       @search-reset="searchReset"
       @selection-change="selectionChange"
-      @current-change="currentChange"
-      @size-change="sizeChange"
       @refresh-change="refreshChange"
       @on-load="onLoad"
     >
@@ -58,731 +55,21 @@
 </template>
 
 <script>
-import { getList, add, update, getDetail } from '@/api/order/address'
-import { getCustomerList } from '@/api/common/index'
-import { mapGetters } from 'vuex'
-import RegionCascader from '@/components/region-cascader'
-
-/**
- * 客户地址查询参数
- * @typedef {Object} CustomerAddressQueryParams
- * @property {string} [customerCode] - 客户编码
- * @property {string} [customerName] - 客户名称
- * @property {string} [receiverName] - 收货人姓名
- * @property {string} [receiverPhone] - 收货人电话
- * @property {string} [regionName] - 地区名称
- * @property {number} [isDefault] - 是否默认地址 0-否 1-是
- * @property {number} [isActive] - 状态 0-禁用 1-启用
- */
-
-/**
- * 客户地址表单数据
- * @typedef {Object} CustomerAddressForm
- * @property {number} [id] - 地址ID
- * @property {number} customerId - 客户ID
- * @property {string} customerCode - 客户编码
- * @property {string} customerName - 客户名称
- * @property {string} receiverName - 收货人姓名
- * @property {string} receiverPhone - 收货人电话
- * @property {string} regionCode - 地区编码
- * @property {string} regionName - 地区名称
- * @property {string} detailAddress - 详细地址
- * @property {string} [postalCode] - 邮政编码
- * @property {number} isDefault - 是否默认地址 0-否 1-是
- * @property {number} isActive - 状态 0-禁用 1-启用
- * @property {string} [createTime] - 创建时间
- * @property {string} [updateTime] - 更新时间
- */
 
+import RegionCascader from '@/components/region-cascader'
+import addressMixin from './addressMixin';
 /**
- * 客户地址列表项
- * @typedef {Object} CustomerAddressItem
- * @property {number} id - 地址ID
- * @property {number} customerId - 客户ID
- * @property {string} customerCode - 客户编码
- * @property {string} customerName - 客户名称
- * @property {string} receiverName - 收货人姓名
- * @property {string} receiverPhone - 收货人电话
- * @property {string} regionCode - 地区编码
- * @property {string} regionName - 地区名称
- * @property {string} detailAddress - 详细地址
- * @property {string} postalCode - 邮政编码
- * @property {number} isDefault - 是否默认地址 0-否 1-是
- * @property {number} isActive - 状态 0-禁用 1-启用
- * @property {string} createTime - 创建时间
- * @property {string} updateTime - 更新时间
+ * @typedef {import('./types').OrderAddressComponent} OrderAddressComponent
  */
 
 /**
- * 客户选项类型定义
- * @typedef {Object} CustomerOption
- * @property {string} value - 客户ID
- * @property {string} label - 显示标签(客户编码 - 客户名称)
- * @property {string} customerCode - 客户编码
- * @property {string} customerName - 客户名称
- * @property {string} customerId - 客户ID
+ * @type {OrderAddressComponent}
  */
-
 export default {
   name: 'OrderAddress',
   components: {
     RegionCascader
   },
-  data() {
-    return {
-      /**
-       * 客户选项列表
-       * @type {CustomerOption[]}
-       */
-      customerOptions: [],
-
-      /**
-       * 客户选项加载状态
-       * @type {boolean}
-       */
-      customerLoading: false,
-
-      /**
-       * 客户搜索关键词
-       * @type {string}
-       */
-      customerSearchKeyword: '',
-
-      /**
-       * 客户搜索定时器
-       * @type {number|null}
-       */
-      customerSearchTimer: null,
-
-      /**
-       * 表单数据
-       * @type {CustomerAddressForm}
-       */
-      form: {},
-
-      /**
-       * 查询条件
-       * @type {CustomerAddressQueryParams}
-       */
-      query: {},
-
-      /**
-       * 加载状态
-       * @type {boolean}
-       */
-      loading: true,
-
-      /**
-       * 地区级联选择器的值
-       * @type {Array}
-       */
-      regionCascaderValue: [],
-
-      /**
-       * 分页信息
-       * @type {{pageSize: number, currentPage: number, total: number}}
-       */
-      page: {
-        pageSize: 10,
-        currentPage: 1,
-        total: 0
-      },
-
-      /**
-       * 选中的行数据
-       * @type {CustomerAddressItem[]}
-       */
-      selectionList: [],
-
-      /**
-       * 表格配置
-       * @type {Object}
-       */
-      option: {
-        height: 'auto',
-        calcHeight: 30,
-        tip: false,
-        searchShow: true,
-        searchMenuSpan: 6,
-        border: true,
-        index: true,
-        selection: true,
-        viewBtn: true,
-        dialogClickModal: false,
-        dialogWidth: 900,
-        column: [
-          {
-            label: '客户',
-            prop: 'customerId',
-            type: 'select',
-            search: true,
-            searchShow: true,
-            searchSubmit: false,
-            width: 200,
-            filterable: true,
-            remote: false,
-            reserveKeyword: true,
-            placeholder: '请选择客户',
-            dicData: [],
-            props: {
-              label: 'label',
-              value: 'value'
-            },
-            rules: [
-              {
-                required: true,
-                message: '请选择客户',
-                trigger: 'change'
-              }
-            ],
-            /**
-             * 客户选择变更事件
-             * @param {Object} param - 事件参数
-             * @param {string} param.value - 选中的客户ID
-             * @param {Object} param.column - 列配置
-             * @returns {void}
-             */
-            change: ({ value, column }) => {
-              if (value) {
-                const selectedCustomer = this.customerOptions.find(option => option.value === value)
-                if (selectedCustomer) {
-                  // 自动填充客户信息
-                  this.form.customerId = selectedCustomer.customerId
-                  this.form.customerCode = selectedCustomer.customerCode
-                  this.form.customerName = selectedCustomer.customerName
-                } else {
-                  this.clearCustomerData()
-                }
-              } else {
-                this.clearCustomerData()
-              }
-            }
-          },
-          {
-            label: '客户编码',
-            prop: 'customerCode',
-            search: true,
-            width: 120,
-            rules: [
-              {
-                required: true,
-                message: '请输入客户编码',
-                trigger: 'blur'
-              },
-              {
-                pattern: /^[A-Z0-9_-]+$/,
-                message: '客户编码只能包含大写字母、数字、下划线和中横线',
-                trigger: 'blur'
-              },
-            ]
-
-            // addDisplay: true,
-            // editDisplay: true
-          },
-          {
-            label: '客户名称',
-            prop: 'customerName',
-            search: true,
-            width: 200,
-            rules: [
-              {
-                required: true,
-                message: '请输入客户名称',
-                trigger: 'blur'
-              },
-              {
-                max: 50,
-                message: '客户名称不能超过50个字符',
-                trigger: 'blur'
-              }
-            ]
-
-            // addDisplay: false,
-            // editDisplay: false
-          },
-          {
-            label: '收货人姓名',
-            prop: 'receiverName',
-            search: true,
-            width: 120,
-            rules: [
-              {
-                required: true,
-                message: '请输入收货人姓名',
-                trigger: 'blur'
-              },
-            ]
-          },
-          {
-            label: '收货人电话',
-            prop: 'receiverPhone',
-            search: true,
-            width: 130,
-            rules: [
-              {
-                required: true,
-                message: '请输入收货人电话',
-                trigger: 'blur'
-              },
-              {
-                pattern: /^1[3-9]\d{9}$/,
-                message: '请输入正确的手机号码',
-                trigger: 'blur'
-              }
-            ]
-          },
-          {
-            label: '地区',
-            prop: 'regionName',
-            search: true,
-            width: 150,
-            formSlot: true, // 启用表单插槽
-            rules: [
-              {
-                required: true,
-                message: '请选择地区',
-                trigger: 'change'
-              }
-            ]
-          },
-          {
-            label: '地区编码',
-            prop: 'regionCode',
-            hide: true,
-            rules: [
-              {
-                required: true,
-                message: '请输入地区编码',
-                trigger: 'blur'
-              }
-            ]
-          },
-          {
-            label: '详细地址',
-            prop: 'detailAddress',
-            width: 250,
-            overHidden: true,
-            span: 24,
-            rules: [
-              {
-                required: true,
-                message: '请输入详细地址',
-                trigger: 'blur'
-              },
-              {
-                min: 5,
-                max: 200,
-                message: '详细地址长度在5到200个字符',
-                trigger: 'blur'
-              }
-            ]
-          },
-          {
-            label: '邮政编码',
-            prop: 'postalCode',
-            width: 100,
-            rules: [
-              {
-                pattern: /^\d{6}$/,
-                message: '请输入正确的邮政编码',
-                trigger: 'blur'
-              }
-            ]
-          },
-          {
-            label: '默认地址',
-            prop: 'isDefault',
-            type: 'select',
-            dicData: [
-              { label: '否', value: 0 },
-              { label: '是', value: 1 }
-            ],
-            search: true,
-            slot: true,
-            width: 100,
-            value: 0
-          },
-          {
-            label: '状态',
-            prop: 'isActive',
-            type: 'select',
-            dicData: [
-              { label: '禁用', value: 0 },
-              { label: '启用', value: 1 }
-            ],
-            search: true,
-            slot: true,
-            width: 100,
-            value: 1
-          },
-          {
-            label: '创建时间',
-            prop: 'createTime',
-            type: 'datetime',
-            format: 'yyyy-MM-dd HH:mm:ss',
-            valueFormat: 'yyyy-MM-dd HH:mm:ss',
-            width: 160,
-            addDisplay: false,
-            editDisplay: false
-          },
-          {
-            label: '更新时间',
-            prop: 'updateTime',
-            type: 'datetime',
-            format: 'yyyy-MM-dd HH:mm:ss',
-            valueFormat: 'yyyy-MM-dd HH:mm:ss',
-            width: 160,
-            addDisplay: false,
-            editDisplay: false
-          }
-        ]
-      },
-
-      /**
-       * 表格数据
-       * @type {CustomerAddressItem[]}
-       */
-      data: []
-    }
-  },
-  computed: {
-    ...mapGetters(['permission']),
-
-    /**
-     * 权限配置
-     * @returns {{addBtn: boolean, viewBtn: boolean, delBtn: boolean, editBtn: boolean}}
-     */
-    permissionList() {
-      return {
-        // addBtn: this.vaildData(this.permission.order_address_add, false),
-        // viewBtn: this.vaildData(this.permission.order_address_view, false),
-        // delBtn: this.vaildData(this.permission.order_address_delete, false),
-        // editBtn: this.vaildData(this.permission.order_address_edit, false)
-        addBtn: true,
-        viewBtn: true,
-        delBtn: false,
-        editBtn: true
-      }
-    },
-
-    /**
-     * 选中的ID字符串
-     * @returns {string} 逗号分隔的ID字符串
-     */
-    ids() {
-      let ids = []
-      this.selectionList.forEach(ele => {
-        ids.push(ele.id)
-      })
-      return ids.join(',')
-    }
-  },
-  methods: {
-    /**
-     * 加载客户选项列表
-     * @param {string} [keyword=''] - 搜索关键词
-     * @returns {Promise<void>}
-     */
-    async loadCustomerOptions(keyword = '') {
-      try {
-        this.customerLoading = true
-        const params = {}
-
-        // 如果有搜索关键词,添加到查询参数中
-        if (keyword.trim()) {
-          params.Customer_CODE = keyword
-          params.Customer_NAME = keyword
-        }
-
-        const response = await getCustomerList(1, 50, params)
-
-        if (response.data && response.data.success) {
-          const customers = response.data.data.records || []
-          this.customerOptions = customers.map(customer => ({
-            value: customer.Customer_ID,
-            label: `${customer.Customer_CODE} - ${customer.Customer_NAME}`,
-            customerCode: customer.Customer_CODE,
-            customerName: customer.Customer_NAME,
-            customerId: customer.Customer_ID
-          }))
-
-          // 更新表格配置中的选项数据
-          this.updateCustomerOptionsInColumn()
-        } else {
-          this.customerOptions = []
-          this.$message.warning('获取客户列表失败')
-        }
-      } catch (error) {
-        this.customerOptions = []
-        console.error('加载客户选项失败:', error)
-        this.$message.error('加载客户选项失败,请稍后重试')
-      } finally {
-        this.customerLoading = false
-      }
-    },
-
-    /**
-     * 搜索客户(防抖处理)
-     * @param {string} query - 搜索关键词
-     * @returns {void}
-     */
-    searchCustomers(query) {
-      // 清除之前的定时器
-      if (this.customerSearchTimer) {
-        clearTimeout(this.customerSearchTimer)
-      }
-
-      // 设置新的定时器,300ms后执行搜索
-      this.customerSearchTimer = setTimeout(() => {
-        this.loadCustomerOptions(query)
-      }, 300)
-    },
-
-    /**
-     * 更新表格配置中的客户选项数据
-     * @returns {void}
-     */
-    updateCustomerOptionsInColumn() {
-      const customerColumn = this.option.column.find(col => col.prop === 'customerId')
-      if (customerColumn) {
-        customerColumn.dicData = this.customerOptions
-      }
-    },
-
-    /**
-     * 清除客户相关数据
-     * @returns {void}
-     */
-    clearCustomerData() {
-      this.form.customerCode = ''
-      this.form.customerName = ''
-      this.form.customerId = ''
-    },
-
-    /**
-     * 地区选择改变事件
-     * @param {Object} data - 选择的地区数据
-     */
-    handleRegionChange(data) {
-      const { regionName } = data
-
-      // 只设置regionName,regionCode保持独立
-      this.form.regionName = regionName
-
-      // 手动触发表单验证
-      this.$nextTick(() => {
-        if (this.$refs.crud && this.$refs.crud.$refs.dialogForm) {
-          this.$refs.crud.$refs.dialogForm.validateField('regionName')
-        }
-      })
-    },
-
-    /**
-     * 新增前的回调
-     * @param {Function} done - 完成回调
-     * @param {string} type - 操作类型
-     * @returns {Promise<void>}
-     */
-    // async beforeOpen(done, type) {
-    //   if (['edit', 'view'].includes(type)) {
-    //     try {
-    //       const res = await getDetail(this.form.id)
-    //       this.form = res.data.data
-
-    //       // regionName会通过组件的watch自动解析和回显
-    //       // 不需要额外处理regionCascaderValue
-    //     } catch (error) {
-    //       window.console.log(error)
-    //     }
-    //   }
-    //   done()
-    // },
-
-   /**
-     * 新增前的回调
-     * @param {Function} done - 完成回调
-     * @param {string} type - 操作类型
-     * @returns {Promise<void>}
-     */
-    async beforeOpen(done, type) {
-      // 确保客户选项已加载
-      if (this.customerOptions.length === 0) {
-        await this.loadCustomerOptions()
-      }
-
-      if (['edit', 'view'].includes(type)) {
-        try {
-          const res = await getDetail(this.form.id)
-          this.form = res.data.data
-
-          // 如果有客户信息,确保客户选项中包含当前客户
-          if (this.form.customerId && this.form.customerCode && this.form.customerName) {
-            const existingCustomer = this.customerOptions.find(option => option.value === this.form.customerId.toString())
-            if (!existingCustomer) {
-              this.customerOptions.unshift({
-                value: this.form.customerId.toString(),
-                label: `${this.form.customerCode} - ${this.form.customerName}`,
-                customerCode: this.form.customerCode,
-                customerName: this.form.customerName,
-                customerId: this.form.customerId.toString()
-              })
-              this.updateCustomerOptionsInColumn()
-            }
-          }
-        } catch (error) {
-          window.console.log(error)
-        }
-      }
-      done()
-    },
-
-    /**
-     * 获取数据
-     * @param {Object} page - 分页信息
-     * @param {CustomerAddressQueryParams} params - 查询参数
-     * @returns {Promise<void>}
-     */
-    async onLoad(page, params = {}) {
-      this.loading = true
-      try {
-        const res = await getList(page.currentPage, page.pageSize, Object.assign(params, this.query))
-        const data = res.data.data
-        this.page.total = data.total
-        this.data = data.records
-        this.loading = false
-        this.selectionClear()
-      } catch (error) {
-        this.loading = false
-        window.console.log(error)
-      }
-    },
-
-    /**
-     * 新增
-     * @param {CustomerAddressForm} row - 表单数据
-     * @param {Function} done - 完成回调
-     * @param {Function} loading - 加载状态回调
-     * @returns {Promise<void>}
-     */
-    async rowSave(row, done, loading) {
-      try {
-        await add(row)
-        done()
-        this.onLoad(this.page)
-        this.$message({
-          type: 'success',
-          message: '操作成功!'
-        })
-      } catch (error) {
-        loading()
-        window.console.log(error)
-      }
-    },
-
-    /**
-     * 修改
-     * @param {CustomerAddressForm} row - 表单数据
-     * @param {number} index - 行索引
-     * @param {Function} done - 完成回调
-     * @param {Function} loading - 加载状态回调
-     * @returns {Promise<void>}
-     */
-    async rowUpdate(row, index, done, loading) {
-      try {
-        await update(row)
-        done()
-        this.onLoad(this.page)
-        this.$message({
-          type: 'success',
-          message: '操作成功!'
-        })
-      } catch (error) {
-        loading()
-        window.console.log(error)
-      }
-    },
-
-    /**
-     * 搜索回调
-     * @param {CustomerAddressQueryParams} params - 搜索参数
-     * @param {Function} done - 完成回调
-     * @returns {void}
-     */
-    searchChange(params, done) {
-      this.query = params
-      this.onLoad(this.page, params)
-      done()
-    },
-
-    /**
-     * 搜索重置回调
-     * @returns {void}
-     */
-    searchReset() {
-      this.query = {}
-      this.onLoad(this.page)
-    },
-
-    /**
-     * 选择改变回调
-     * @param {CustomerAddressItem[]} list - 选中的数据
-     * @returns {void}
-     */
-    selectionChange(list) {
-      this.selectionList = list
-    },
-
-    /**
-     * 清空选择
-     * @returns {void}
-     */
-    selectionClear() {
-      this.selectionList = []
-      this.$refs.crud.toggleSelection()
-    },
-
-    /**
-     * 当前页改变回调
-     * @param {number} currentPage - 当前页
-     * @returns {void}
-     */
-    currentChange(currentPage) {
-      this.page.currentPage = currentPage
-    },
-
-    /**
-     * 页大小改变回调
-     * @param {number} pageSize - 页大小
-     * @returns {void}
-     */
-    sizeChange(pageSize) {
-      this.page.pageSize = pageSize
-    },
-
-    /**
-     * 刷新回调
-     * @returns {void}
-     */
-    refreshChange() {
-      this.onLoad(this.page, this.query)
-    }
-  },
-  /**
-   * 组件创建时加载客户选项
-   * @returns {Promise<void>}
-   */
-  async created() {
-    await this.loadCustomerOptions()
-  },
-
-  /**
-   * 组件销毁前清理定时器
-   * @returns {void}
-   */
-  beforeDestroy() {
-    if (this.customerSearchTimer) {
-      clearTimeout(this.customerSearchTimer)
-    }
-  }
+  mixins: [addressMixin],
 }
 </script>

+ 258 - 0
src/views/order/address/types.d.ts

@@ -0,0 +1,258 @@
+/**
+ * 订单地址管理组件类型定义
+ * @description 为订单地址管理相关组件提供完整的TypeScript类型支持
+ */
+
+import { Vue } from 'vue/types/vue';
+import { AxiosResponse } from 'axios';
+import {
+  CustomerAddressQueryParams as BaseCustomerAddressQueryParams,
+  CustomerAddressForm as BaseCustomerAddressForm,
+  CustomerAddressRecord,
+  CustomerAddressListResponse,
+  CustomerAddressDetailResponse,
+  CustomerAddressOperationResponse,
+  CustomerAddressFullListResponse
+} from '@/api/types/address';
+import { SelectOption, ValidationRule, ApiResponse, PageResult } from '@/api/types/common';
+
+/**
+ * 扩展的客户地址查询参数
+ * @description 继承基础查询参数,扩展前端特有字段
+ */
+export interface CustomerAddressQueryParams extends BaseCustomerAddressQueryParams {
+  /** 客户ID */
+  customerId?: string | number;
+}
+
+/**
+ * 扩展的客户地址表单数据
+ * @description 继承基础表单数据,扩展前端特有字段
+ */
+export interface CustomerAddressForm extends Omit<BaseCustomerAddressForm, 'customerId'> {
+  /** 客户ID */
+  customerId?: number | null;
+  /** 创建时间 */
+  createTime?: string;
+  /** 更新时间 */
+  updateTime?: string;
+}
+
+/**
+ * 客户地址列表项类型
+ * @description 基于CustomerAddressRecord的别名
+ */
+export type CustomerAddressItem = CustomerAddressRecord;
+
+/**
+ * 客户选项类型
+ * @description 用于下拉选择的客户选项
+ */
+export interface CustomerOption {
+  /** 选项值 */
+  value: string | number;
+  /** 选项标签 */
+  label: string;
+  /** 客户编码 */
+  customerCode: string;
+  /** 客户名称 */
+  customerName: string;
+  /** 客户ID */
+  customerId: string;
+}
+
+/**
+ * 地区选择器数据类型
+ */
+export interface RegionData {
+  /** 地区编码 */
+  regionCode: string;
+  /** 地区名称 */
+  regionName: string;
+}
+
+/**
+ * 订单地址管理Mixin数据类型
+ */
+export interface OrderAddressMixinData {
+  /** 客户选项列表 */
+  customerOptions: Array<CustomerOption>;
+  /** 客户选项加载状态 */
+  customerLoading: boolean;
+  /** 客户搜索关键词 */
+  customerSearchKeyword: string;
+  /** 客户搜索定时器 */
+  customerSearchTimer: number | null;
+  /** 表单数据 */
+  form: CustomerAddressForm;
+  /** 查询参数 */
+  query: CustomerAddressQueryParams;
+  /** 加载状态 */
+  loading: boolean;
+  /** 地区级联选择器值 */
+  regionCascaderValue: string;
+  /** 选中的数据列表 */
+  selectionList: Array<CustomerAddressItem>;
+  /** 表格数据 */
+  data: Array<CustomerAddressItem>;
+  /** 表格配置选项 */
+  option: {
+    [key: string]: any;
+    column?: Array<{
+      prop: string;
+      label: string;
+      type?: string;
+      dicData?: Array<{ label: string; value: any }>;
+      [key: string]: any;
+    }>;
+  };
+}
+
+/**
+ * 订单地址管理Mixin计算属性类型
+ */
+export interface OrderAddressMixinComputed {
+  /** 权限映射 */
+  permission: {
+    [key: string]: boolean;
+    order_address_add?: boolean;
+    order_address_edit?: boolean;
+    order_address_delete?: boolean;
+    order_address_view?: boolean;
+  };
+  /** 权限列表 */
+  permissionList: {
+    addBtn: boolean;
+    viewBtn: boolean;
+    editBtn: boolean;
+    delBtn: boolean;
+  };
+  /** 选中的ID字符串 */
+  ids: string;
+}
+
+/**
+ * 订单地址管理Mixin方法类型
+ */
+export interface OrderAddressMixinMethods {
+  /** 加载客户选项列表 */
+  loadCustomerOptions(keyword?: string): Promise<void>;
+  /** 搜索客户(防抖处理) */
+  searchCustomers(query: string): void;
+  /** 更新表格配置中的客户选项数据 */
+  updateCustomerOptionsInColumn(): void;
+  /** 清除客户相关数据 */
+  clearCustomerData(): void;
+  /** 地区选择改变事件 */
+  handleRegionChange(data: RegionData): void;
+  /** 新增前的回调 */
+  beforeOpen(done: () => void, type: string): Promise<void>;
+  /** 获取数据 */
+  onLoad(params?: CustomerAddressQueryParams): Promise<void>;
+  /** 新增 */
+  rowSave(row: CustomerAddressForm, done: () => void, loading: () => void): Promise<void>;
+  /** 修改 */
+  rowUpdate(row: CustomerAddressForm, index: number, done: () => void, loading: () => void): Promise<void>;
+  /** 搜索回调 */
+  searchChange(params: CustomerAddressQueryParams, done: () => void): void;
+  /** 搜索重置回调 */
+  searchReset(): void;
+  /** 选择改变回调 */
+  selectionChange(list: Array<CustomerAddressItem>): void;
+  /** 清空选择 */
+  selectionClear(): void;
+  /** 刷新回调 */
+  refreshChange(): void;
+}
+
+/**
+ * 订单地址管理组件Props类型
+ */
+export interface OrderAddressComponentProps {
+  // 目前没有特定的props,可根据需要扩展
+}
+
+/**
+ * 订单地址管理组件事件类型
+ */
+export interface OrderAddressComponentEvents {
+  /** 删除事件 */
+  'row-del': (row: CustomerAddressItem, index: number) => void;
+  /** 更新事件 */
+  'row-update': (row: CustomerAddressForm, index: number, done: () => void, loading: () => void) => void;
+  /** 保存事件 */
+  'row-save': (row: CustomerAddressForm, done: () => void, loading: () => void) => void;
+  /** 搜索改变事件 */
+  'search-change': (params: CustomerAddressQueryParams, done: () => void) => void;
+  /** 搜索重置事件 */
+  'search-reset': () => void;
+  /** 选择改变事件 */
+  'selection-change': (list: Array<CustomerAddressItem>) => void;
+  /** 刷新事件 */
+  'refresh-change': () => void;
+  /** 加载事件 */
+  'on-load': (params?: CustomerAddressQueryParams) => void;
+}
+
+/**
+ * 订单地址管理组件类型
+ * @description 组合所有相关类型,用于@this注解
+ */
+export interface OrderAddressComponent extends 
+  OrderAddressComponentProps,
+  OrderAddressMixinData,
+  OrderAddressMixinComputed,
+  OrderAddressMixinMethods {
+  /** Vue refs */
+  $refs: {
+    crud?: {
+      toggleSelection(): void;
+      clearSelection(): void;
+      validate?: (callback?: (valid: boolean) => void) => void;
+      resetFields?: () => void;
+      clearValidate?: () => void;
+      [key: string]: any;
+    };
+    [key: string]: any;
+  };
+  /** 事件发射器 */
+  $emit: <K extends keyof OrderAddressComponentEvents>(
+    event: K,
+    ...args: Parameters<OrderAddressComponentEvents[K]>
+  ) => void;
+  /** 消息提示 */
+  $message: any;
+  /** 下一个tick */
+  $nextTick: (callback?: () => void) => Promise<void>;
+}
+
+/**
+ * 订单地址管理Mixin组件类型
+ * @description 用于Mixin文件的@this注解
+ */
+export interface OrderAddressMixinComponent extends 
+  OrderAddressComponentProps,
+  OrderAddressMixinData,
+  OrderAddressMixinComputed,
+  OrderAddressMixinMethods,
+  Vue {}
+
+/**
+ * API响应类型重导出
+ */
+export {
+  CustomerAddressListResponse,
+  CustomerAddressDetailResponse,
+  CustomerAddressOperationResponse,
+  CustomerAddressFullListResponse
+} from '@/api/types/address';
+
+/**
+ * 通用类型重导出
+ */
+export {
+  SelectOption,
+  ValidationRule,
+  ApiResponse,
+  PageResult
+} from '@/api/types/common';