tjxt 2 месяцев назад
Родитель
Сommit
7f6634a5c0

+ 65 - 0
src/api/product/base/index.ts

@@ -0,0 +1,65 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { BaseVO, BaseForm, BaseQuery, StatusCountVo } from '@/api/product/base/types';
+
+
+/**
+ * 查询产品基础信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listBase = (query?: BaseQuery): AxiosPromise<BaseVO[]> => {
+  return request({
+    url: '/product/base/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品基础信息详细
+ * @param id
+ */
+export const getBase = (id: string | number): AxiosPromise<BaseVO> => {
+  return request({
+    url: '/product/base/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品基础信息
+ * @param data
+ */
+export const addBase = (data: BaseForm) => {
+  return request({
+    url: '/product/base',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品基础信息
+ * @param data
+ */
+export const updateBase = (data: BaseForm) => {
+  return request({
+    url: '/product/base',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品基础信息
+ * @param id
+ */
+export const delBase = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/base/' + id,
+    method: 'delete'
+  });
+};
+

+ 756 - 0
src/api/product/base/types.ts

@@ -0,0 +1,756 @@
+export interface BaseVO {
+  /**
+   * 主键,自增ID
+   */
+  id: string | number;
+
+  /**
+   * 产品编号
+   */
+  productNo: string;
+
+  /**
+   * 项目名称
+   */
+  itemName: string;
+
+  /**
+   * 品牌id
+   */
+  brandId: string | number;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId: string | number;
+
+  /**
+   * 底层分类id
+   */
+  bottomCategoryId: string | number;
+
+  /**
+   * 单位id
+   */
+  unitId: string | number;
+
+  /**
+   * 产品图片URL
+   */
+  productImage: string;
+
+  /**
+   * 产品图片URLUrl
+   */
+  productImageUrl: string;
+  /**
+   * 是否自营(1=是,0=否)
+   */
+  isSelf: string;
+
+  /**
+   * 商品类型 1=默认类型,2精选商品,3=停售商品
+   * */
+  productCategory?: number;
+
+  /**
+   * 产品审核状态 0=待采购审核,1=审核通过,2=驳回,3=待营销审核
+   */
+  productReviewStatus: string;
+
+  /**
+   * 首页推荐:1=推荐,0=不推荐
+   */
+  homeRecommended: string;
+
+  /**
+   * 分类推荐:1=推荐,0=不推荐
+   */
+  categoryRecommendation: string;
+
+  /**
+   * 购物车推荐:1=推荐,0=不推荐
+   */
+  cartRecommendation: string;
+
+  /**
+   * 推荐产品顺序
+   */
+  recommendedProductOrder: number;
+
+  /**
+   * 是否热门:1=是,0=否
+   */
+  isPopular: string;
+
+  /**
+   * 是否新品:1=是,0=否
+   */
+  isNew: string;
+
+  /**
+   * 商品状态:1=已上架,0=下架,2=上架中
+   */
+  productStatus: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 市场价
+   */
+  marketPrice: number;
+
+  /**
+   * 会员价格
+   */
+  memberPrice: number;
+
+  /**
+   * 最低销售价格
+   */
+  minSellingPrice: number;
+
+  /**
+   * 采购价格
+   */
+  purchasingPrice: number;
+
+  /**
+   * 暂估毛利率
+   */
+  tempGrossMargin: number;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  /**
+   * 主库简介
+   */
+  mainLibraryIntro?: string;
+
+  /**
+   * 售后服务
+   */
+  afterSalesService?: string;
+
+  /**
+   * 服务保障 支持多选,分隔 (存储服务保障ID列表,如: "1,2,3")
+   */
+  serviceGuarantee?: string;
+
+  /**
+   * 安装服务 - 免费安装
+   */
+  freeInstallation?: string;
+
+  /**
+   * 市场价
+   */
+  midRangePrice?: number;
+
+  /**
+   * 平档价
+   */
+  standardPrice?: number;
+
+  /**
+   * 最低售价
+   */
+  certificatePrice?: number;
+
+  /**
+   * 售价验证量
+   */
+  priceVerificationQuantity?: string;
+
+  /**
+   * 采购价
+   */
+  purchasePrice?: number;
+
+  /**
+   * 暂估采购价
+   */
+  estimatedPurchasePrice?: number;
+
+  /**
+   * 产品性质
+   */
+  productNature?: string;
+
+  /**
+   * 采购人员
+   */
+  purchasingPersonnel?: string;
+
+  /**
+   * 旧属性类型
+   */
+  oldAttributeType?: string;
+
+  /**
+   * 录入套数
+   */
+  entrySetCount?: string;
+
+  /**
+   * 商品主图
+   */
+  mainImage?: string;
+
+  /**
+   * 商品详情 - 电脑端
+   */
+  pcDetail?: string;
+
+  /**
+   * 商品详情 - 移动端
+   */
+  mobileDetail?: string;
+
+  /**
+   * 税率
+   */
+  taxRate?: number;
+
+  /**
+   * 币种
+   */
+  currency?: string;
+
+  /**
+   * 最低起订量
+   */
+  minOrderQuantity?: number;
+
+  /**
+   * 审核意见
+   */
+  reviewComments?: string;
+
+  /**
+   * 商品属性值(JSON字符串)
+   */
+  attributesList?: string;
+
+}
+
+export interface BaseForm extends BaseEntity {
+  /**
+   * 主键,自增ID
+   */
+  id?: string | number;
+
+  /**
+   * 产品编号
+   */
+  productNo?: string;
+
+  /**
+   * 项目名称
+   */
+  itemName?: string;
+
+  /**
+   * 品牌id
+   */
+  brandId?: string | number;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId?: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId?: string | number;
+
+  /**
+   * 底层分类id
+   */
+  bottomCategoryId?: string | number;
+
+  /**
+   * 单位id
+   */
+  unitId?: string | number;
+
+  /**
+   * 产品图片URL
+   */
+  productImage?: string;
+
+  /**
+   * 是否自营(1=是,0=否)
+   */
+  isSelf?: number;
+
+  /**
+   * 商品类型 1=默认类型,2精选商品,3=停售商品
+   * */
+  productCategory?: number;
+
+  /**
+   * 产品审核状态 0=待采购审核,1=审核通过,2=驳回,3=待营销审核
+   */
+  productReviewStatus?: number;
+
+  /**
+   * 首页推荐:1=推荐,0=不推荐
+   */
+  homeRecommended?: number;
+
+  /**
+   * 分类推荐:1=推荐,0=不推荐
+   */
+  categoryRecommendation?: number;
+
+  /**
+   * 购物车推荐:1=推荐,0=不推荐
+   */
+  cartRecommendation?: number;
+
+  /**
+   * 推荐产品顺序
+   */
+  recommendedProductOrder?: number;
+
+  /**
+   * 是否热门:1=是,0=否
+   */
+  isPopular?: number;
+
+  /**
+   * 是否新品:1=是,0=否
+   */
+  isNew?: number;
+
+  /**
+   * 商品状态:1=已上架,0=下架,2=上架中
+   */
+  productStatus?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  /**
+   * 款号
+   */
+  styleNo?: string;
+
+  /**
+   * A10产品名称
+   */
+  a10ProductName?: string;
+
+  /**
+   * 规格型号
+   */
+  specification?: string;
+
+  /**
+   * UPC(S)条码
+   */
+  upcBarcode?: string;
+
+  /**
+   * 发票名称
+   */
+  invoiceName?: string;
+
+  /**
+   * 发票规格
+   */
+  invoiceSpec?: string;
+
+  /**
+   * 产品品牌
+   */
+  productBrand?: string;
+
+  /**
+   * 段号
+   */
+  sectionNo?: string;
+
+  /**
+   * 包装规格
+   */
+  packagingSpec?: string;
+
+  /**
+   * 采用基准
+   */
+  adoptionStandard?: string;
+
+  /**
+   * 采品性质
+   */
+  purchaseNature?: string;
+
+  /**
+   * 参考链接
+   */
+  referenceLink?: string;
+
+  /**
+   * 商品重量
+   */
+  weight?: string;
+
+  /**
+   * 重量单位
+   */
+  weightUnit?: string;
+
+  /**
+   * 商品体积
+   */
+  volume?: string;
+
+  /**
+   * 体积单位
+   */
+  volumeUnit?: string;
+
+  /**
+   * 主库简介
+   */
+  mainLibraryIntro?: string;
+
+  /**
+   * 售后服务
+   */
+  afterSalesService?: string;
+
+  /**
+   * 服务保障 支持多选,分隔 (存储服务保障ID列表,如: "1,2,3")
+   */
+  serviceGuarantee?: string;
+
+  /**
+   * 安装服务 - 免费安装
+   */
+  freeInstallation?: string;
+
+  /**
+   * 市场价
+   */
+  midRangePrice?: number;
+
+  /**
+   * 平档价
+   */
+  standardPrice?: number;
+
+  /**
+   * 最低售价
+   */
+  certificatePrice?: number;
+
+  /**
+   * 售价验证量
+   */
+  priceVerificationQuantity?: string;
+
+  /**
+   * 采购价
+   */
+  purchasePrice?: number;
+
+  /**
+   * 暂估采购价
+   */
+  estimatedPurchasePrice?: number;
+
+  /**
+   * 产品性质
+   */
+  productNature?: string;
+
+  /**
+   * 采购人员
+   */
+  purchasingPersonnel?: string;
+
+  /**
+   * 旧属性类型
+   */
+  oldAttributeType?: string;
+
+  /**
+   * 录入套数
+   */
+  entrySetCount?: string;
+
+  /**
+   * 商品主图
+   */
+  mainImage?: string;
+
+  /**
+   * 商品详情 - 电脑端
+   */
+  pcDetail?: string;
+
+  /**
+   * 商品详情 - 移动端
+   */
+  mobileDetail?: string;
+
+  /**
+   * 税率
+   */
+  taxRate?: number;
+
+  /**
+   * 币种
+   */
+  currency?: string;
+
+  /**
+   * 最低起订量
+   */
+  minOrderQuantity?: number;
+
+  /**
+   * 是否可定制
+   */
+  customizable?: boolean;
+
+  /**
+   * 定制方式(逗号分隔)
+   */
+  customizedStyle?: string;
+
+  /**
+   * 定制工艺(逗号分隔)
+   */
+  customizedCraft?: string;
+
+  /**
+   * 定制说明
+   */
+  customDescription?: string;
+
+  /**
+   * 定制详情列表(JSON字符串)
+   */
+  customDetailsJson?: string;
+
+  /**
+   * 销售量/销量人气
+   */
+  salesVolume?: number;
+
+  /**
+   * 商品属性值(JSON字符串)
+   */
+  attributesList?: string;
+
+  /**
+   * 审核意见
+   */
+  reviewComments?: string;
+
+  /**
+   * 上下架审核意见
+   */
+  shelfComments?: string;
+
+}
+
+export interface BaseQuery extends PageQuery {
+
+  /**
+   * 搜索文本(商品名称/商品编号)
+   */
+  searchText?: string;
+
+  /**
+   * 产品编号
+   */
+  productNo?: string;
+
+  /**
+   * 项目名称
+   */
+  itemName?: string;
+
+  /**
+   * 品牌id
+   */
+  brandId?: string | number;
+
+  /**
+   * 商品品牌名称
+   */
+  brandName?: string;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId?: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId?: string | number;
+
+  /**
+   * 底层分类id
+   */
+  bottomCategoryId?: string | number;
+
+  /**
+   * 单位id
+   */
+  unitId?: string | number;
+
+  /**
+   * 产品图片URL
+   */
+  productImage?: string;
+
+  /**
+   * 是否自营(1=是,0=否)
+   */
+  isSelf?: number;
+
+  /**
+   * 商品类型 1=默认类型,2精选商品,3=停售商品
+   * */
+  productCategory?: number;
+
+  /**
+   * 产品审核状态 0=待采购审核,1=审核通过,2=驳回,3=待营销审核
+   */
+  productReviewStatus?: number;
+
+  /**
+   * 首页推荐:1=推荐,0=不推荐
+   */
+  homeRecommended?: number;
+
+  /**
+   * 分类推荐:1=推荐,0=不推荐
+   */
+  categoryRecommendation?: number;
+
+  /**
+   * 购物车推荐:1=推荐,0=不推荐
+   */
+  cartRecommendation?: number;
+
+  /**
+   * 推荐产品顺序
+   */
+  recommendedProductOrder?: number;
+
+  /**
+   * 是否热门:1=是,0=否
+   */
+  isPopular?: number;
+
+  /**
+   * 是否新品:1=是,0=否
+   */
+  isNew?: number;
+
+  /**
+   * 商品状态:1=已上架,0=下架,2=上架中
+   */
+  productStatus?: number;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 商品标签
+   */
+  productTag?: string;
+
+  /**
+   * 采购性质
+   */
+  purchaseNature?: string;
+
+  /**
+   * 供应商类型
+   */
+  supplierType?: string;
+
+  /**
+   * 供应商性质
+   */
+  supplierNature?: string;
+
+  /**
+   * 项目组织
+   */
+  projectOrg?: string;
+
+
+
+    /**
+     * 日期范围参数
+     */
+    params?: any;
+}
+/**
+ * 状态数量统计视图对象
+ */
+export class StatusCountVo {
+  /**
+   * 总数
+   */
+  total: number | null = null;
+
+  /**
+   * 上架数
+   */
+  onSale: number | null = null;
+
+  /**
+   * 下架数
+   */
+  offSale: number | null = null;
+
+  /**
+   * 待审核数量
+   */
+  waitAudit: number | null = null;
+
+  /**
+   * 通过数量
+   */
+  auditPass: number | null = null;
+
+  /**
+   * 驳回数量
+   */
+  auditReject: number | null = null;
+}
+
+
+

+ 63 - 0
src/api/product/contractproduct/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { ContracproductVO, ContracproductForm, ContracproductQuery } from '@/api/product/contracproduct/types';
+
+/**
+ * 查询合同产品关联列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listContracproduct = (query?: ContracproductQuery): AxiosPromise<ContracproductVO[]> => {
+  return request({
+    url: '/product/contracproduct/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询合同产品关联详细
+ * @param id
+ */
+export const getContracproduct = (id: string | number): AxiosPromise<ContracproductVO> => {
+  return request({
+    url: '/product/contracproduct/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增合同产品关联
+ * @param data
+ */
+export const addContracproduct = (data: ContracproductForm) => {
+  return request({
+    url: '/product/contracproduct',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改合同产品关联
+ * @param data
+ */
+export const updateContracproduct = (data: ContracproductForm) => {
+  return request({
+    url: '/product/contracproduct',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除合同产品关联
+ * @param id
+ */
+export const delContracproduct = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/contracproduct/' + id,
+    method: 'delete'
+  });
+};

+ 146 - 0
src/api/product/contractproduct/types.ts

@@ -0,0 +1,146 @@
+export interface ContracproductVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 合同供货编号
+   */
+  contractSupplyNo: string;
+
+  /**
+   * 产品编号
+   */
+  productNo: string;
+
+  /**
+   * 产品id
+   */
+  productId: string | number;
+
+  /**
+   * 供货周期(单位:天/月,根据业务定义)
+   */
+  supplyCycle: number;
+
+  /**
+   * 库存属性
+   */
+  inventoryProperties: string;
+
+  /**
+   * 最小供货量
+   */
+  minSupply: number;
+
+  /**
+   * 报价(支持大文本)
+   */
+  offerPrice: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+}
+
+export interface ContracproductForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 合同供货编号
+   */
+  contractSupplyNo?: string;
+
+  /**
+   * 产品编号
+   */
+  productNo?: string;
+
+  /**
+   * 产品id
+   */
+  productId?: string | number;
+
+  /**
+   * 供货周期(单位:天/月,根据业务定义)
+   */
+  supplyCycle?: number;
+
+  /**
+   * 库存属性
+   */
+  inventoryProperties?: string;
+
+  /**
+   * 最小供货量
+   */
+  minSupply?: number;
+
+  /**
+   * 报价(支持大文本)
+   */
+  offerPrice?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+}
+
+export interface ContracproductQuery extends PageQuery {
+
+  /**
+   * 合同供货编号
+   */
+  contractSupplyNo?: string;
+
+  /**
+   * 产品编号
+   */
+  productNo?: string;
+
+  /**
+   * 产品id
+   */
+  productId?: string | number;
+
+  /**
+   * 供货周期(单位:天/月,根据业务定义)
+   */
+  supplyCycle?: number;
+
+  /**
+   * 库存属性
+   */
+  inventoryProperties?: string;
+
+  /**
+   * 最小供货量
+   */
+  minSupply?: number;
+
+  /**
+   * 报价(支持大文本)
+   */
+  offerPrice?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+    /**
+     * 日期范围参数
+     */
+    params?: any;
+}
+
+
+

+ 12 - 0
src/api/supplier/contact/index.ts

@@ -61,3 +61,15 @@ export const delContact = (id: string | number | Array<string | number>) => {
     method: 'delete'
   });
 };
+
+/**
+ * 重置联系人密码
+ * @param data
+ */
+export const resetContactPassword = (data: { userId: string | number; newPassword: string }) => {
+  return request({
+    url: '/customer/contact/resetPassword',
+    method: 'put',
+    data: data
+  });
+};

+ 99 - 0
src/api/supplier/contact/types.ts

@@ -1,9 +1,19 @@
 export interface ContactVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
   /**
    * 供应商编号
    */
   supplierNo: string;
 
+  /**
+   * 供应商名称
+   */
+  supplierName: string;
+
   /**
    * 用户ID
    */
@@ -52,6 +62,90 @@ export interface ContactVO {
 }
 
 export interface ContactForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 供应商ID
+   */
+  supplierId?: string | number;
+
+  /**
+   * 供应商编号
+   */
+  supplierNo?: string;
+
+  /**
+   * 用户ID
+   */
+  userNo?: string;
+
+  /**
+   * 员工姓名
+   */
+  userName?: string;
+
+  /**
+   * 密码
+   */
+  password?: string;
+
+  /**
+   * 手机号
+   */
+  phone?: string;
+
+  /**
+   * 办公电话
+   */
+  officePhone?: string;
+
+  /**
+   * 角色
+   */
+  roleNo?: string;
+
+  /**
+   * 部门
+   */
+  departmentNo?: string;
+
+  /**
+   * 职位
+   */
+  position?: string;
+
+  /**
+   * 性别
+   */
+  gender?: string;
+
+  /**
+   * 主要联系人
+   */
+  isPrimaryContact?: string;
+
+  /**
+   * 允许登录供应商端
+   */
+  isRegister?: string;
+
+  /**
+   * 人员描述
+   */
+  userDescribe?: string;
+
+  /**
+   * 联系地址
+   */
+  connAddr?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
 }
 
 export interface ContactQuery extends PageQuery {
@@ -61,6 +155,11 @@ export interface ContactQuery extends PageQuery {
    */
   supplierNo?: string;
 
+  /**
+   * 供应商名称
+   */
+  supplierName?: string;
+
   /**
    * 员工姓名
    */

+ 69 - 0
src/api/supplier/contractsupply/types.ts

@@ -1,4 +1,9 @@
 export interface ContractsupplyVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
   /**
    * 协议单号
    */
@@ -9,6 +14,11 @@ export interface ContractsupplyVO {
    */
   supplyNo: string;
 
+  /**
+   * 供应商名称
+   */
+  supplierName: string;
+
   /**
    * 商品数量
    */
@@ -24,6 +34,11 @@ export interface ContractsupplyVO {
    */
   endTime: string;
 
+  /**
+   * 剩余时限(天)
+   */
+  timeRemaining: number;
+
   /**
    * 状态(0正常 1停用)
    */
@@ -32,6 +47,60 @@ export interface ContractsupplyVO {
 }
 
 export interface ContractsupplyForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 协议单号
+   */
+  contractSupplyNo?: string;
+
+  /**
+   * 所属公司ID
+   */
+  companyId?: string | number;
+
+  /**
+   * 供应商ID
+   */
+  supplierId?: string | number;
+
+  /**
+   * 供应商名称
+   */
+  supplierName?: string;
+
+  /**
+   * 开始时间
+   */
+  startTime?: string;
+
+  /**
+   * 结束时间
+   */
+  endTime?: string;
+
+  /**
+   * 附件
+   */
+  attachment?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  /**
+   * 是否提交
+   */
+  isSubmit?: boolean;
+
+  /**
+   * 状态(0驳回 1生效)
+   */
+  status?: number | string;
 }
 
 export interface ContractsupplyQuery extends PageQuery {

+ 12 - 0
src/router/index.ts

@@ -120,6 +120,18 @@ export const constantRoutes: RouteRecordRaw[] = [
         component: () => import('@/views/supplier/contract/add.vue'),
         name: 'SupplierContractAdd',
         meta: { title: '创建合同', activeMenu: '/supplier/contract' }
+      },
+      {
+        path: 'contractsupply/add',
+        component: () => import('@/views/supplier/contractsupply/add.vue'),
+        name: 'SupplierContractsupplyAdd',
+        meta: { title: '新增合约供货', activeMenu: '/supplier/contractsupply' }
+      },
+      {
+        path: 'contractsupply/edit/:id',
+        component: () => import('@/views/supplier/contractsupply/edit.vue'),
+        name: 'SupplierContractsupplyEdit',
+        meta: { title: '编辑合约供货', activeMenu: '/supplier/contractsupply' }
       }
     ]
   }

+ 32 - 2
src/views/supplier/approve/index.vue

@@ -102,8 +102,8 @@
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['customer:info:query']">查看</el-button>
-            <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['customer:info:edit']">编辑</el-button>
-            <el-button link type="primary" @click="handleStopCooperation(scope.row)" v-hasPermi="['customer:info:edit']">停止合作</el-button>
+            <el-button link type="primary" @click="handleApprove(scope.row)" v-hasPermi="['customer:info:edit']">审核通过</el-button>
+            <el-button link type="primary" @click="handleReject(scope.row)" v-hasPermi="['customer:info:edit']">驳回</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -755,6 +755,36 @@ const handleView = (row: InfoVO) => {
   });
 }
 
+/** 审核通过按钮操作 */
+const handleApprove = async (row: InfoVO) => {
+  await proxy?.$modal.confirm('是否确认审核通过供应商"' + row.enterpriseName + '"?');
+  try {
+    await updateInfo({ 
+      ...row,
+      supplyStatus: 1 
+    });
+    proxy?.$modal.msgSuccess("审核通过成功");
+    await getList();
+  } catch (e) {
+    console.error('审核通过失败:', e);
+  }
+}
+
+/** 驳回按钮操作 */
+const handleReject = async (row: InfoVO) => {
+  await proxy?.$modal.confirm('是否确认驳回供应商"' + row.enterpriseName + '"?');
+  try {
+    await updateInfo({ 
+      ...row,
+      supplyStatus: 3 
+    });
+    proxy?.$modal.msgSuccess("驳回成功");
+    await getList();
+  } catch (e) {
+    console.error('驳回失败:', e);
+  }
+}
+
 /** 停止合作按钮操作 */
 const handleStopCooperation = async (row: InfoVO) => {
   await proxy?.$modal.confirm('是否确认停止与供应商"' + row.enterpriseName + '"的合作?');

+ 241 - 26
src/views/supplier/contact/index.vue

@@ -7,8 +7,11 @@
             <el-form-item label="供应商编号" prop="supplierNo">
               <el-input v-model="queryParams.supplierNo" placeholder="请输入供应商编号" clearable @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="员工姓名" prop="userName">
-              <el-input v-model="queryParams.userName" placeholder="请输入员工姓名" clearable @keyup.enter="handleQuery" />
+            <el-form-item label="供应商名称" prop="supplierName">
+              <el-input v-model="queryParams.supplierName" placeholder="请输入供应商名称" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="联系人" prop="userName">
+              <el-input v-model="queryParams.userName" placeholder="联系人" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="手机号" prop="phone">
               <el-input v-model="queryParams.phone" placeholder="请输入手机号" clearable @keyup.enter="handleQuery" />
@@ -24,21 +27,7 @@
 
     <el-card shadow="never">
       <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['supplier:contact:add']">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['supplier:contact:edit']">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['supplier:contact:remove']">删除</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplier:contact:export']">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
+        业务联系人
       </template>
 
       <el-table v-loading="loading" border :data="contactList" @selection-change="handleSelectionChange">
@@ -65,21 +54,110 @@
         <el-table-column label="状态" align="center" prop="status" />
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['supplier:contact:edit']"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['supplier:contact:remove']"></el-button>
-            </el-tooltip>
+            <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['supplier:contact:edit']">编辑</el-button>
+            <br />
+            <el-button link type="primary" @click="handleResetPassword(scope.row)">重置密码</el-button>
           </template>
         </el-table-column>
       </el-table>
 
       <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
-    <!-- 添加或修改联系人对话框 -->
-    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
-      <el-form ref="contactFormRef" :model="form" :rules="rules" label-width="80px">
+    <!-- 修改联系人对话框 -->
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="900px" append-to-body>
+      <el-form ref="contactFormRef" :model="form" :rules="rules" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="供应商" prop="supplierId">
+              <el-select v-model="form.supplierId" placeholder="请选择供应商" style="width: 100%;" filterable :disabled="!!form.id">
+                <el-option
+                  v-for="item in supplierList"
+                  :key="item.id"
+                  :label="item.enterpriseName"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="员工姓名" prop="userName">
+              <el-input v-model="form.userName" placeholder="请输入员工姓名" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="电话" prop="phone">
+              <el-input v-model="form.phone" placeholder="请输入电话" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="办公电话" prop="officePhone">
+              <el-input v-model="form.officePhone" placeholder="请输入办公电话" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="角色" prop="roleNo">
+              <el-input v-model="form.roleNo" placeholder="请输入角色" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="部门" prop="departmentNo">
+              <el-input v-model="form.departmentNo" placeholder="请输入部门" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="职位" prop="position">
+              <el-input v-model="form.position" placeholder="请输入职位" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="性别" prop="gender">
+              <el-radio-group v-model="form.gender">
+                <el-radio label="0">男</el-radio>
+                <el-radio label="1">女</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="主要联系人" prop="isPrimaryContact">
+              <el-radio-group v-model="form.isPrimaryContact">
+                <el-radio label="0">是</el-radio>
+                <el-radio label="1">否</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="允许登录" prop="isRegister">
+              <el-radio-group v-model="form.isRegister">
+                <el-radio label="0">是</el-radio>
+                <el-radio label="1">否</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="人员描述" prop="userDescribe">
+              <el-input v-model="form.userDescribe" type="textarea" :rows="3" placeholder="请输入人员描述" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="联系地址" prop="connAddr">
+              <el-input v-model="form.connAddr" type="textarea" :rows="3" placeholder="请输入联系地址" />
+            </el-form-item>
+          </el-col>
+        </el-row>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -88,17 +166,37 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 重置密码对话框 -->
+    <el-dialog title="重置密码" v-model="resetPasswordDialog.visible" width="500px" append-to-body>
+      <el-form ref="resetPasswordFormRef" :model="resetPasswordForm" :rules="resetPasswordRules" label-width="100px">
+        <el-form-item label="新密码" prop="newPassword">
+          <el-input v-model="resetPasswordForm.newPassword" type="password" placeholder="请输入新密码" show-password />
+        </el-form-item>
+        <el-form-item label="确认密码" prop="confirmPassword">
+          <el-input v-model="resetPasswordForm.confirmPassword" type="password" placeholder="请输入确认密码" show-password />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="confirmResetPassword">确 认</el-button>
+          <el-button @click="cancelResetPassword">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="Contact" lang="ts">
 import { listContact, getContact, delContact, addContact, updateContact } from '@/api/supplier/contact';
 import { ContactVO, ContactQuery, ContactForm } from '@/api/supplier/contact/types';
+import { listInfo } from '@/api/customer/info';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { is_primary_contack, is_register } = toRefs<any>(proxy?.useDict('is_primary_contack', 'is_register'));
 
 const contactList = ref<ContactVO[]>([]);
+const supplierList = ref<any[]>([]);
 const buttonLoading = ref(false);
 const loading = ref(true);
 const showSearch = ref(true);
@@ -115,7 +213,54 @@ const dialog = reactive<DialogOption>({
   title: ''
 });
 
+const resetPasswordDialog = reactive({
+  visible: false,
+  userId: '',
+  userName: ''
+});
+
+const resetPasswordForm = ref({
+  newPassword: '',
+  confirmPassword: ''
+});
+
+const resetPasswordRules = {
+  newPassword: [
+    { required: true, message: '请输入新密码', trigger: 'blur' },
+    { min: 6, message: '密码长度不能少于6位', trigger: 'blur' }
+  ],
+  confirmPassword: [
+    { required: true, message: '请输入确认密码', trigger: 'blur' },
+    { 
+      validator: (rule: any, value: any, callback: any) => {
+        if (value !== resetPasswordForm.value.newPassword) {
+          callback(new Error('两次输入的密码不一致'));
+        } else {
+          callback();
+        }
+      }, 
+      trigger: 'blur' 
+    }
+  ]
+};
+
+const resetPasswordFormRef = ref<ElFormInstance>();
+
 const initFormData: ContactForm = {
+  id: undefined,
+  supplierId: undefined,
+  userName: undefined,
+  phone: undefined,
+  officePhone: undefined,
+  roleNo: undefined,
+  departmentNo: undefined,
+  position: undefined,
+  gender: '0',
+  isPrimaryContact: '1',
+  isRegister: '1',
+  userDescribe: undefined,
+  connAddr: undefined,
+  status: undefined
 }
 const data = reactive<PageData<ContactForm, ContactQuery>>({
   form: {...initFormData},
@@ -123,6 +268,7 @@ const data = reactive<PageData<ContactForm, ContactQuery>>({
     pageNum: 1,
     pageSize: 10,
     supplierNo: undefined,
+    supplierName: undefined,
     userName: undefined,
     phone: undefined,
     status: undefined,
@@ -130,6 +276,22 @@ const data = reactive<PageData<ContactForm, ContactQuery>>({
     }
   },
   rules: {
+    supplierId: [
+      { required: true, message: '请选择供应商', trigger: 'change' }
+    ],
+    userName: [
+      { required: true, message: '请输入员工姓名', trigger: 'blur' }
+    ],
+    phone: [
+      { required: true, message: '请输入电话', trigger: 'blur' },
+      { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
+    ],
+    isPrimaryContact: [
+      { required: true, message: '请选择是否为主要联系人', trigger: 'change' }
+    ],
+    isRegister: [
+      { required: true, message: '请选择是否允许登录', trigger: 'change' }
+    ]
   }
 });
 
@@ -144,6 +306,16 @@ const getList = async () => {
   loading.value = false;
 }
 
+/** 获取供应商列表 */
+const getSupplierList = async () => {
+  try {
+    const res = await listInfo();
+    supplierList.value = res.rows || [];
+  } catch (e) {
+    console.error('获取供应商列表失败:', e);
+  }
+}
+
 /** 取消按钮 */
 const cancel = () => {
   reset();
@@ -192,6 +364,48 @@ const handleUpdate = async (row?: ContactVO) => {
   dialog.title = "修改联系人";
 }
 
+/** 重置密码按钮操作 */
+const handleResetPassword = (row: ContactVO) => {
+  resetPasswordDialog.userId = String(row.id);
+  resetPasswordDialog.userName = row.userName;
+  resetPasswordForm.value = {
+    newPassword: '',
+    confirmPassword: ''
+  };
+  resetPasswordDialog.visible = true;
+}
+
+/** 确认重置密码 */
+const confirmResetPassword = () => {
+  resetPasswordFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      try {
+        await updateContact({ 
+          id: resetPasswordDialog.userId, 
+          password: resetPasswordForm.value.newPassword 
+        });
+        proxy?.$modal.msgSuccess("重置密码成功");
+        resetPasswordDialog.visible = false;
+        resetPasswordForm.value = {
+          newPassword: '',
+          confirmPassword: ''
+        };
+      } catch (e) {
+        console.error('重置密码失败:', e);
+      }
+    }
+  });
+}
+
+/** 取消重置密码 */
+const cancelResetPassword = () => {
+  resetPasswordDialog.visible = false;
+  resetPasswordForm.value = {
+    newPassword: '',
+    confirmPassword: ''
+  };
+}
+
 /** 提交按钮 */
 const submitForm = () => {
   contactFormRef.value?.validate(async (valid: boolean) => {
@@ -227,5 +441,6 @@ const handleExport = () => {
 
 onMounted(() => {
   getList();
+  getSupplierList();
 });
 </script>

+ 8 - 48
src/views/supplier/contract/add.vue

@@ -124,21 +124,12 @@
         <el-row :gutter="20">
           <el-col :span="24">
             <el-form-item label="合同附件" prop="contractAttachment">
-              <el-button type="primary" plain @click="openFileManager">
-                <el-icon><Upload /></el-icon>
-                上传附件
-              </el-button>
-              <div v-if="selectedFiles.length > 0" style="margin-top: 10px;">
-                <el-tag 
-                  v-for="(file, index) in selectedFiles" 
-                  :key="index"
-                  closable
-                  @close="removeFile(index)"
-                  style="margin-right: 10px; margin-bottom: 5px;"
-                >
-                  {{ file.name }}
-                </el-tag>
-              </div>
+              <FileUpload 
+                v-model="form.contractAttachment" 
+                :file-type="['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf']"
+                :file-size="50"
+                :limit="10"
+              />
             </el-form-item>
           </el-col>
         </el-row>
@@ -163,32 +154,17 @@
         </el-row>
       </el-form>
     </el-card>
-
-    <!-- 文件管理对话框 -->
-    <el-dialog 
-      v-model="showFileDialog" 
-      title="选择文件" 
-      width="80%" 
-      :close-on-click-modal="false"
-    >
-      <iframe 
-        :src="'/file/info'" 
-        style="width: 100%; height: 600px; border: none;"
-      />
-      <template #footer>
-        <el-button @click="showFileDialog = false">关闭</el-button>
-      </template>
-    </el-dialog>
   </div>
 </template>
 
 <script setup lang="ts">
 import { ref, onMounted } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
-import { ArrowLeft, Upload } from '@element-plus/icons-vue';
+import { ArrowLeft } from '@element-plus/icons-vue';
 import { getDictData, getTaxRateList, getSettlementMethodList, getInvoiceTypeList } from '@/api/customer/info';
 import { addContract } from '@/api/supplier/contract';
 import { ElMessage } from 'element-plus';
+import FileUpload from '@/components/FileUpload/index.vue';
 
 const route = useRoute();
 const router = useRouter();
@@ -198,8 +174,6 @@ const contractTypeDict = ref<any[]>([]);
 const taxRateList = ref<any[]>([]);
 const settlementMethodList = ref<any[]>([]);
 const invoiceTypeList = ref<any[]>([]);
-const selectedFiles = ref<any[]>([]);
-const showFileDialog = ref(false);
 
 const form = ref({
   supplierId: '',
@@ -279,20 +253,6 @@ const getInvoiceTypeData = async () => {
   }
 };
 
-/** 打开文件管理页面 */
-const openFileManager = () => {
-  // 打开文件管理对话框
-  showFileDialog.value = true;
-};
-
-/** 移除文件 */
-const removeFile = (index: number) => {
-  selectedFiles.value.splice(index, 1);
-  // 更新表单中的附件字段
-  const urls = selectedFiles.value.map(f => f.url).join(',');
-  form.value.contractAttachment = urls;
-};
-
 /** 提交表单 */
 const handleSubmit = async () => {
   formRef.value?.validate(async (valid: boolean) => {

+ 512 - 0
src/views/supplier/contractsupply/add.vue

@@ -0,0 +1,512 @@
+<template>
+  <div class="app-container">
+    <!-- 页面头部 -->
+    <div class="detail-header">
+      <el-icon class="back-icon" @click="goBack"><ArrowLeft /></el-icon>
+      <span class="header-title">新增合约供货</span>
+    </div>
+
+    <!-- 表单卡片 -->
+    <el-card shadow="never" class="form-card">
+      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="所属公司" prop="companyId">
+              <el-select v-model="form.companyId" placeholder="请选择" style="width: 100%;">
+                <el-option
+                  v-for="item in companyList"
+                  :key="item.id"
+                  :label="item.companyName"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="供应商" prop="supplierId">
+              <el-select v-model="form.supplierId" placeholder="请选择" style="width: 100%;" @change="handleSupplierChange">
+                <el-option
+                  v-for="item in supplierList"
+                  :key="item.id"
+                  :label="item.enterpriseName"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="开始时间" prop="startTime">
+              <el-date-picker
+                v-model="form.startTime"
+                type="date"
+                placeholder="请选择"
+                value-format="YYYY-MM-DD"
+                style="width: 100%;"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="结束时间" prop="endTime">
+              <el-date-picker
+                v-model="form.endTime"
+                type="date"
+                placeholder="请选择"
+                value-format="YYYY-MM-DD"
+                style="width: 100%;"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="附件" prop="attachment">
+              <FileUpload 
+                v-model="form.proFile" 
+                :limit="10"
+                :file-size="50"
+                :file-type="['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf']"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="备注" prop="remark">
+              <el-input 
+                v-model="form.remark" 
+                type="textarea" 
+                :rows="4"
+                placeholder="请输入内容"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <!-- 商品列表 -->
+        <div class="section-title">
+          <el-button type="primary" @click="handleAddProduct">添加商品信息</el-button>
+          <el-button type="success" @click="handleImport">导入</el-button>
+          <el-button type="warning" @click="handleExport">导出</el-button>
+        </div>
+
+        <el-table :data="productList" border style="width: 100%; margin-top: 20px;">
+          <el-table-column prop="productCode" label="产品编号" align="center" width="120" />
+          <el-table-column label="产品图片" align="center" width="100">
+            <template #default="scope">
+              <el-image 
+                v-if="scope.row.productImage" 
+                :src="scope.row.productImage" 
+                style="width: 60px; height: 60px;"
+                fit="cover"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column prop="productName" label="产品名称" align="center" show-overflow-tooltip />
+          <el-table-column prop="productType" label="产品类型" align="center" width="120" />
+          <el-table-column prop="brand" label="品牌" align="center" width="100" />
+          <el-table-column prop="unit" label="单位" align="center" width="80" />
+          <el-table-column prop="marketPrice" label="市场价" align="center" width="100" />
+          <el-table-column prop="platformPrice" label="平台价" align="center" width="100" />
+          <el-table-column label="供应价(元)" align="center" width="120">
+            <template #default="scope">
+              <el-input v-model="scope.row.offerPrice" placeholder="请输入" />
+            </template>
+          </el-table-column>
+          <el-table-column label="供应时效" align="center" width="120">
+            <template #default="scope">
+              <el-input v-model="scope.row.supplyCycle" placeholder="请输入" />
+            </template>
+          </el-table-column>
+          <el-table-column label="上架状态" align="center" width="100">
+            <template #default="scope">
+              <span>{{ scope.row.upPrice }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="100" fixed="right">
+            <template #default="scope">
+              <el-button link type="primary" @click="handleDeleteProduct(scope.$index)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <div style="text-align: center; margin-top: 20px;">
+          <el-checkbox v-model="form.isSubmit">提交</el-checkbox>
+        </div>
+
+        <el-row style="margin-top: 20px;">
+          <el-col :span="24" style="text-align: center;">
+            <el-button type="primary" @click="handleSubmit">提交</el-button>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+
+    <!-- 添加商品对话框 -->
+    <el-dialog title="添加商品报价" v-model="productDialog.visible" width="90%" append-to-body>
+      <div class="mb-4">
+        <el-form :inline="true" :model="productQuery">
+          <el-form-item label="产品编号">
+            <el-input v-model="productQuery.productNo" placeholder="请输入产品编号" clearable style="width: 200px;" />
+          </el-form-item>
+          <el-form-item label="产品名称">
+            <el-input v-model="productQuery.itemName" placeholder="请输入产品名称" clearable style="width: 200px;" />
+          </el-form-item>
+          <el-form-item label="品牌名称">
+            <el-input v-model="productQuery.brandName" placeholder="请输入品牌名称" clearable style="width: 200px;" />
+          </el-form-item>
+          <el-form-item label="上架状态">
+            <el-select v-model="productQuery.productStatus" placeholder="请选择" clearable style="width: 150px;">
+              <el-option label="上架" :value="1" />
+              <el-option label="下架" :value="0" />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="Search" @click="handleProductQuery">搜索</el-button>
+            <el-button icon="Refresh" @click="resetProductQuery">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <el-table 
+        :data="productListData" 
+        border 
+        style="width: 100%;"
+        @selection-change="handleProductSelectionChange"
+      >
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column prop="productNo" label="产品编号" align="center" width="120" />
+        <el-table-column label="产品图片" align="center" width="100">
+          <template #default="scope">
+            <el-image 
+              v-if="scope.row.productImage" 
+              :src="scope.row.productImage" 
+              style="width: 60px; height: 60px;"
+              fit="cover"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column prop="itemName" label="产品名称" align="center" show-overflow-tooltip />
+        <el-table-column prop="brandName" label="品牌" align="center" width="120" />
+        <el-table-column prop="unitName" label="单位" align="center" width="80" />
+        <el-table-column prop="marketPrice" label="市场价" align="center" width="100" />
+        <el-table-column prop="memberPrice" label="平台价" align="center" width="100" />
+        <el-table-column prop="minOrderQuantity" label="起订量" align="center" width="100" />
+        <el-table-column label="上架状态" align="center" width="100">
+          <template #default="scope">
+            <span>{{ scope.row.productStatus === 1 ? '上架' : '下架' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" width="100">
+          <template #default="scope">
+            <el-button link type="primary" @click="handleAddToList(scope.row)">加入清单</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination 
+        v-show="productTotal > 0" 
+        :total="productTotal" 
+        v-model:page="productQuery.pageNum" 
+        v-model:limit="productQuery.pageSize"
+        @pagination="getProductList" 
+      />
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="handleBatchAdd">批量加入清单</el-button>
+          <el-button @click="productDialog.visible = false">关 闭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, reactive } from 'vue';
+import { useRouter } from 'vue-router';
+import { ArrowLeft } from '@element-plus/icons-vue';
+import { addContractsupply } from '@/api/supplier/contractsupply';
+import { getCompanyList, listInfo } from '@/api/customer/info';
+import { listBase } from '@/api/product/base';
+import { ElMessage } from 'element-plus';
+import FileUpload from '@/components/FileUpload/index.vue';
+
+const router = useRouter();
+
+const formRef = ref();
+const productList = ref<any[]>([]);
+const companyList = ref<any[]>([]);
+const supplierList = ref<any[]>([]);
+
+// 商品对话框相关
+const productDialog = reactive({
+  visible: false
+});
+
+const productListData = ref<any[]>([]);
+const productTotal = ref(0);
+const selectedProducts = ref<any[]>([]);
+
+const productQuery = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  productNo: '',
+  itemName: '',
+  brandName: '',
+  productStatus: undefined as number | undefined
+});
+
+const form = ref({
+  companyId: '',
+  supplierId: '',
+  supplyNo: '',
+  startTime: '',
+  endTime: '',
+  attachment: '',
+  remark: '',
+  isSubmit: false
+});
+
+const rules = {
+  supplierId: [
+    { required: true, message: '请选择供应商', trigger: 'change' }
+  ]
+};
+
+/** 返回上一页 */
+const goBack = () => {
+  router.back();
+};
+
+/** 获取公司列表 */
+const getCompanyData = async () => {
+  try {
+    const res = await getCompanyList();
+    companyList.value = res.data || [];
+  } catch (e) {
+    console.error('获取公司列表失败:', e);
+  }
+};
+
+/** 获取供应商列表 */
+const getSupplierData = async () => {
+  try {
+    const res = await listInfo();
+    supplierList.value = res.rows || [];
+  } catch (e) {
+    console.error('获取供应商列表失败:', e);
+  }
+};
+
+/** 供应商选择变化 */
+const handleSupplierChange = (value: any) => {
+  const supplier = supplierList.value.find(item => String(item.id) === String(value));
+  if (supplier) {
+    form.value.supplyNo = supplier.supplierNo || '';
+  }
+};
+
+/** 添加商品 */
+const handleAddProduct = () => {
+  productDialog.visible = true;
+  // 不再重新获取商品列表,使用已加载的数据
+};
+
+/** 获取商品列表 */
+const getProductList = async () => {
+  try {
+    const res = await listBase(productQuery);
+    productListData.value = res.rows || [];
+    productTotal.value = res.total || 0;
+  } catch (e) {
+    console.error('获取商品列表失败:', e);
+    ElMessage.error('获取商品列表失败');
+  }
+};
+
+/** 商品查询 */
+const handleProductQuery = () => {
+  productQuery.pageNum = 1;
+  getProductList();
+};
+
+/** 重置商品查询 */
+const resetProductQuery = () => {
+  productQuery.productNo = '';
+  productQuery.itemName = '';
+  productQuery.brandName = '';
+  productQuery.productStatus = undefined;
+  handleProductQuery();
+};
+
+/** 商品多选 */
+const handleProductSelectionChange = (selection: any[]) => {
+  selectedProducts.value = selection;
+};
+
+/** 加入清单 */
+const handleAddToList = (row: any) => {
+  // 检查是否已存在
+  const exists = productList.value.some(item => item.productId === row.id);
+  if (exists) {
+    ElMessage.warning('该商品已在清单中');
+    return;
+  }
+  
+  // 添加到本地清单(不调用API)
+  productList.value.push({
+    productId: row.id,
+    productCode: row.productNo,
+    productImage: row.productImage,
+    productName: row.itemName,
+    productType: row.categoryName,
+    brand: row.brandName,
+    unit: row.unitName,
+    basePrice: row.purchasingPrice || 0,
+    marketPrice: row.marketPrice || 0,
+    platformPrice: row.memberPrice || 0,
+    supplyPrice: '',
+    supplyCycle: '',
+    upPrice: row.productStatus === 1 ? '上架' : '下架'
+  });
+  
+  ElMessage.success('添加成功');
+};
+
+/** 批量加入清单 */
+const handleBatchAdd = () => {
+  if (selectedProducts.value.length === 0) {
+    ElMessage.warning('请选择要添加的商品');
+    return;
+  }
+  
+  let successCount = 0;
+  
+  selectedProducts.value.forEach(row => {
+    const exists = productList.value.some(item => item.productId === row.id);
+    if (!exists) {
+      // 添加到本地清单(不调用API)
+      productList.value.push({
+        productId: row.id,
+        productCode: row.productNo,
+        productImage: row.productImage,
+        productName: row.itemName,
+        productType: row.categoryName,
+        brand: row.brandName,
+        unit: row.unitName,
+        basePrice: row.purchasingPrice || 0,
+        marketPrice: row.marketPrice || 0,
+        platformPrice: row.memberPrice || 0,
+        supplyPrice: '',
+        supplyCycle: '',
+        upPrice: row.productStatus === 1 ? '上架' : '下架'
+      });
+      
+      successCount++;
+    }
+  });
+  
+  ElMessage.success(`成功添加${successCount}个商品`);
+  productDialog.visible = false;
+};
+
+/** 导入 */
+const handleImport = () => {
+  console.log('导入');
+  // TODO: 实现导入功能
+};
+
+/** 导出 */
+const handleExport = () => {
+  console.log('导出');
+  // TODO: 实现导出功能
+};
+
+/** 删除商品 */
+const handleDeleteProduct = (index: number) => {
+  productList.value.splice(index, 1);
+};
+
+/** 提交表单 */
+const handleSubmit = async () => {
+  formRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      try {
+        // 组装提交数据,包含表单数据和商品列表
+        const submitData = {
+          ...form.value,
+          contractProduct: productList.value.map(item => ({
+            productId: item.productId,
+            productNo: item.productCode,
+            offerPrice: item.supplyPrice,
+            supplyCycle: item.supplyCycle
+          }))
+        };
+        
+        await addContractsupply(submitData);
+        ElMessage.success('新增成功');
+        router.back();
+      } catch (e) {
+        console.error('新增失败:', e);
+        ElMessage.error('新增失败');
+      }
+    }
+  });
+};
+
+onMounted(() => {
+  getCompanyData();
+  getSupplierData();
+  getProductList(); // 页面加载时获取商品列表
+});
+</script>
+
+<style scoped>
+.app-container {
+  background: #f0f2f5;
+  min-height: 100vh;
+  padding: 0;
+}
+
+.detail-header {
+  background: #fff;
+  padding: 16px 24px;
+  display: flex;
+  align-items: center;
+  border-bottom: 1px solid #e8e8e8;
+  margin-bottom: 16px;
+}
+
+.back-icon {
+  font-size: 18px;
+  cursor: pointer;
+  margin-right: 12px;
+  color: #666;
+}
+
+.back-icon:hover {
+  color: #409eff;
+}
+
+.header-title {
+  font-size: 16px;
+  font-weight: 500;
+  color: #333;
+}
+
+.form-card {
+  margin: 16px;
+  padding: 24px;
+}
+
+.section-title {
+  margin: 20px 0;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #e8e8e8;
+}
+</style>

+ 555 - 0
src/views/supplier/contractsupply/edit.vue

@@ -0,0 +1,555 @@
+<template>
+  <div class="app-container">
+    <!-- 页面头部 -->
+    <div class="detail-header">
+      <el-icon class="back-icon" @click="goBack"><ArrowLeft /></el-icon>
+      <span class="header-title">编辑合约供货</span>
+    </div>
+
+    <!-- 表单卡片 -->
+    <el-card shadow="never" class="form-card">
+      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="协议编号" prop="contractSupplyNo">
+              <span>{{ form.contractSupplyNo }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="所属公司" prop="companyId">
+              <el-select v-model="form.companyId" placeholder="请选择" style="width: 100%;">
+                <el-option
+                  v-for="item in companyList"
+                  :key="item.id"
+                  :label="item.companyName"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="供应商" prop="supplierId">
+              <el-select v-model="form.supplierId" placeholder="请选择" style="width: 100%;">
+                <el-option
+                  v-for="item in supplierList"
+                  :key="item.id"
+                  :label="item.enterpriseName"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="开始时间" prop="startTime">
+              <el-date-picker
+                v-model="form.startTime"
+                type="date"
+                placeholder="请选择"
+                value-format="YYYY-MM-DD"
+                style="width: 100%;"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="结束时间" prop="endTime">
+              <el-date-picker
+                v-model="form.endTime"
+                type="date"
+                placeholder="请选择"
+                value-format="YYYY-MM-DD"
+                style="width: 100%;"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="附件" prop="attachment">
+              <FileUpload 
+                v-model="form.attachment" 
+                :limit="10"
+                :file-size="50"
+                :file-type="['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf']"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="备注" prop="remark">
+              <el-input 
+                v-model="form.remark" 
+                type="textarea" 
+                :rows="4"
+                placeholder="请输入内容"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <!-- 商品列表 -->
+        <div class="section-title">
+          <el-button type="primary" @click="handleAddProduct">添加商品信息</el-button>
+          <el-button type="success" @click="handleImport">导入</el-button>
+          <el-button type="warning" @click="handleExport">导出</el-button>
+        </div>
+
+        <el-table :data="productList" border style="width: 100%; margin-top: 20px;">
+          <el-table-column prop="productCode" label="产品编号" align="center" width="120" />
+          <el-table-column label="产品图片" align="center" width="100">
+            <template #default="scope">
+              <el-image 
+                v-if="scope.row.productImage" 
+                :src="scope.row.productImage" 
+                style="width: 60px; height: 60px;"
+                fit="cover"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column prop="productName" label="产品名称" align="center" show-overflow-tooltip />
+          <el-table-column prop="productType" label="产品类型" align="center" width="120" />
+          <el-table-column prop="brand" label="品牌" align="center" width="100" />
+          <el-table-column prop="unit" label="单位" align="center" width="80" />
+          <el-table-column prop="marketPrice" label="市场价" align="center" width="100" />
+          <el-table-column prop="platformPrice" label="平台价" align="center" width="100" />
+          <el-table-column label="供应价(元)" align="center" width="120">
+            <template #default="scope">
+              <el-input v-model="scope.row.supplyPrice" placeholder="请输入" />
+            </template>
+          </el-table-column>
+          <el-table-column label="供应时效" align="center" width="120">
+            <template #default="scope">
+              <el-input v-model="scope.row.supplyCycle" placeholder="请输入" />
+            </template>
+          </el-table-column>
+          <el-table-column label="上架状态" align="center" width="100">
+            <template #default="scope">
+              <span>{{ scope.row.upPrice }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="100" fixed="right">
+            <template #default="scope">
+              <el-button link type="primary" @click="handleDeleteProduct(scope.$index)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <div style="text-align: center; margin-top: 20px;">
+          <el-checkbox v-model="form.isSubmit">提交</el-checkbox>
+        </div>
+
+        <el-row style="margin-top: 20px;">
+          <el-col :span="24" style="text-align: center;">
+            <el-button type="primary" @click="handleSubmit">提交</el-button>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+
+    <!-- 添加商品对话框 -->
+    <el-dialog title="添加商品报价" v-model="productDialog.visible" width="90%" append-to-body>
+      <div class="mb-4">
+        <el-form :inline="true" :model="productQuery">
+          <el-form-item label="产品编号">
+            <el-input v-model="productQuery.productNo" placeholder="请输入产品编号" clearable style="width: 200px;" />
+          </el-form-item>
+          <el-form-item label="产品名称">
+            <el-input v-model="productQuery.itemName" placeholder="请输入产品名称" clearable style="width: 200px;" />
+          </el-form-item>
+          <el-form-item label="品牌名称">
+            <el-input v-model="productQuery.brandName" placeholder="请输入品牌名称" clearable style="width: 200px;" />
+          </el-form-item>
+          <el-form-item label="上架状态">
+            <el-select v-model="productQuery.productStatus" placeholder="请选择" clearable style="width: 150px;">
+              <el-option label="上架" :value="1" />
+              <el-option label="下架" :value="0" />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="Search" @click="handleProductQuery">搜索</el-button>
+            <el-button icon="Refresh" @click="resetProductQuery">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <el-table 
+        :data="productListData" 
+        border 
+        style="width: 100%;"
+        @selection-change="handleProductSelectionChange"
+      >
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column prop="productNo" label="产品编号" align="center" width="120" />
+        <el-table-column label="产品图片" align="center" width="100">
+          <template #default="scope">
+            <el-image 
+              v-if="scope.row.productImage" 
+              :src="scope.row.productImage" 
+              style="width: 60px; height: 60px;"
+              fit="cover"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column prop="itemName" label="产品名称" align="center" show-overflow-tooltip />
+        <el-table-column prop="brandName" label="品牌" align="center" width="120" />
+        <el-table-column prop="unitName" label="单位" align="center" width="80" />
+        <el-table-column prop="marketPrice" label="市场价" align="center" width="100" />
+        <el-table-column prop="memberPrice" label="平台价" align="center" width="100" />
+        <el-table-column prop="minOrderQuantity" label="起订量" align="center" width="100" />
+        <el-table-column label="上架状态" align="center" width="100">
+          <template #default="scope">
+            <span>{{ scope.row.productStatus === 1 ? '上架' : '下架' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" width="100">
+          <template #default="scope">
+            <el-button link type="primary" @click="handleAddToList(scope.row)">加入清单</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination 
+        v-show="productTotal > 0" 
+        :total="productTotal" 
+        v-model:page="productQuery.pageNum" 
+        v-model:limit="productQuery.pageSize"
+        @pagination="getProductList" 
+      />
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="handleBatchAdd">批量加入清单</el-button>
+          <el-button @click="productDialog.visible = false">关 闭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, reactive } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import { ArrowLeft } from '@element-plus/icons-vue';
+import { getContractsupply, updateContractsupply } from '@/api/supplier/contractsupply';
+import { getCompanyList, listInfo } from '@/api/customer/info';
+import { listBase } from '@/api/product/base';
+import { ElMessage } from 'element-plus';
+import FileUpload from '@/components/FileUpload/index.vue';
+
+const route = useRoute();
+const router = useRouter();
+
+const formRef = ref();
+const productList = ref<any[]>([]);
+const companyList = ref<any[]>([]);
+const supplierList = ref<any[]>([]);
+
+// 商品对话框相关
+const productDialog = reactive({
+  visible: false
+});
+
+const productListData = ref<any[]>([]);
+const productTotal = ref(0);
+const selectedProducts = ref<any[]>([]);
+
+const productQuery = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  productNo: '',
+  itemName: '',
+  brandName: '',
+  productStatus: undefined as number | undefined
+});
+
+const form = ref({
+  id: '',
+  contractSupplyNo: '',
+  companyId: '',
+  supplierId: '',
+  supplyNo: '',
+  supplierName: '',
+  startTime: '',
+  endTime: '',
+  attachment: '',
+  remark: '',
+  isSubmit: false
+});
+
+const rules = {
+  // 编辑页面所有字段都不是必填
+};
+
+/** 返回上一页 */
+const goBack = () => {
+  router.back();
+};
+
+/** 获取公司列表 */
+const getCompanyData = async () => {
+  try {
+    const res = await getCompanyList();
+    companyList.value = res.data || [];
+  } catch (e) {
+    console.error('获取公司列表失败:', e);
+  }
+};
+
+/** 获取供应商列表 */
+const getSupplierData = async () => {
+  try {
+    const res = await listInfo();
+    supplierList.value = res.rows || [];
+  } catch (e) {
+    console.error('获取供应商列表失败:', e);
+  }
+};
+
+/** 获取详情数据 */
+const getDetail = async () => {
+  const id = route.params.id as string;
+  if (id) {
+    try {
+      const res = await getContractsupply(id);
+      
+      // 回显基本信息
+      form.value = {
+        id: res.data.id,
+        contractSupplyNo: res.data.contractSupplyNo,
+        companyId: res.data.companyId,
+        supplierId: res.data.supplierId,
+        supplyNo: res.data.supplyNo || '',
+        supplierName: res.data.supplierName,
+        startTime: res.data.startTime,
+        endTime: res.data.endTime,
+        attachment: res.data.attachment,
+        remark: res.data.remark,
+        isSubmit: res.data.isSubmit || false
+      };
+      
+      // 回显商品列表(关键!需要字段映射)
+      productList.value = (res.data.contractProduct || []).map((item: any) => ({
+        productId: item.productId,
+        productCode: item.productNo,
+        productImage: item.productImage,
+        productName: item.itemName,
+        productType: item.categoryName,
+        brand: item.brandName,
+        unit: item.unitName,
+        basePrice: item.purchasingPrice || 0,
+        marketPrice: item.marketPrice || 0,
+        platformPrice: item.memberPrice || 0,
+        supplyPrice: item.offerPrice || '',
+        supplyCycle: item.supplyCycle || '',
+        upPrice: item.productStatus === 1 ? '上架' : '下架'
+      }));
+    } catch (e) {
+      console.error('获取详情失败:', e);
+      ElMessage.error('获取详情失败');
+    }
+  }
+};
+
+/** 添加商品 */
+const handleAddProduct = () => {
+  productDialog.visible = true;
+};
+
+/** 获取商品列表 */
+const getProductList = async () => {
+  try {
+    const res = await listBase(productQuery);
+    productListData.value = res.rows || [];
+    productTotal.value = res.total || 0;
+  } catch (e) {
+    console.error('获取商品列表失败:', e);
+    ElMessage.error('获取商品列表失败');
+  }
+};
+
+/** 商品查询 */
+const handleProductQuery = () => {
+  productQuery.pageNum = 1;
+  getProductList();
+};
+
+/** 重置商品查询 */
+const resetProductQuery = () => {
+  productQuery.productNo = '';
+  productQuery.itemName = '';
+  productQuery.brandName = '';
+  productQuery.productStatus = undefined;
+  handleProductQuery();
+};
+
+/** 商品多选 */
+const handleProductSelectionChange = (selection: any[]) => {
+  selectedProducts.value = selection;
+};
+
+/** 加入清单 */
+const handleAddToList = (row: any) => {
+  // 检查是否已存在
+  const exists = productList.value.some(item => item.productId === row.id);
+  if (exists) {
+    ElMessage.warning('该商品已在清单中');
+    return;
+  }
+  
+  // 添加到本地清单
+  productList.value.push({
+    productId: row.id,
+    productCode: row.productNo,
+    productImage: row.productImage,
+    productName: row.itemName,
+    productType: row.categoryName,
+    brand: row.brandName,
+    unit: row.unitName,
+    basePrice: row.purchasingPrice || 0,
+    marketPrice: row.marketPrice || 0,
+    platformPrice: row.memberPrice || 0,
+    supplyPrice: '',
+    supplyCycle: '',
+    upPrice: row.productStatus === 1 ? '上架' : '下架'
+  });
+  
+  ElMessage.success('添加成功');
+};
+
+/** 批量加入清单 */
+const handleBatchAdd = () => {
+  if (selectedProducts.value.length === 0) {
+    ElMessage.warning('请选择要添加的商品');
+    return;
+  }
+  
+  let successCount = 0;
+  
+  selectedProducts.value.forEach(row => {
+    const exists = productList.value.some(item => item.productId === row.id);
+    if (!exists) {
+      productList.value.push({
+        productId: row.id,
+        productCode: row.productNo,
+        productImage: row.productImage,
+        productName: row.itemName,
+        productType: row.categoryName,
+        brand: row.brandName,
+        unit: row.unitName,
+        basePrice: row.purchasingPrice || 0,
+        marketPrice: row.marketPrice || 0,
+        platformPrice: row.memberPrice || 0,
+        supplyPrice: '',
+        supplyCycle: '',
+        upPrice: row.productStatus === 1 ? '上架' : '下架'
+      });
+      
+      successCount++;
+    }
+  });
+  
+  ElMessage.success(`成功添加${successCount}个商品`);
+  productDialog.visible = false;
+};
+
+/** 导入 */
+const handleImport = () => {
+  console.log('导入');
+  // TODO: 实现导入功能
+};
+
+/** 导出 */
+const handleExport = () => {
+  console.log('导出');
+  // TODO: 实现导出功能
+};
+
+/** 删除商品 */
+const handleDeleteProduct = (index: number) => {
+  productList.value.splice(index, 1);
+};
+
+/** 提交表单 */
+const handleSubmit = async () => {
+  formRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      try {
+        // 组装提交数据,包含表单数据和商品列表
+        const submitData = {
+          ...form.value,
+          contractProduct: productList.value.map(item => ({
+            productId: item.productId,
+            productNo: item.productCode,
+            offerPrice: item.supplyPrice,
+            supplyCycle: item.supplyCycle
+          }))
+        };
+        
+        await updateContractsupply(submitData);
+        ElMessage.success('保存成功');
+        router.back();
+      } catch (e) {
+        console.error('保存失败:', e);
+        ElMessage.error('保存失败');
+      }
+    }
+  });
+};
+
+onMounted(() => {
+  getSupplierData(); // 先加载供应商列表
+  getDetail();
+  getCompanyData();
+  getProductList(); // 页面加载时获取商品列表
+});
+</script>
+
+<style scoped>
+.app-container {
+  background: #f0f2f5;
+  min-height: 100vh;
+  padding: 0;
+}
+
+.detail-header {
+  background: #fff;
+  padding: 16px 24px;
+  display: flex;
+  align-items: center;
+  border-bottom: 1px solid #e8e8e8;
+  margin-bottom: 16px;
+}
+
+.back-icon {
+  font-size: 18px;
+  cursor: pointer;
+  margin-right: 12px;
+  color: #666;
+}
+
+.back-icon:hover {
+  color: #409eff;
+}
+
+.header-title {
+  font-size: 16px;
+  font-weight: 500;
+  color: #333;
+}
+
+.form-card {
+  margin: 16px;
+  padding: 24px;
+}
+
+.section-title {
+  margin: 20px 0;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #e8e8e8;
+}
+</style>

+ 77 - 28
src/views/supplier/contractsupply/index.vue

@@ -26,6 +26,7 @@
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
               <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+              <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['supplier:contractsupply:add']">新增</el-button>
             </el-form-item>
           </el-form>
         </el-card>
@@ -35,19 +36,7 @@
     <el-card shadow="never">
       <template #header>
         <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['supplier:contractsupply:add']">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['supplier:contractsupply:edit']">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['supplier:contractsupply:remove']">删除</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplier:contractsupply:export']">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+          协议供货信息列表
         </el-row>
       </template>
 
@@ -76,12 +65,9 @@
         </el-table-column>
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['supplier:contractsupply:edit']"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['supplier:contractsupply:remove']"></el-button>
-            </el-tooltip>
+            <el-button link type="primary" @click="handleAudit(scope.row)" v-hasPermi="['supplier:contractsupply:edit']">审核</el-button>
+            <el-divider direction="vertical" />
+            <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['supplier:contractsupply:edit']">编辑</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -99,12 +85,33 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 审核对话框 -->
+    <el-dialog title="审核" v-model="auditDialog.visible" width="500px" append-to-body>
+      <el-form ref="auditFormRef" :model="auditForm" :rules="auditRules" label-width="100px">
+        <el-form-item label="审核结果" prop="status">
+          <el-select v-model="auditForm.status" placeholder="请选择" style="width: 100%;">
+            <el-option label="生效" :value="1" />
+            <el-option label="驳回" :value="0" />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitAudit">确 定</el-button>
+          <el-button @click="cancelAudit">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="Contractsupply" lang="ts">
 import { listContractsupply, getContractsupply, delContractsupply, addContractsupply, updateContractsupply } from '@/api/supplier/contractsupply';
 import { ContractsupplyVO, ContractsupplyQuery, ContractsupplyForm } from '@/api/supplier/contractsupply/types';
+import { useRouter } from 'vue-router';
+
+const router = useRouter();
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { contract_supplier_status } = toRefs<any>(proxy?.useDict('contract_supplier_status'));
@@ -120,12 +127,28 @@ const total = ref(0);
 
 const queryFormRef = ref<ElFormInstance>();
 const contractsupplyFormRef = ref<ElFormInstance>();
+const auditFormRef = ref<ElFormInstance>();
 
 const dialog = reactive<DialogOption>({
   visible: false,
   title: ''
 });
 
+const auditDialog = reactive({
+  visible: false,
+  currentRow: null as ContractsupplyVO | null
+});
+
+const auditForm = ref({
+  status: undefined as number | undefined
+});
+
+const auditRules = {
+  status: [
+    { required: true, message: '请选择审核结果', trigger: 'change' }
+  ]
+};
+
 const initFormData: ContractsupplyForm = {
 }
 const data = reactive<PageData<ContractsupplyForm, ContractsupplyQuery>>({
@@ -187,21 +210,47 @@ const handleSelectionChange = (selection: ContractsupplyVO[]) => {
 
 /** 新增按钮操作 */
 const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = "添加协议供货";
+  router.push('/supplier/contractsupply/add');
 }
 
 /** 修改按钮操作 */
 const handleUpdate = async (row?: ContractsupplyVO) => {
-  reset();
-  const _id = row?.id || ids.value[0]
-  const res = await getContractsupply(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = "修改协议供货";
+  const _id = row?.id || ids.value[0];
+  router.push(`/supplier/contractsupply/edit/${_id}`);
 }
 
+/** 审核按钮操作 */
+const handleAudit = (row: ContractsupplyVO) => {
+  auditDialog.currentRow = row;
+  auditForm.value.status = undefined;
+  auditDialog.visible = true;
+};
+
+/** 提交审核 */
+const submitAudit = () => {
+  auditFormRef.value?.validate(async (valid: boolean) => {
+    if (valid && auditDialog.currentRow) {
+      try {
+        await updateContractsupply({
+          ...auditDialog.currentRow,
+          status: auditForm.value.status
+        });
+        proxy?.$modal.msgSuccess("审核成功");
+        auditDialog.visible = false;
+        await getList();
+      } catch (e) {
+        console.error('审核失败:', e);
+      }
+    }
+  });
+};
+
+/** 取消审核 */
+const cancelAudit = () => {
+  auditDialog.visible = false;
+  auditForm.value.status = undefined;
+};
+
 /** 提交按钮 */
 const submitForm = () => {
   contractsupplyFormRef.value?.validate(async (valid: boolean) => {

+ 14 - 8
src/views/supplier/none/index.vue

@@ -89,9 +89,9 @@
         </el-table-column>  
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['customer:info:query']">查看</el-button>
+            
             <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['customer:info:edit']">编辑</el-button>
-            <el-button link type="primary" @click="handleStopCooperation(scope.row)" v-hasPermi="['customer:info:edit']">停止合作</el-button>
+            <el-button link type="primary" @click="handleStopCooperation(scope.row)" v-hasPermi="['customer:info:edit']">恢复合作</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -205,13 +205,19 @@ const handleView = (row: InfoVO) => {
   });
 }
 
-/** 停止合作按钮操作 */
+/** 恢复合作按钮操作 */
 const handleStopCooperation = async (row: InfoVO) => {
-  await proxy?.$modal.confirm('是否确认停止与供应商"' + row.enterpriseName + '"的合作?');
-  const updateData = { ...row, cooperative: 0 };
-  await updateInfo(updateData);
-  proxy?.$modal.msgSuccess("操作成功");
-  await getList();
+  await proxy?.$modal.confirm('是否确认恢复与供应商"' + row.enterpriseName + '"的合作?');
+  try {
+    await updateInfo({ 
+      ...row,
+      supplyStatus: 1 
+    });
+    proxy?.$modal.msgSuccess("恢复合作成功");
+    await getList();
+  } catch (e) {
+    console.error('恢复合作失败:', e);
+  }
 }
 
 /** 获取供应商类型列表 */