123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- <template>
- <!-- 订单表单容器 - 参照示例HTML的基础容器结构 -->
- <div class="order-form-container basic-container">
- <!-- 表单头部导航 -->
- <div class="order-form-header">
- <div class="header-left">
- <el-button
- type="text"
- icon="el-icon-arrow-left"
- size="small"
- class="back-btn"
- @click="handleBack"
- >
- 返回列表
- </el-button>
- <span class="form-title">{{ formTitle }}</span>
- </div>
- <div class="header-right">
- <el-button
- type="text"
- icon="el-icon-upload2"
- size="small"
- v-if="isEdit && canSubmitToU9(formData) && (orderId || formData.id)"
- @click="handleSubmitToU9"
- style="color: #409eff"
- >
- 提交
- </el-button>
- <!-- 顶部保存按钮 -->
- <el-button
- type="primary"
- icon="el-icon-check"
- size="small"
- :loading="saveLoading"
- @click="handleSave"
- >
- 保存
- </el-button>
- </div>
- </div>
- <!-- 表单内容区域 - 参照示例HTML的avue-form结构 -->
- <div class="order-form-content">
- <avue-form
- ref="orderForm"
- v-model="formData"
- :option="formOption"
- class="order-form"
- @submit="handleFormSubmit"
- @reset-change="handleFormReset"
- >
- <!-- 自定义客户选择组件 -->
- <template #customerId="{ value, column }">
- <customer-select
- v-model="formData.customerId"
- :placeholder="column.placeholder"
- :disabled="column.disabled"
- @customer-selected="handleCustomerSelected"
- />
- </template>
- <!-- 自定义地址选择组件 -->
- <template #addressId="{ value, column }">
- <address-select
- v-model="formData.addressId"
- :customer-code="formData.customerCode"
- :placeholder="column.placeholder"
- :disabled="column.disabled"
- @address-selected="handleAddressSelected"
- />
- </template>
- </avue-form>
- <!-- 物料明细区域 -->
- <div class="material-detail-section">
- <material-detail-table
- :order-id="orderId"
- :edit-mode="true"
- :material-details="materialDetails"
- @refresh="handleMaterialChange"
- @material-import="handleMaterialImport"
- @material-delete="handleMaterialDelete"
- @material-update="handleMaterialUpdate"
- />
- </div>
- </div>
- </div>
- </template>
- <script>
- // @ts-check
- import orderFormMixin from './order-form-mixin'
- import MaterialDetailTable from './material-detail-table.vue'
- import CustomerSelect from './customer-select.vue'
- import AddressSelect from './address-select.vue'
- /**
- * 订单表单组件类型定义
- * @typedef {import('./types').OrderFormModel} OrderFormModel
- * @typedef {import('./types').MaterialDetailRecord} MaterialDetailRecord
- * @typedef {import('./types').MaterialUpdateEventData} MaterialUpdateEventData
- * @typedef {import('./types').MaterialDeleteEventData} MaterialDeleteEventData
- * @typedef {import('./types').CustomerSelectData} CustomerSelectData
- * @typedef {import('./types').AddressSelectData} AddressSelectData
- * @typedef {import('./types').OrderFormComponent} OrderFormComponent
- * @typedef {import('smallwei__avue/form').AvueFormOption<OrderFormModel>} AvueFormOption
- * @typedef {import('smallwei__avue/form').AvueFormColumn<OrderFormModel>} AvueFormColumn
- * @typedef {import('smallwei__avue/form').AvueFormGroup<OrderFormModel>} AvueFormGroup
- */
- /**
- * 订单表单组件
- * @description 基于AvueJS的订单表单组件,支持新增和编辑订单功能,包含物料明细管理和自动计算功能
- * @this {import('./types').OrderFormComponent}
- */
- export default {
- name: 'OrderForm',
- mixins: [orderFormMixin],
- /**
- * 组件注册
- */
- components: {
- MaterialDetailTable,
- CustomerSelect,
- AddressSelect
- },
- /**
- * 组件属性定义
- * @description 定义组件接收的外部属性及其类型约束
- */
- props: {
- /**
- * 表单可见性控制
- * @description 控制订单表单的显示和隐藏状态
- * @type {boolean}
- * @default false
- */
- visible: {
- type: Boolean,
- default: false,
- validator: (value) => typeof value === 'boolean'
- },
- /**
- * 编辑模式标识
- * @description 标识当前表单是新增模式还是编辑模式
- * @type {boolean}
- * @default false
- */
- isEdit: {
- type: Boolean,
- default: false,
- validator: (value) => typeof value === 'boolean'
- },
- /**
- * 订单唯一标识
- * @description 编辑模式下用于标识要编辑的订单记录
- * @type {string|number|null}
- * @default null
- */
- orderId: {
- type: [String, Number],
- default: null,
- validator: (value) => {
- return value === null ||
- typeof value === 'string' ||
- typeof value === 'number'
- }
- }
- },
- /**
- * 属性监听器
- * @description 监听组件属性变化并执行相应的响应逻辑
- */
- watch: {
- /**
- * 监听表单可见性变化
- * @description 当表单从隐藏变为可见时,初始化表单数据
- * @param {boolean} newVal - 新的可见性状态
- * @param {boolean} oldVal - 旧的可见性状态
- */
- visible: {
- handler(newVal, oldVal) {
- if (newVal && !oldVal) {
- this.initForm()
- }
- },
- immediate: true
- },
- /**
- * 监听订单ID变化
- * @description 当订单ID变化且处于编辑模式时,加载订单详情数据
- * @param {string|number|null} newVal - 新的订单ID
- * @param {string|number|null} oldVal - 旧的订单ID
- */
- orderId: {
- handler(newVal, oldVal) {
- if (newVal && this.isEdit && newVal !== oldVal) {
- this.loadOrderDetail(newVal)
- }
- },
- immediate: true
- },
- /**
- * 监听表单数据变化,用于地址回显
- * @description 当表单数据中的客户编码和地址相关字段都有值时,触发地址选择组件的回显
- */
- 'formData.customerCode': {
- handler(newVal) {
- if (newVal && this.isEdit && this.formData.addressId) {
- // 延迟执行,确保地址选择组件已经加载完成
- this.$nextTick(() => {
- this.handleAddressEcho()
- })
- }
- }
- }
- }
- }
- </script>
- <style scooped>
- /* 全局覆盖外层el-card的body padding - 使用更高优先级 */
- .order-form-container .el-card .el-card__body {
- padding: 0 !important;
- }
- /* 针对可能的嵌套情况 */
- .el-card .el-card__body {
- padding: 0 !important;
- }
- </style>
- <style scoped>
- .order-form-container {
- /* padding: 20px; */
- background-color: #f5f5f5;
- min-height: 100vh;
- /* max-width: 1200px; */
- margin: 0 auto;
- }
- .order-form-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 16px 20px;
- background-color: #ffffff;
- border-radius: 8px 8px 0 0;
- border-bottom: 1px solid #ebeef5;
- margin-bottom: 0;
- }
- .header-left {
- display: flex;
- align-items: center;
- gap: 12px;
- }
- .back-btn {
- color: #409eff;
- font-size: 14px;
- padding: 0;
- }
- .back-btn:hover {
- color: #66b1ff;
- }
- .form-title {
- font-size: 18px;
- font-weight: 600;
- color: #303133;
- margin: 0;
- }
- .header-right {
- display: flex;
- gap: 8px;
- }
- .order-form-content {
- background-color: #ffffff;
- padding: 10px;
- border-radius: 0 0 8px 8px;
- /* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
- }
- .order-form {
- max-width: 100%;
- }
- .material-detail-section {
- background-color: #ffffff;
- margin-top: 16px;
- border-radius: 8px;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
- }
- /* 响应式设计 */
- @media (max-width: 768px) {
- .order-form-container {
- padding: 10px;
- }
- .order-form-header {
- flex-direction: column;
- gap: 12px;
- align-items: flex-start;
- padding: 12px 16px;
- }
- .header-right {
- width: 100%;
- justify-content: flex-end;
- }
- .form-title {
- font-size: 16px;
- }
- .order-form-content {
- padding: 16px;
- }
- }
- </style>
|