Ver código fonte

Merge branch 'dev' of 21.tcp.vip.cpolar.cn:hzy-starrysky/zkhx/gubersail/gubersail-platform-ui into dev

yz 2 semanas atrás
pai
commit
81131da6af

+ 8 - 5
src/components/forecast-form/forecast-form-mixin.js

@@ -78,6 +78,7 @@ import { getCustomerList, getItemList, getCustomerInfo } from '@/api/common'
 
 // 表单配置导入
 import { getFormOption } from './form-option'
+import { safeBigInt } from '@/util/util'
 
 /**
  * 销售预测表单事件常量
@@ -380,18 +381,18 @@ export default {
             try {
               this.stockTableData = newData.pcBladeSalesForecastSummaryList.map(item => ({
                 // 尽量保持与 PjpfStockDesc 结构一致,便于表格渲染
-                id: item.id != null ? item.id : undefined,
-                goodsId: item.itemId != null ? item.itemId : undefined,
+                id: item.id ? safeBigInt(item.id) : undefined,
+                goodsId: item.itemId ? safeBigInt(item.itemId) : undefined,
                 code: item.itemCode || '',
                 cname: item.itemName || '',
-                brandId: item.brandId != null ? item.brandId : undefined,
+                brandId: item.brandId ? safeBigInt(item.brandId) : undefined,
                 brandCode: item.brandCode || '',
                 brandName: item.brandName || '',
                 typeNo: item.specs || '',
                 productDescription: item.pattern || '',
                 brandItem: item.pattern || '',
                 // 回显数据可能无库存,先不默认写入 '0',留给后续合并方法填充
-                storeInventory: (item.storeInventory !== undefined && item.storeInventory !== null && item.storeInventory !== '') ? String(item.storeInventory) : undefined,
+                storeInventory: undefined,
                 // 预测数量用于编辑
                 forecastQuantity: Number(item.forecastQuantity || 0)
               }))
@@ -821,7 +822,7 @@ export default {
         }
         // 若编辑入参未包含预测编码,则根据id加载详情以保证回显
         try {
-          const id = (this.editData && (this.editData.id || this.editData.Id)) || (this.formData && (this.formData.id || this.formData.Id))
+          const id = (this.editData && (this.editData.id)) || (this.formData && (this.formData.id))
           if (!this.formData.forecastCode && id) {
             this.loadForecastDetail(id)
           }
@@ -878,6 +879,7 @@ export default {
 
     /**
      * 收集当前可见表单项的必填与数值规则错误信息(用于控制台打印)
+     * @this {ForecastFormMixinComponent & Vue}
      * @returns {string[]} 错误消息列表
      */
     collectValidationErrors() {
@@ -1298,6 +1300,7 @@ export default {
 
     /**
      * 合并回显行的库存数量
+     * @this {ForecastFormMixinComponent & Vue}
      * @description 使用 getUserLinkGoods 接口返回的库存数据,为编辑态回显的物料行补齐 storeInventory 字段
      * @returns {Promise<void>}
      */

+ 15 - 1
src/components/forecast-form/types.d.ts

@@ -158,7 +158,7 @@ export interface ForecastFormMixinData {
   /** 品牌选项列表 */
   brandOptions: Array<SelectOption<number>>;
   /** 物料表格数据(来自用户关联商品 pjpfStockDescList),带预测数量字段 */
-  stockTableData: Array<import('@/api/types/order').PjpfStockDesc & { forecastQuantity: number }>;
+  stockTableData: Array<Partial<import('@/api/types/order').PjpfStockDesc> & { forecastQuantity: number; brandCode?: string; storeInventory?: string }>;
   /** 表格加载状态 */
   tableLoading: boolean;
   /** 品牌描述列表(用于品牌信息匹配) */
@@ -204,6 +204,10 @@ export interface ForecastFormEvents {
   reset: () => void;
   /** 表单提交事件 */
   submit: (data: any) => void;
+  /** 表单提交错误事件 */
+  'submit-error': (error: any) => void;
+  /** v-model 可见性更新事件 */
+  'update:visible': (visible: boolean) => void;
 }
 
 /**
@@ -270,6 +274,14 @@ export interface ForecastFormMethods {
   handleMaterialSelected(materialData: MaterialSelectData): void;
   /** 获取当前库存 */
   getCurrentInventory(itemId: string | number): void;
+  /** 收集可见表单项的校验错误 */
+  collectValidationErrors(): string[];
+  /** 导入所选物料到下方表格 */
+  handleImportSelectedStock(): void;
+  /** 删除物料行 */
+  handleDelete(row: ForecastFormMixinData['stockTableData'][number], index: number): Promise<void>;
+  /** 合并编辑回显行的库存数量 */
+  mergeEchoStoreInventory(): Promise<void>;
   /** 提交(Avue 回调) */
   handleSubmit(): void;
   /** 重置 */
@@ -278,6 +290,8 @@ export interface ForecastFormMethods {
   submitForm(): Promise<void>;
   /** 加载当前用户客户信息(新增态) */
   loadCurrentCustomerInfo(): Promise<void>;
+  /** 可选:宿主组件用于禁用年月选择器的辅助方法 */
+  setYearMonthDisabled?: (disabled: boolean) => void;
 }
 
 /**

+ 1 - 1
src/util/util.js

@@ -383,7 +383,7 @@ export const formatFileSize = (bytes) => {
 /**
  * BigInt 安全转换(兼容 stringify)
  * @param {string|number|bigint|null|undefined} v
- * @returns {string|null}
+ * @returns {string}
  */
 export const safeBigInt = (v) => {
   try {

+ 67 - 11
src/views/announcement/index.vue

@@ -1,7 +1,29 @@
 <template>
     <basic-container>
+        <!-- 公告预览(全屏容器) -->
+        <div v-if="announcementPreviewVisible" class="announcement-preview-container basic-container">
+            <div class="preview-header">
+                <div class="header-top">
+                    <el-button
+                        type="text"
+                        icon="el-icon-arrow-left"
+                        size="small"
+                        class="back-btn"
+                        @click="handlePreviewBack"
+                    >
+                        返回列表
+                    </el-button>
+                </div>
+                <div class="preview-title">{{ currentDetail.title || '公告预览' }}</div>
+            </div>
+            <div class="preview-content">
+                <div class="detail-body" v-html="currentDetail.content"></div>
+            </div>
+        </div>
+
         <!-- 公告表单组件 -->
         <announcement-form
+            v-else-if="announcementFormVisible"
             :visible.sync="announcementFormVisible"
             :is-edit="isEditMode"
             :announcement-id="editAnnouncementId"
@@ -10,7 +32,7 @@
 
         <!-- 公告列表 -->
         <avue-crud
-            v-if="!announcementFormVisible"
+            v-else
             :option="option"
             :data="data"
             ref="crud"
@@ -93,16 +115,6 @@
             </template>
         </avue-crud>
 
-        <!-- 详情对话框 -->
-        <el-dialog title="公告详情" :visible.sync="detailVisible" append-to-body width="60%" :close-on-click-modal="false">
-            <div class="detail-content" v-if="currentDetail.id">
-                <!-- 仅展示富文本内容 -->
-                <div class="detail-body" v-html="currentDetail.content"></div>
-            </div>
-            <span slot="footer" class="dialog-footer">
-                <el-button @click="detailVisible = false">关 闭</el-button>
-            </span>
-        </el-dialog>
     </basic-container>
 </template>
 
@@ -135,4 +147,48 @@ export default {
 
 <style lang="scss" scoped>
 @import './index.scss';
+
+.announcement-preview-container {
+  padding: 0;
+}
+
+.preview-header {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start; /* 显式左对齐头部子项,避免外部样式影响 */
+  padding: 12px 16px;
+  background-color: #ffffff;
+  border-radius: 8px 8px 0 0;
+  margin-bottom: 8px;
+}
+
+.header-top {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.back-btn {
+  padding-left: 0;
+}
+
+.preview-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #303133;
+  text-align: center;
+  margin-top: 4px;
+  align-self: center; /* 让标题在交叉轴居中 */
+  width: 100%;        /* 占满一行,文本居中更明显 */
+}
+
+.preview-content {
+  background-color: #ffffff;
+  padding: 16px;
+  border-radius: 0 0 8px 8px;
+}
+
+.detail-body {
+  min-height: 300px;
+}
 </style>

+ 22 - 2
src/views/announcement/mixins/announcementIndex.js

@@ -139,6 +139,8 @@ export default {
             loading: true,
             /** @type {boolean} 详情对话框显示状态 */
             detailVisible: false,
+            /** 用于全屏预览的可见性控制 */
+            announcementPreviewVisible: false,
             /** @type {Partial<NoticeRecord>} 当前查看的详情数据 */
             currentDetail: {},
             /** @type {PageInfo} 分页信息 */
@@ -394,6 +396,14 @@ export default {
                 // 关闭表单后,avue-crud 会通过 v-if 重新渲染,需等 DOM 恢复后再刷新字典
                 this.$nextTick(() => this.loadCategoryOptions());
             }
+        },
+        announcementPreviewVisible(val) {
+            if (val === true) {
+                // 打开预览时不需要刷新列表
+            } else {
+                // 关闭预览后,avue-crud 会通过 v-if 重新渲染,需等 DOM 恢复后再刷新字典
+                this.$nextTick(() => this.loadCategoryOptions());
+            }
         }
     },
 
@@ -475,7 +485,7 @@ export default {
         },
 
         /**
-         * 查看详情(支持行内操作)
+         * 查看详情(支持行内操作)- 改为进入全屏预览模式
          * @async
          * @this {import('@/views/announcement/types').AnnouncementComponent & import('vue').default}
          * @param {Partial<NoticeRecord>} [row] - 可选,当前行数据
@@ -492,13 +502,23 @@ export default {
             try {
                 const response = await getAnnouncement(id);
                 this.currentDetail = response.data?.data || {};
-                this.detailVisible = true;
+                // 打开全屏预览
+                this.announcementPreviewVisible = true;
             } catch (error) {
                 console.error('获取详情失败:', error);
                 this.$message.error('获取详情失败,请稍后重试');
             }
         },
 
+        /**
+         * 关闭全屏预览并返回列表
+         */
+        handlePreviewBack() {
+            this.announcementPreviewVisible = false;
+            // 可按需清理当前详情
+            // this.currentDetail = {};
+        },
+
         // 新增:单行删除(操作列按钮)
         /**
          * 行删除(操作列按钮)