import { getList, getAddressList, add, update, getDetail, addAddress, updateAddress, deleteAddress } 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: false, viewBtn: true, delBtn: 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', addDisplay: false, editDisplay: false }, { label: '客户编码', prop: 'customerCode', width: 120, rules: [ { required: true, message: '请输入客户编码', trigger: 'blur' }, { pattern: /^[A-Z0-9_-]+$/, message: '客户编码只能包含大写字母、数字、下划线和中横线', trigger: 'blur' }, ], addDisplay: false, editDisplay: false }, { 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: true, 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} * @this {OrderAddressMixinComponent & Vue} */ async loadCustomerOptions(keyword = '') { try { /** @type {Record} */ 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 {OrderAddressMixinComponent & Vue} * @param {Function} done - 完成回调 * @param {string} type - 操作类型 * @returns {Promise} */ 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} params - 查询参数 * @returns {Promise} * @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} */ async rowSave(row, done, loading) { try { // 转换为API期望的类型 const apiData = { ...row, customerId: row.customerId || 0 } await addAddress(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} */ async rowUpdate(row, index, done, loading) { try { // 转换为API期望的类型 const apiData = { ...row, customerId: row.customerId || 0 } await updateAddress(apiData) done() this.onLoad(this.query) this.$message({ type: 'success', message: '操作成功!' }) } catch (error) { loading() window.console.log(error) } }, /** * 删除行数据 * @param {CustomerAddressItem} row - 行数据 * @param {number} index - 行索引 * @returns {Promise} * @this {OrderAddressMixinComponent & Vue} */ async rowDel(row, index) { try { await deleteAddress(row.id || 0) this.onLoad(this.query) this.$message({ type: 'success', message: '删除成功!' }) } catch (error) { this.$message({ type: 'error', message: '删除失败!' }) 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) } } }