li.shaoyi il y a 3 ans
Parent
commit
df66e43abb
38 fichiers modifiés avec 1039 ajouts et 179 suppressions
  1. 124 0
      public/proto/gz.proto
  2. 35 0
      src/business/customs/index.ts
  3. 2 1
      src/business/goods/index.ts
  4. 30 3
      src/business/table/index.ts
  5. 10 9
      src/constants/bank.ts
  6. 4 5
      src/constants/certificate.ts
  7. 2 4
      src/constants/client.ts
  8. 17 19
      src/constants/diamond.ts
  9. 9 0
      src/constants/funcode.ts
  10. 10 10
      src/constants/order.ts
  11. 53 21
      src/packages/pc/components/layouts/header/components/calculator/index.vue
  12. 71 10
      src/packages/pc/components/layouts/header/components/certificate/index.vue
  13. 23 0
      src/packages/pc/components/modules/performance-rule/index.less
  14. 22 0
      src/packages/pc/components/modules/performance-rule/index.vue
  15. 0 20
      src/packages/pc/components/modules/performance/index.less
  16. 7 17
      src/packages/pc/components/modules/performance/index.vue
  17. 2 2
      src/packages/pc/views/boot/index.vue
  18. 16 1
      src/packages/pc/views/customs/bonded/index.vue
  19. 16 1
      src/packages/pc/views/customs/exit/index.vue
  20. 8 1
      src/packages/pc/views/trade/bargain/components/details/index.vue
  21. 7 3
      src/packages/pc/views/trade/bargain/index.vue
  22. 7 1
      src/packages/pc/views/trade/buy/components/details/index.vue
  23. 14 3
      src/packages/pc/views/trade/delisting/components/details/index.vue
  24. 8 2
      src/packages/pc/views/trade/purchase/components/details/index.vue
  25. 8 2
      src/packages/pc/views/trade/sale/components/details/index.vue
  26. 4 2
      src/packages/pc/views/warehousing/goods/components/details/index.vue
  27. 2 2
      src/packages/pc/views/warehousing/goods/components/edit/diamonds.vue
  28. 21 0
      src/services/api/common/index.ts
  29. 74 0
      src/services/api/customs/index.ts
  30. 10 0
      src/services/api/favorite/index.ts
  31. 0 7
      src/services/api/goods/index.ts
  32. 8 8
      src/stores/@next.ts
  33. 38 23
      src/stores/modules/enum.ts
  34. 6 1
      src/stores/modules/performance.ts
  35. 37 0
      src/types/ermcp/common.d.ts
  36. 201 0
      src/types/ermcp/customs.d.ts
  37. 2 1
      src/types/ermcp/trade.d.ts
  38. 131 0
      src/types/proto/customs.d.ts

+ 124 - 0
public/proto/gz.proto

@@ -945,4 +945,128 @@ message ReceiptZSOutApplyRsp {
 		optional WRCommon Common = 4; // 
 		optional uint64 ApplyID = 5; // 申请ID
 		optional string ClientTicket = 6; // 客户端流水号
+}
+
+// 货物明细列表
+message GZCJCategoryDetail {
+	optional uint32 OrderIndex = 1; // 顺序,必填
+	optional string GZNo = 2; // 货物编号,必填
+	optional uint32 GZCJShapeType = 3; // 形状,必填
+	optional double Weight = 4; // 重量(CT),3位小数,必填
+	optional double Amount = 5; // 参考货值(USD),2位小数,必填
+	optional string ColorInfo = 6; // 彩钻信息
+	optional string Remark = 7; // 备注
+	optional uint32 GZCJMarkType = 8; // 刻印服务,必填
+	optional uint32 GZCJPublishType = 9; // 是否披露处理,必填
+	optional uint32 GZCJServiceType = 10; // 服务类别,必填
+	optional string OriginCertNo = 11; // 原证书号
+}
+
+// 文件列表
+message FileDetail {
+	optional string FileName = 1; // 文件名
+	optional string FilePath = 2; // 文件地址
+}
+
+// 出境检测申请请求
+message CJJCApplyReq {
+optional MessageHead Header = 1;
+	optional uint32 UserID = 2; // 用户ID,必填
+	optional uint64 AccountID = 3; // 资金账户ID,必填
+	optional uint32 OperateID = 4; // 操作人ID,LoginAccount的LoginID,必填
+	optional string OperateAccount = 5; // 操作人账户,LoginAccount的LoginCode,LoginCode为空则填LoginID,必填
+	optional uint32 GZCJAccountType = 6; // 检测账户类型,枚举"GZCJAccountType"NUMBER(2),必填
+	optional string GZCJAccount = 7; // 送检账户,GZCJAccountType=1:GIA自有账户
+	optional string CompanyNameCN = 8; // 公司名称(中文)
+	optional string CompanyNameEn = 9; // 公司名称(英文)
+	optional string AddressCN = 10; // 地址(中文)
+	optional string AddressEN = 11; // 地址(英文)
+	optional string ContactName = 12; // 联系人姓名
+	optional string ContactPosition = 13; // 联系人职位
+	optional string ContactPhoneNo = 14; // 联系人电话
+	optional string Email = 15; // 邮箱
+	optional uint32 GZCJCategoryType = 16; // 货物品类,必填
+	optional string ProcessingCountry = 17; // 成品钻石加工国
+	optional string ZSOrigin = 18; // 天然钻石毛坯原产地
+	optional uint32 GZCJDeliveryType = 19; // 收货方式,必填
+	repeated GZCJCategoryDetail GZCJCategoryDetails = 20; // 货物明细列表
+	optional uint32 ApplyType = 21; // 申请类型1:保存草稿2:修改草稿
+	optional uint64 OrderID = 22; // 单据ID,ApplyType=2,3时,有则填
+		optional uint32 ClientType = 23; // 终端类型
+		optional string ClientSerialNo = 24; // 客户端流水号
+}
+
+// 出境检测申请响应
+message CJJCApplyRsp {
+optional MessageHead Header = 1; // 消息头
+optional int32 RetCode = 2; // 返回码
+optional string RetDesc = 3; // 描述信息
+		optional uint32 UserID = 4; // 用户ID
+		optional uint64 AccountID = 5; // 资金账号
+		optional uint64 OrderID = 6; // 单据ID
+		optional string ClientSerialNo = 7; // 客户端流水号
+}
+
+// 出境检测会员操作请求
+message CJJCMemberOperateReq {
+optional MessageHead Header = 1;
+	optional uint32 UserID = 2; // 用户ID,必填
+	optional uint64 OperateID = 3; // 操作人ID,必填,LoginAccount的LoginID
+	optional string OperateAccount = 4; // 操作人账户,LoginAccount的LoginCode,LoginCode为空则填LoginID,必
+	optional uint64 OrderID = 5; // 单据ID,必填
+	optional uint32 OperateType = 6; // 操作类型,必填,1:撤回2:确认发货3:确认检测结果
+	optional string Remark = 7; // 备注
+		optional uint32 ClientType = 8; // 终端类型
+		optional string ClientSerialNo = 9; // 客户端流水号
+}
+
+// 出境检测会员操作响应
+message CJJCMemberOperateRsp {
+optional MessageHead Header = 1; // 消息头
+optional int32 RetCode = 2; // 返回码
+optional string RetDesc = 3; // 描述信息
+		optional uint32 UserID = 4; // 用户ID
+		optional uint64 AccountID = 5; // 资金账号
+		optional string ClientSerialNo = 6; // 客户端流水号
+}
+
+// 保税服务会员操作请求
+message BSFWMemberOperateReq {
+optional MessageHead Header = 1;
+	optional uint32 UserID = 2; // 用户ID,必填
+	optional uint64 OperateID = 3; // 操作人ID,必填,LoginAccount的LoginID
+	optional string OperateAccount = 4; // 操作人账户,LoginAccount的LoginCode,LoginCode为空则填LoginID,必
+	optional uint64 OrderID = 5; // 单据ID,必填
+	optional uint32 OperateType = 6; // 操作类型,必填,1:上传发货单2:上传盖章单据3:确认预付款
+	repeated FileDetail FileDetails = 7; // 文件列表
+	optional string Remark = 8; // 备注
+	optional uint32 GZBSDeliveryType = 9; // 收货方式,OperateType=1:上传发货单时必填,枚举“GZBSDeliveryType”
+	optional string OtherLogistics = 10; // 指定其它物流,OperateType=1:上传发货单时填写
+		optional uint32 ClientType = 11; // 终端类型
+		optional string ClientSerialNo = 12; // 客户端流水号
+}
+
+// 保税服务会员操作响应
+message BSFWMemberOperateRsp {
+optional MessageHead Header = 1; // 消息头
+optional int32 RetCode = 2; // 返回码
+optional string RetDesc = 3; // 描述信息
+		optional uint32 UserID = 4; // 用户ID
+		optional uint64 AccountID = 5; // 资金账号
+		optional string ClientSerialNo = 6; // 客户端流水号
+}
+
+// 出境检测确认预付款生成文件接口请求
+message CJJCConfirmMarginBuildFileReq {
+optional MessageHead Header = 1;
+	optional uint64 OrderID = 2; // 单据ID,必填
+}
+
+// 出境检测确认预付款生成文件接口响应
+message CJJCConfirmMarginBuildFileRsp {
+optional MessageHead Header = 1; // 消息头
+optional int32 RetCode = 2; // 返回码
+optional string RetDesc = 3; // 描述信息
+	optional uint64 OrderID = 4; // 单据ID,必填
+		optional uint32 IsSuccess = 5; // 返回码
 }

+ 35 - 0
src/business/customs/index.ts

@@ -0,0 +1,35 @@
+import { shallowRef } from 'vue'
+import { useDataTable } from '@/hooks/datatable'
+import { getTableColumns } from '@/business/table'
+
+// 出境检测
+export function useCJJCOrder() {
+    const { dataList, total, pageIndex, pageSize } = useDataTable<Ermcp.GZCJJCOrderRsp>()
+    const loading = shallowRef(false)
+    const columns = shallowRef(getTableColumns('customs_cjjc'))
+
+    return {
+        loading,
+        dataList,
+        total,
+        pageIndex,
+        pageSize,
+        columns,
+    }
+}
+
+// 保税服务
+export function useBSFWOrder() {
+    const { dataList, total, pageIndex, pageSize } = useDataTable<Ermcp.GZBSFWOrderRsp>()
+    const loading = shallowRef(false)
+    const columns = shallowRef(getTableColumns('customs_bsfw'))
+
+    return {
+        loading,
+        dataList,
+        total,
+        pageIndex,
+        pageSize,
+        columns,
+    }
+}

+ 2 - 1
src/business/goods/index.ts

@@ -6,7 +6,8 @@ import { formatDecimal } from '@/filters'
 import { ClientType } from '@/constants/client'
 import { Market } from '@/constants/market'
 import { queryWarehouseInfo } from '@/services/api/warehouse'
-import { addDiamond, queryDiamondList, queryDiamondDetails, goodsFavoriteOperate, receiptZSOutApply } from '@/services/api/goods'
+import { addDiamond, queryDiamondList, queryDiamondDetails, receiptZSOutApply } from '@/services/api/goods'
+import { goodsFavoriteOperate } from '@/services/api/favorite'
 import { useLoginStore } from '@/stores'
 import {
     Category,

+ 30 - 3
src/business/table/index.ts

@@ -2,7 +2,7 @@ import { shallowRef } from 'vue'
 import { useTableColumnStore } from '@/stores'
 
 type TableColumnKey = typeof tableColumnKeys[number]
-const tableColumnKeys = ['system_menu', 'system_role', 'warehousing_diamond', 'warehousing_warehouse', 'mine_capital', 'listing_sellorder', 'listing_buyorder', 'listing_saleorder', 'listing_purchaseorder', 'listing_delisting', 'listing_bargain_buy', 'listing_bargain_sell', 'mine_address', 'mine_invoice', 'favorite', 'order', 'order_step', 'bargain_buy', 'bargain_sell'] as const
+const tableColumnKeys = ['system_menu', 'system_role', 'warehousing_diamond', 'warehousing_warehouse', 'mine_capital', 'listing_sellorder', 'listing_buyorder', 'listing_saleorder', 'listing_purchaseorder', 'listing_delisting', 'listing_bargain_buy', 'listing_bargain_sell', 'mine_address', 'mine_invoice', 'favorite', 'order', 'order_step', 'bargain_buy', 'bargain_sell', 'customs_cjjc', 'customs_bsfw'] as const
 
 /**
  * PC端表格列
@@ -62,7 +62,7 @@ const pcTableColumnMap = new Map<TableColumnKey, Ermcp.TableColumn[]>([
         { prop: 'zspolishtype1display', label: '抛光' },
         { prop: 'zssymmetrytype1display', label: '对称' },
         { prop: 'zsfluorescencetype1display', label: '荧光' },
-        { prop: 'size1', label: '尺寸' },
+        { prop: 'sizedisplay', label: '尺寸' },
         { prop: 'price', label: '价格' },
         { prop: 'totalqty', label: '克拉重量' },
         { prop: 'fixedprice', label: '克拉单价' },
@@ -91,7 +91,7 @@ const pcTableColumnMap = new Map<TableColumnKey, Ermcp.TableColumn[]>([
         { prop: 'zspolishtype1display', label: '抛光' },
         { prop: 'zssymmetrytype1display', label: '对称' },
         { prop: 'zsfluorescencetype1display', label: '荧光' },
-        { prop: 'size1', label: '尺寸' },
+        { prop: 'sizedisplay', label: '尺寸' },
         { prop: 'price', label: '价格' },
         { prop: 'totalqty', label: '克拉重量' },
         { prop: 'fixedprice', label: '克拉单价' },
@@ -282,6 +282,33 @@ const pcTableColumnMap = new Map<TableColumnKey, Ermcp.TableColumn[]>([
         { prop: 'applytime', label: '申请时间', width: 200 },
         { prop: 'operate', label: '操作', width: 180 }
     ]],
+    // 交易服务-出境检测
+    ['customs_cjjc', [
+        { prop: 'orderno', label: '单据编号' },
+        { prop: 'gzcjcategorytypedisplay', label: '货物品类' },
+        { prop: 'gzcjdeliverytypedisplay', label: '收货方式' },
+        { prop: 'gzcjaccount', label: '送检账户' },
+        { prop: 'undefined', label: '总数量(粒)' },
+        { prop: 'undefined', label: '总重量(ct)' },
+        { prop: 'totalamount', label: '总参考值(US$)' },
+        { prop: 'contactname', label: '联系人姓名' },
+        { prop: 'contactphoneno', label: '联系人电话' },
+        { prop: 'gzcjstatusdisplay', label: '单据状态' },
+        { prop: 'operate', label: '操作', width: 180 }
+    ]],
+    // 交易服务-保税服务
+    ['customs_bsfw', [
+        { prop: 'orderno', label: '单据编号' },
+        { prop: 'contentrange', label: '内容' },
+        { prop: 'totalnetweigthct', label: '总净重(克拉)' },
+        { prop: 'totalnetweightgm', label: '总净重(克)' },
+        { prop: 'totalgrossweightgm', label: '总毛重(克)' },
+        { prop: 'totalamount', label: '总值(美元)' },
+        { prop: 'priceper', label: '单价(美元/克拉)', width: 160 },
+        { prop: 'undefined', label: '备注' },
+        { prop: 'gzbsstatusdisplay', label: '单据状态' },
+        { prop: 'operate', label: '操作', width: 180 }
+    ]],
 ])
 
 /**

+ 10 - 9
src/constants/bank.ts

@@ -1,8 +1,6 @@
 import { useEnumStore } from '@/stores'
 
-const { getEnumTypes, getEnumTypeList, getEnumTypeName } = useEnumStore()
-const enumKeys = ['signstatus', 'applystatus', 'executetype'] as const
-const enumMap = getEnumTypes(...enumKeys)
+const { getEnumTypeList, getEnumTypeName } = useEnumStore()
 
 /**
  * 签约状态
@@ -21,7 +19,7 @@ export enum SignStatus {
  * @returns 
  */
 export function getSignStatusList() {
-    return getEnumTypeList(enumMap.get('signstatus'))
+    return getEnumTypeList('signstatus')
 }
 
 /**
@@ -29,7 +27,8 @@ export function getSignStatusList() {
  * @returns 
  */
 export function getSignStatusName(value: number) {
-    return getEnumTypeName(getSignStatusList(), value)
+    const enums = getSignStatusList()
+    return getEnumTypeName(enums, value)
 }
 
 /**
@@ -37,7 +36,7 @@ export function getSignStatusName(value: number) {
  * @returns 
  */
 export function getApplyStatusList() {
-    return getEnumTypeList(enumMap.get('applystatus'))
+    return getEnumTypeList('applystatus')
 }
 
 /**
@@ -45,7 +44,8 @@ export function getApplyStatusList() {
  * @returns 
  */
 export function getApplyStatusName(value: number) {
-    return getEnumTypeName(getApplyStatusList(), value)
+    const enums = getApplyStatusList()
+    return getEnumTypeName(enums, value)
 }
 
 /**
@@ -53,7 +53,7 @@ export function getApplyStatusName(value: number) {
  * @returns 
  */
 export function getExecuteTypeList() {
-    return getEnumTypeList(enumMap.get('executetype'))
+    return getEnumTypeList('executetype')
 }
 
 /**
@@ -61,5 +61,6 @@ export function getExecuteTypeList() {
  * @returns 
  */
 export function getExecuteTypeName(value: number) {
-    return getEnumTypeName(getExecuteTypeList(), value)
+    const enums = getExecuteTypeList()
+    return getEnumTypeName(enums, value)
 }

+ 4 - 5
src/constants/certificate.ts

@@ -1,15 +1,13 @@
 import { useEnumStore } from '@/stores'
 
-const { getEnumTypes, getEnumTypeList, getEnumTypeName } = useEnumStore()
-const enumKeys = ['certificatetype'] as const
-const enumMap = getEnumTypes(...enumKeys)
+const { getEnumTypeList, getEnumTypeName } = useEnumStore()
 
 /**
  * 获取证件类型列表
  * @returns 
  */
 export function getCertificateTypeList() {
-    return getEnumTypeList(enumMap.get('certificatetype'))
+    return getEnumTypeList('certificatetype')
 }
 
 /**
@@ -17,5 +15,6 @@ export function getCertificateTypeList() {
  * @returns 
  */
 export function getCertificateTypeName(value?: number) {
-    return getEnumTypeName(getCertificateTypeList(), value)
+    const enums = getCertificateTypeList()
+    return getEnumTypeName(enums, value)
 }

+ 2 - 4
src/constants/client.ts

@@ -1,8 +1,6 @@
 import { useEnumStore } from '@/stores'
 
-const { getEnumTypes, getEnumTypeList } = useEnumStore()
-const enumKeys = ['clientType'] as const
-const enumMap = getEnumTypes(...enumKeys)
+const { getEnumTypeList } = useEnumStore()
 
 /**
  * 客户端类型
@@ -26,5 +24,5 @@ export enum ClientType {
  * @returns 
  */
 export function getClientTypeList() {
-    return getEnumTypeList(enumMap.get('clientType'))
+    return getEnumTypeList('clientType')
 }

+ 17 - 19
src/constants/diamond.ts

@@ -1,8 +1,6 @@
 import { useEnumStore } from '@/stores'
 
-const { getEnumTypes, getEnumTypeList, getEnumTypeInfo } = useEnumStore()
-const enumKeys = ['ZSCategory', 'ZSCurrencyType', 'ZSCurrencyType', 'ZSColorType', 'ZSClarityType', 'ZSCutType', 'ZSShapeType', 'ZSSymmetryType', 'ZSPolishType', 'ZSFluorescenceType', 'ZSCertType', 'ZSCrystalType', 'ZSCZColor1Type', 'ZSCZColor2Type', 'ZSCZColor3Type', 'ZSStyleType'] as const
-const enumMap = getEnumTypes(...enumKeys)
+const { getEnumTypeList, getEnumTypeInfo } = useEnumStore()
 
 /**
  * 钻石类型
@@ -28,7 +26,7 @@ export enum CurrencyType {
  * @returns 
  */
 export function getCategoryList() {
-    return getEnumTypeList(enumMap.get('ZSCategory'))
+    return getEnumTypeList('ZSCategory')
 }
 
 /**
@@ -36,7 +34,7 @@ export function getCategoryList() {
  * @returns 
  */
 export function getCurrencyTypeList() {
-    return getEnumTypeList(enumMap.get('ZSCurrencyType'))
+    return getEnumTypeList('ZSCurrencyType')
 }
 
 /**
@@ -45,7 +43,7 @@ export function getCurrencyTypeList() {
  * @returns 
  */
 export function getCurrencyTypeInfo(value: number) {
-    return getEnumTypeInfo(enumMap.get('ZSCurrencyType') ?? [], value)
+    return getEnumTypeInfo('ZSCurrencyType', value)
 }
 
 /**
@@ -53,7 +51,7 @@ export function getCurrencyTypeInfo(value: number) {
  * @returns 
  */
 export function getColorTypeList() {
-    return getEnumTypeList(enumMap.get('ZSColorType'))
+    return getEnumTypeList('ZSColorType')
 }
 
 /**
@@ -61,7 +59,7 @@ export function getColorTypeList() {
  * @returns 
  */
 export function getClarityTypeList() {
-    return getEnumTypeList(enumMap.get('ZSClarityType'))
+    return getEnumTypeList('ZSClarityType')
 }
 
 /**
@@ -69,7 +67,7 @@ export function getClarityTypeList() {
  * @returns 
  */
 export function getCutTypeList() {
-    return getEnumTypeList(enumMap.get('ZSCutType'))
+    return getEnumTypeList('ZSCutType')
 }
 
 /**
@@ -77,7 +75,7 @@ export function getCutTypeList() {
  * @returns 
  */
 export function getShapeTypeList() {
-    return getEnumTypeList(enumMap.get('ZSShapeType'))
+    return getEnumTypeList('ZSShapeType')
 }
 
 /**
@@ -85,7 +83,7 @@ export function getShapeTypeList() {
  * @returns 
  */
 export function getSymmetryTypeList() {
-    return getEnumTypeList(enumMap.get('ZSSymmetryType'))
+    return getEnumTypeList('ZSSymmetryType')
 }
 
 /**
@@ -93,7 +91,7 @@ export function getSymmetryTypeList() {
  * @returns 
  */
 export function getPolishTypeList() {
-    return getEnumTypeList(enumMap.get('ZSPolishType'))
+    return getEnumTypeList('ZSPolishType')
 }
 
 /**
@@ -101,7 +99,7 @@ export function getPolishTypeList() {
  * @returns 
  */
 export function getFluorescenceTypeList() {
-    return getEnumTypeList(enumMap.get('ZSFluorescenceType'))
+    return getEnumTypeList('ZSFluorescenceType')
 }
 
 /**
@@ -109,7 +107,7 @@ export function getFluorescenceTypeList() {
  * @returns 
  */
 export function getCertTypeList() {
-    return getEnumTypeList(enumMap.get('ZSCertType'))
+    return getEnumTypeList('ZSCertType')
 }
 
 /**
@@ -117,7 +115,7 @@ export function getCertTypeList() {
  * @returns 
  */
 export function getCrystalTypeList() {
-    return getEnumTypeList(enumMap.get('ZSCrystalType'))
+    return getEnumTypeList('ZSCrystalType')
 }
 
 /**
@@ -125,7 +123,7 @@ export function getCrystalTypeList() {
  * @returns 
  */
 export function getFancyColorType1List() {
-    return getEnumTypeList(enumMap.get('ZSCZColor1Type'))
+    return getEnumTypeList('ZSCZColor1Type')
 }
 
 /**
@@ -133,7 +131,7 @@ export function getFancyColorType1List() {
  * @returns 
  */
 export function getFancyColorType2List() {
-    return getEnumTypeList(enumMap.get('ZSCZColor2Type'))
+    return getEnumTypeList('ZSCZColor2Type')
 }
 
 /**
@@ -141,7 +139,7 @@ export function getFancyColorType2List() {
  * @returns 
  */
 export function getFancyColorType3List() {
-    return getEnumTypeList(enumMap.get('ZSCZColor3Type'))
+    return getEnumTypeList('ZSCZColor3Type')
 }
 
 /**
@@ -149,5 +147,5 @@ export function getFancyColorType3List() {
  * @returns 
  */
 export function getStyleTypeList() {
-    return getEnumTypeList(enumMap.get('ZSStyleType'))
+    return getEnumTypeList('ZSStyleType')
 }

+ 9 - 0
src/constants/funcode.ts

@@ -79,4 +79,13 @@ export enum FunCode {
     PerformanceContractedApplyRsp = 1310730, // 违约申请应答
     PerformanceModifyContactReq = 1310735, // 履约修改联络信息请求
     PerformanceModifyContactRsp = 1310736, // 履约修改联络信息回应
+
+    CJJCApplyReq = 1114115, // 出境检测申请请求
+    CJJCApplyRsp = 1114116, // 出境检测申请响应
+    CJJCMemberOperateReq = 1114117, // 出境检测会员操作请求
+    CJJCMemberOperateRsp = 1114118, // 出境检测会员操作响应
+    BSFWMemberOperateReq = 1114119, // 保税服务会员操作请求
+    BSFWMemberOperateRsp = 1114120, // 保税服务会员操作响应
+    CJJCConfirmMarginBuildFileReq = 1114121, // 出境检测确认预付款生成文件接口请求
+    CJJCConfirmMarginBuildFileRsp = 1114122, // 出境检测确认预付款生成文件接口响应
 }

+ 10 - 10
src/constants/order.ts

@@ -1,10 +1,7 @@
 import { useEnumStore } from '@/stores'
 import { usePerformanceStore } from '@/stores'
 
-const { getEnumTypes, getEnumTypeList, getEnumTypeName } = useEnumStore()
-const enumKeys = ['wrApplyStatus', 'performanceStatus', 'stepStatus'] as const
-const enumMap = getEnumTypes(...enumKeys)
-
+const { getEnumTypeList, getEnumTypeName } = useEnumStore()
 /**
  * 买卖方向
  */
@@ -44,7 +41,7 @@ export enum ApplyStatus {
  * @returns 
  */
 export function getApplyStatusList() {
-    return getEnumTypeList(enumMap.get('wrApplyStatus'))
+    return getEnumTypeList('wrApplyStatus')
 }
 
 /**
@@ -52,7 +49,8 @@ export function getApplyStatusList() {
  * @returns 
  */
 export function getApplyStatusName(value: number) {
-    return getEnumTypeName(getApplyStatusList(), value)
+    const enums = getApplyStatusList()
+    return getEnumTypeName(enums, value)
 }
 
 /**
@@ -60,7 +58,7 @@ export function getApplyStatusName(value: number) {
  * @returns 
  */
 export function getPerformanceStatusList() {
-    return getEnumTypeList(enumMap.get('performanceStatus'))
+    return getEnumTypeList('performanceStatus')
 }
 
 /**
@@ -68,7 +66,8 @@ export function getPerformanceStatusList() {
  * @returns 
  */
 export function getPerformanceStatusName(value: number) {
-    return getEnumTypeName(getPerformanceStatusList(), value)
+    const enums = getPerformanceStatusList()
+    return getEnumTypeName(enums, value)
 }
 
 /**
@@ -110,7 +109,7 @@ export function getStepTypeName(value: number) {
  * @returns 
  */
 export function getStepStatusList() {
-    return getEnumTypeList(enumMap.get('stepStatus'))
+    return getEnumTypeList('stepStatus')
 }
 
 /**
@@ -118,5 +117,6 @@ export function getStepStatusList() {
  * @returns 
  */
 export function getStepStatusName(value: number) {
-    return getEnumTypeName(getStepStatusList(), value)
+    const enums = getStepStatusList()
+    return getEnumTypeName(enums, value)
 }

+ 53 - 21
src/packages/pc/components/layouts/header/components/calculator/index.vue

@@ -1,69 +1,101 @@
 <!-- 钻石计算器 -->
 <template>
-    <app-drawer title="计算器" :width="860" v-model:show="show">
+    <app-drawer title="计算器" :width="800" v-model:show="show">
         <el-form ref="formRef" label-width="70px">
             <el-form-item label="形状">
-                <el-radio-group>
+                <el-radio-group v-model="formData.zsshape">
                     <el-radio :label="1">圆形</el-radio>
                     <el-radio :label="2">异形</el-radio>
                 </el-radio-group>
             </el-form-item>
             <el-form-item label="颜色">
-                <el-radio-group>
+                <el-radio-group v-model="formData.zscolor">
                     <el-radio :label="item" v-for="(item, index) in colors" :key="index">
                         {{ item }}
                     </el-radio>
                 </el-radio-group>
             </el-form-item>
             <el-form-item label="净度">
-                <el-radio-group>
+                <el-radio-group v-model="formData.zsclarity">
                     <el-radio :label="item" v-for="(item, index) in claritys" :key="index">
                         {{ item }}
                     </el-radio>
                 </el-radio-group>
             </el-form-item>
             <el-form-item label="重量" style="width:50%">
-                <el-input type="number" placeholder="请输入">
+                <el-input type="number" placeholder="请输入" v-model.number="formData.weight">
                     <template #append>(克拉)</template>
                 </el-input>
             </el-form-item>
             <el-form-item label="汇率" style="width:50%">
-                <el-input type="number" placeholder="请输入" />
+                <el-input type="number" placeholder="请输入" v-model.number="formData.rate" />
             </el-form-item>
             <el-form-item label="折扣(%)" style="width:50%">
-                <el-input type="number" placeholder="请输入">
+                <el-input type="number" placeholder="请输入" v-model.number="formData.discount">
                     <template #prepend>
-                        <el-select style="width: 90px">
-                            <el-option label="+" value="1" />
-                            <el-option label="-" value="2" />
+                        <el-select v-model="operator" style="width: 60px">
+                            <el-option label="+" :value="1" />
+                            <el-option label="-" :value="2" />
                         </el-select>
                     </template>
                 </el-input>
             </el-form-item>
-            <el-form-item label="美元">
-                <span>100</span>
-            </el-form-item>
-            <el-form-item label="人民币">
-                <span>100</span>
-            </el-form-item>
-            <el-form-item label="日期">
-                <span>2022-07-29</span>
+            <el-form-item label="计算结果" v-if="dataList.length">
+                <div class="el-form-item--col">
+                    <span>美元: 100</span>
+                    <span>人民币: 100</span>
+                </div>
             </el-form-item>
             <el-form-item>
-                <el-button type="primary">计算</el-button>
-                <el-button>取消</el-button>
+                <el-button type="primary" @click="formSubmit">计算</el-button>
+                <el-button @click="show = false">取消</el-button>
             </el-form-item>
         </el-form>
     </app-drawer>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef } from 'vue'
+import { shallowRef, reactive } from 'vue'
 import type { FormInstance } from 'element-plus'
+import { priceCalc } from '@/services/api/common'
 import AppDrawer from '@pc/components/base/drawer/index.vue'
 
 const show = shallowRef(true)
 const colors = ['D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N']
 const claritys = ['IF', 'VVS1', 'VVS2', 'VS1', 'VS2', 'SI1', 'SI2', 'SI3', 'I1', 'I2', 'I3']
 const formRef = shallowRef<FormInstance>()
+const loading = shallowRef(false)
+const operator = shallowRef(1) // 运算符
+const dataList = shallowRef<Ermcp.PriceCalcRsp[]>([])
+
+const formData = reactive<Partial<Ermcp.PriceCalcReq>>({
+    zsshape: undefined, // 形状 - 1:BR(圆形) 2:PS(异形)
+    zscolor: '', // 颜色(D-M)
+    zsclarity: '', // 净度
+    weight: undefined, // 重量
+    rate: undefined, // 汇率
+    discount: undefined, // 折扣(%), 方向(加:10, 减:-10 )
+})
+
+const formSubmit = () => {
+    loading.value = true
+    let discount = formData.discount
+
+    if (discount && operator.value === 2) {
+        discount = -discount
+    }
+
+    priceCalc({
+        data: {
+            ...formData,
+            discount
+        },
+        success: (res) => {
+            dataList.value = res.data
+        },
+        complete: () => {
+            loading.value = false
+        }
+    })
+}
 </script>

+ 71 - 10
src/packages/pc/components/layouts/header/components/certificate/index.vue

@@ -1,29 +1,90 @@
 <!-- 证书查询 -->
 <template>
     <app-drawer title="证书查询" :width="600" v-model:show="show">
-        <el-tabs>
-            <el-tab-pane label="国内" name="first">User</el-tab-pane>
-            <el-tab-pane label="国际" name="second">Config</el-tab-pane>
+        <el-tabs v-model="certTab">
+            <el-tab-pane label="国内" :name="1" />
+            <el-tab-pane label="国际" :name="2" />
         </el-tabs>
-        <ul>
+        <el-radio-group v-model="formData.certtype">
+            <el-radio :label="item.certtype" v-for="(item, index) in certList" :key="index">
+                {{ item.certtype }}
+            </el-radio>
+        </el-radio-group>
+        <ul v-if="selectedCert">
             <li>
-                <label>National Gemological Training Centre</label>
-                <el-input placeholder="请输入证书号" />
+                <label>{{ selectedCert.orgenname }}</label>
+                <el-input placeholder="请输入证书号" v-model="formData.certno" />
             </li>
             <li>
-                <label>国家珠宝玉石质量监督检验中心</label>
-                <el-input placeholder="请输入防伪码" />
+                <label>{{ selectedCert.orgcnname }}</label>
+                <el-input placeholder="请输入防伪码" v-model="formData.certcode" />
             </li>
             <li>
-                <el-button type="primary">查询</el-button>
+                {{ selectedCert.certtype }}证书数据来源于官网,所有权归{{ selectedCert.certtype }}所有。
+            </li>
+            <li>
+                <el-button type="primary" @click="formSubmit">查询</el-button>
             </li>
         </ul>
     </app-drawer>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef } from 'vue'
+import { reactive, shallowRef, computed } from 'vue'
+import { ElMessage } from 'element-plus'
+import { gzCertAddressConfig, gzCertAddressParam } from '@/services/api/common'
 import AppDrawer from '@pc/components/base/drawer/index.vue'
 
 const show = shallowRef(true)
+const certTab = shallowRef(1)
+const dataList = shallowRef<Ermcp.GzCertAddressConfigRsp[]>([])
+const urlParams = shallowRef<Ermcp.GzCertAddressParamRsp[]>([])
+
+const formData = reactive({
+    certtype: '', // 证书类型
+    certno: '', // 证书号
+    certcode: '', // 防伪码
+})
+
+// 证书列表
+const certList = computed(() => (dataList.value.filter((e) => e.certregion === certTab.value)))
+// 当前选中的证书
+const selectedCert = computed(() => (dataList.value.find((e) => e.certtype === formData.certtype)))
+
+const formSubmit = () => {
+    const cert = selectedCert.value
+    const params = urlParams.value.filter((e) => e.certtype === formData.certtype)
+
+    const qs = params.reduce((res, e, i) => {
+        if (i === 0) {
+            res.push(`${e.paramkey}=${formData.certno}`)
+        }
+        if (i === 1) {
+            res.push(`${e.paramkey}=${formData.certcode}`)
+        }
+        return res
+    }, [] as string[])
+
+    if (cert) {
+        const url = cert.queryaddress + '?' + qs.join('&')
+        window.open(url)
+    } else {
+        ElMessage.success('查询失败')
+    }
+}
+
+gzCertAddressParam({
+    success: (res) => {
+        urlParams.value = res.data
+    }
+})
+
+gzCertAddressConfig({
+    success: (res) => {
+        if (res.data.length) {
+            formData.certtype = res.data[0].certtype
+        }
+        dataList.value = res.data
+    }
+})
 </script>

+ 23 - 0
src/packages/pc/components/modules/performance-rule/index.less

@@ -0,0 +1,23 @@
+.app-performance-rule {
+    display   : flex;
+    margin-top: 8px;
+
+    &:empty {
+        display: none;
+    }
+
+    .block {
+        display       : flex;
+        flex-direction: column;
+        align-items   : center;
+
+        &:not(:first-child) {
+            margin-left: 10px;
+        }
+
+        &-label {
+            font-size : 12px;
+            margin-top: 4px;
+        }
+    }
+}

+ 22 - 0
src/packages/pc/components/modules/performance-rule/index.vue

@@ -0,0 +1,22 @@
+<template>
+    <div class="app-performance-rule">
+        <div class="block" v-for="(step, j) in item?.LstStep" :key="j">
+            <el-tag :type="j % 2 ? 'warning' : ''" disable-transitions>{{ step.steptypename }}</el-tag>
+            <span class="block-label">{{ step.stepdate }}</span>
+        </div>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import { PropType } from 'vue'
+
+defineProps({
+    item: {
+        type: Object as PropType<Ermcp.PermancePlanTmpRsp>,
+    }
+})
+</script>
+
+<style lang="less">
+@import './index.less';
+</style>

+ 0 - 20
src/packages/pc/components/modules/performance/index.less

@@ -11,25 +11,5 @@
         &.selected &__title {
             font-weight: bold;
         }
-
-        &__content {
-            display   : flex;
-            margin-top: 8px;
-
-            .block {
-                display       : flex;
-                flex-direction: column;
-                align-items   : center;
-
-                &:not(:first-child) {
-                    margin-left: 10px;
-                }
-
-                &-label {
-                    font-size : 12px;
-                    margin-top: 4px;
-                }
-            }
-        }
     }
 }

+ 7 - 17
src/packages/pc/components/modules/performance/index.vue

@@ -1,22 +1,18 @@
 <template>
     <el-select popper-class="app-performance" value-key="autoid" :placeholder="placeholder" v-model="selectedItem"
         @change="onChange" clearable>
-        <el-option class="app-performance-item" v-for="(item, i) in dataList" :key="i" :label="item.templatename"
-            :value="item">
+        <el-option class="app-performance-item" v-for="(item, i) in performanceTemplates" :key="i"
+            :label="item.templatename" :value="item">
             <h4 class="app-performance-item__title">{{ item.templatename }}</h4>
-            <div class="app-performance-item__content">
-                <div class="block" v-for="(step, j) in item.LstStep" :key="j">
-                    <el-tag :type="j % 2 ? 'warning' : ''">{{ step.steptypename }}</el-tag>
-                    <span class="block-label">{{ step.stepdate }}</span>
-                </div>
-            </div>
+            <app-performance-rule :item="item" />
         </el-option>
     </el-select>
 </template>
 
 <script lang="ts" setup>
 import { shallowRef } from 'vue'
-import { queryPermancePlanTmp } from '@/services/api/performance'
+import { usePerformanceStore } from '@/stores'
+import AppPerformanceRule from '../performance-rule/index.vue'
 
 const props = defineProps({
     modelValue: Number,
@@ -27,20 +23,14 @@ const props = defineProps({
 })
 
 const emit = defineEmits(['update:modelValue'])
-
-const dataList = shallowRef<Ermcp.PermancePlanTmpRsp[]>([])
+const { performanceTemplates } = usePerformanceStore()
 const selectedItem = shallowRef<Ermcp.PermancePlanTmpRsp>()
 
 const onChange = (item: Ermcp.PermancePlanTmpRsp) => {
     emit('update:modelValue', item.autoid)
 }
 
-queryPermancePlanTmp({
-    success: (res) => {
-        dataList.value = res.data
-        selectedItem.value = res.data.find((e) => e.autoid === props.modelValue)
-    }
-})
+selectedItem.value = performanceTemplates.value.find((e) => e.autoid === props.modelValue)
 </script>
 
 <style lang="less">

+ 2 - 2
src/packages/pc/views/boot/index.vue

@@ -30,8 +30,8 @@ const initService = async () => {
     loading.value = false
   })
 
-  await getAllEnumList().result
-  await getErrorInfoList().result
+  await getAllEnumList()
+  await getErrorInfoList()
 
   if (getToken()) {
     // 等待连接交易服务

+ 16 - 1
src/packages/pc/views/customs/bonded/index.vue

@@ -1,9 +1,24 @@
+<!-- 交易服务-保税服务 -->
 <template>
     <app-view>
-        保税
+        <!-- 表格数据 -->
+        <app-table :data="dataList" v-model:columns="columns" :loading="loading">
+            <!-- 操作 -->
+            <template #operate="{ row }">
+                <app-auth-operation :options="{ selectedRow: row }" />
+            </template>
+            <template #footer>
+                <app-pagination :total="total" v-model:page-size="pageSize" v-model:page-index="pageIndex" />
+            </template>
+        </app-table>
     </app-view>
 </template>
 
 <script lang="ts" setup>
+import { useBSFWOrder } from '@/business/customs'
+import AppAuthOperation from '@pc/components/modules/auth-operation/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+import AppPagination from '@pc/components/base/pagination/index.vue'
 
+const { loading, dataList, columns, total, pageIndex, pageSize } = useBSFWOrder()
 </script>

+ 16 - 1
src/packages/pc/views/customs/exit/index.vue

@@ -1,9 +1,24 @@
+<!-- 交易服务-出境检测 -->
 <template>
     <app-view>
-        出境
+        <!-- 表格数据 -->
+        <app-table :data="dataList" v-model:columns="columns" :loading="loading">
+            <!-- 操作 -->
+            <template #operate="{ row }">
+                <app-auth-operation :options="{ selectedRow: row }" />
+            </template>
+            <template #footer>
+                <app-pagination :total="total" v-model:page-size="pageSize" v-model:page-index="pageIndex" />
+            </template>
+        </app-table>
     </app-view>
 </template>
 
 <script lang="ts" setup>
+import { useCJJCOrder } from '@/business/customs'
+import AppAuthOperation from '@pc/components/modules/auth-operation/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+import AppPagination from '@pc/components/base/pagination/index.vue'
 
+const { loading, dataList, columns, total, pageIndex, pageSize } = useCJJCOrder()
 </script>

+ 8 - 1
src/packages/pc/views/trade/bargain/components/details/index.vue

@@ -59,7 +59,10 @@
                             </tr>
                             <tr>
                                 <td>履约规则</td>
-                                <td>{{details.performancetemplateid}}</td>
+                                <td>
+                                    <app-performance-rule
+                                        :item="getPerformanceTemplateById(details.performancetemplateid)" />
+                                </td>
                             </tr>
                             <tr>
                                 <td>备注</td>
@@ -76,7 +79,9 @@
 
 <script lang="ts" setup>
 import { PropType, computed } from 'vue'
+import { usePerformanceStore } from '@/stores'
 import AppGoods from '@pc/views/warehousing/goods/components/details/index.vue'
+import AppPerformanceRule from '@pc/components/modules/performance-rule/index.vue'
 
 const props = defineProps({
     selectedRow: {
@@ -85,6 +90,8 @@ const props = defineProps({
     },
 })
 
+const { getPerformanceTemplateById } = usePerformanceStore()
+
 const details = computed(() => {
     if ('buywrtradeorderid' in props.selectedRow) {
         return props.selectedRow

+ 7 - 3
src/packages/pc/views/trade/bargain/index.vue

@@ -10,14 +10,18 @@
             <template #applystatus="{ value }">
                 {{ getApplyStatusName(value) }}
             </template>
-            <!-- 克拉单价 -->
-            <template #priceper="{ row }">
-                {{ row.zscurrencytypedisplayunit + formatDecimal(row.priceper) }}
+            <!-- 价 -->
+            <template #price="{ row }">
+                {{ row.zscurrencytypedisplayunit + formatDecimal(row.price) }}
             </template>
             <!-- 我的出价 -->
             <template #applyprice="{ row }">
                 {{ row.zscurrencytypedisplayunit + formatDecimal(row.applyprice) }}
             </template>
+            <!-- 克拉单价 -->
+            <template #priceper="{ row }">
+                {{ row.zscurrencytypedisplayunit + formatDecimal(row.priceper) }}
+            </template>
             <!-- 操作 -->
             <template #operate="{ row }">
                 <app-auth-operation :menus="handleTableButtons(row)" :options="{ selectedRow: row }"

+ 7 - 1
src/packages/pc/views/trade/buy/components/details/index.vue

@@ -20,6 +20,10 @@
                 <el-descriptions-item label="切工">{{ selectedRow.zscuttypedisplay }}</el-descriptions-item>
                 <el-descriptions-item label="荧光">{{ selectedRow.zsfluorescencetypedisplay }}</el-descriptions-item>
             </el-descriptions>
+            <div>
+                <div>履约规则</div>
+                <app-performance-rule :item="getPerformanceTemplateById(selectedRow.performancetemplateid)" />
+            </div>
             <template v-for="(auth, index) in getAuthComponent()" :key="index">
                 <component :is="componentMap.get(auth.code)" v-bind="{ selectedRow }" v-if="showComponent" />
             </template>
@@ -30,7 +34,8 @@
 <script lang="ts" setup>
 import { computed, PropType } from 'vue'
 import { useAuth } from '@/hooks/auth'
-import { useLoginStore } from '@/stores'
+import { useLoginStore, usePerformanceStore } from '@/stores'
+import AppPerformanceRule from '@pc/components/modules/performance-rule/index.vue'
 
 const props = defineProps({
     code: String,
@@ -42,6 +47,7 @@ const props = defineProps({
 
 const { getUserId } = useLoginStore()
 const { componentMap, getAuthComponent } = useAuth(props.code)
+const { getPerformanceTemplateById } = usePerformanceStore()
 
 // 不能购买自己发布的求购
 const showComponent = computed(() => {

+ 14 - 3
src/packages/pc/views/trade/delisting/components/details/index.vue

@@ -54,7 +54,13 @@
                             </tr>
                             <tr>
                                 <td>履约规则</td>
-                                <td>/WrTrade2/QueryWrPerformancePlanStep</td>
+                                <td>
+                                    <ul>
+                                        <li v-for="(item,index) in dataList" :key="index">
+                                            {{item.steptypename}}
+                                        </li>
+                                    </ul>
+                                </td>
                             </tr>
                         </tbody>
                     </table>
@@ -67,8 +73,9 @@
 <script lang="ts" setup>
 import { PropType } from 'vue'
 import { BuyOrSell } from '@/constants/order'
+import { usePerformancePlanStep } from '@/business/order'
 
-defineProps({
+const props = defineProps({
     teleportTo: {
         type: String as PropType<'#appPageTeleport' | '#appMainTeleport'>,
         default: '#appPageTeleport'
@@ -79,7 +86,11 @@ defineProps({
     },
     selectedRow: {
         type: Object as PropType<Ermcp.MyDeListingRsp>,
-        default: () => ({})
+        required: true
     },
 })
+
+const { dataList, getPlanStepList } = usePerformancePlanStep(props.selectedRow.performanceplanid)
+
+getPlanStepList()
 </script>

+ 8 - 2
src/packages/pc/views/trade/purchase/components/details/index.vue

@@ -60,7 +60,10 @@
                             </tr>
                             <tr>
                                 <td>履约规则</td>
-                                <td></td>
+                                <td>
+                                    <app-performance-rule
+                                        :item="getPerformanceTemplateById(selectedRow.performancetemplateid)" />
+                                </td>
                             </tr>
                             <tr>
                                 <td>备注</td>
@@ -91,9 +94,10 @@
 import { PropType, shallowRef } from 'vue'
 import { formatDecimal } from '@/filters'
 import { getApplyStatusName } from '@/constants/order'
-import { useLoginStore } from '@/stores'
+import { useLoginStore, usePerformanceStore } from '@/stores'
 import { queryMyDelistingApply } from '@/services/api/trade'
 import AppTable from '@pc/components/base/table/index.vue'
+import AppPerformanceRule from '@pc/components/modules/performance-rule/index.vue'
 
 const props = defineProps({
     teleportTo: {
@@ -107,6 +111,8 @@ const props = defineProps({
 })
 
 const { getUserId } = useLoginStore()
+const { getPerformanceTemplateById } = usePerformanceStore()
+
 const dataList = shallowRef<Ermcp.MyDelistingApplyRsp[]>([])
 const columns = shallowRef<Ermcp.TableColumn[]>([
     { prop: 'selldelistingapplyid', label: '询价单号', show: true },

+ 8 - 2
src/packages/pc/views/trade/sale/components/details/index.vue

@@ -52,7 +52,10 @@
                             </tr>
                             <tr>
                                 <td>履约规则</td>
-                                <td>{{selectedRow.performancetemplateid}}</td>
+                                <td>
+                                    <app-performance-rule
+                                        :item="getPerformanceTemplateById(selectedRow.performancetemplateid)" />
+                                </td>
                             </tr>
                         </tbody>
                     </table>
@@ -79,9 +82,10 @@
 import { PropType, shallowRef } from 'vue'
 import { formatDecimal } from '@/filters'
 import { getApplyStatusName } from '@/constants/order'
-import { useLoginStore } from '@/stores'
+import { useLoginStore, usePerformanceStore } from '@/stores'
 import { queryMyBargainApply } from '@/services/api/trade'
 import AppTable from '@pc/components/base/table/index.vue'
+import AppPerformanceRule from '@pc/components/modules/performance-rule/index.vue'
 
 const props = defineProps({
     teleportTo: {
@@ -95,6 +99,8 @@ const props = defineProps({
 })
 
 const { getUserId } = useLoginStore()
+const { getPerformanceTemplateById } = usePerformanceStore()
+
 const dataList = shallowRef<Ermcp.MyBargainApplyRsp[]>([])
 const columns = shallowRef<Ermcp.TableColumn[]>([
     { prop: 'wrbargainid', label: '询价单号', show: true },

+ 4 - 2
src/packages/pc/views/warehousing/goods/components/details/index.vue

@@ -66,7 +66,7 @@
                 </div>
                 <div class="rule" style="margin-bottom:48px" v-if="details.performancetemplateid !== 0">
                     <h1>履约规则</h1>
-                    {{details.performancetemplateid}}
+                    <app-performance-rule :item="getPerformanceTemplateById(details.performancetemplateid)" />
                 </div>
                 <div class="property" style="line-height:normal">
                     <h1>钻石属性</h1>
@@ -126,9 +126,10 @@
 import { computed, PropType, defineAsyncComponent } from 'vue'
 import { formatDecimal } from '@/filters'
 import { CurrencyType } from '@/constants/diamond'
-import { useLoginStore, useFavoriteStore, useExrateStore } from '@/stores'
+import { useLoginStore, useFavoriteStore, useExrateStore, usePerformanceStore } from '@/stores'
 import { useComponent } from '@/hooks/component'
 import { useDiamondDetails } from '@/business/goods'
+import AppPerformanceRule from '@pc/components/modules/performance-rule/index.vue'
 
 const componentMap = new Map<string, unknown>([
     ['favorite', defineAsyncComponent(() => import('../favorite/index.vue'))], // 收藏
@@ -151,6 +152,7 @@ const emit = defineEmits(['closed'])
 const { getUserId } = useLoginStore()
 const { getExrate, exchangeRate } = useExrateStore()
 const { hasFavorite } = useFavoriteStore()
+const { getPerformanceTemplateById } = usePerformanceStore()
 const { details, getDiamondDetails } = useDiamondDetails(props.selectedRow.goodsno)
 
 const { componentId, openComponent, closeComponent } = useComponent((componentName) => {

+ 2 - 2
src/packages/pc/views/warehousing/goods/components/edit/diamonds.vue

@@ -100,7 +100,7 @@ const components = {
 }
 
 const emit = defineEmits(['cancel'])
-const { loading, formData, performanceId, caratUnit, selectedType, enums, warehouseList, currencyInfo, formSubmit } = useDiamondForm(Category.Diamonds)
+const { loading, formData, performanceId, caratUnit, selectedType, enums, warehouseList, currencyInfo, addOrUpdate } = useDiamondForm(Category.Diamonds)
 const formRef = ref<FormInstance>()
 
 const formRules: FormRules = {
@@ -183,7 +183,7 @@ const formRules: FormRules = {
 const onSubmit = () => {
     formRef.value?.validate((valid) => {
         if (valid) {
-            formSubmit().then(() => {
+            addOrUpdate().then(() => {
                 ElMessage.success('提交成功')
                 emit('cancel', true)
             }).catch((err) => {

+ 21 - 0
src/services/api/common/index.ts

@@ -83,4 +83,25 @@ export function postNoticeReaded(params: HttpRequest<{ req: Ermcp.NoticeReadedRe
  */
 export function queryErrorInfos(params: HttpRequest<{ req: Ermcp.ErrorInfosReq, rsp: Ermcp.ErrorInfosRsp[] }>) {
     return httpRequest('/Common/QueryErrorInfos', 'get', params);
+}
+
+/**
+ * 钻石价格计算器
+ */
+export function priceCalc(params: HttpRequest<{ req: Partial<Ermcp.PriceCalcReq>, rsp: Ermcp.PriceCalcRsp[] }>) {
+    return httpRequest('/Guangzuan/PriceCalc', 'get', params);
+}
+
+/**
+ * Rapaport最新报价表(广钻)
+ */
+export function gzCertAddressConfig(params: HttpRequest<{ rsp: Ermcp.GzCertAddressConfigRsp[] }>) {
+    return httpRequest('/Guangzuan/GzCertAddressConfig', 'get', params);
+}
+
+/**
+ * 钻石证书地址参数
+ */
+export function gzCertAddressParam(params: HttpRequest<{ rsp: Ermcp.GzCertAddressParamRsp[] }>) {
+    return httpRequest('/Guangzuan/GzCertAddressParam', 'get', params);
 }

+ 74 - 0
src/services/api/customs/index.ts

@@ -0,0 +1,74 @@
+import { httpRequest } from '@/services/http'
+import { HttpRequest } from '@/services/http/interface'
+import { tradeServerRequest } from '@/services/socket/trade'
+import { TradeRequest } from '@/services/socket/trade/interface'
+
+/**
+ * 查询出境检测单据
+ */
+export function queryGZCJJCOrder(params: HttpRequest<{ req: Ermcp.GZCJJCOrderReq, rsp: Ermcp.GZCJJCOrderRsp[] }>) {
+    return httpRequest('/Guangzuan/QueryGZCJJCOrder', 'get', params);
+}
+
+/**
+ * 查询出境检测单据明细(批次信息)
+ */
+export function queryGZCJJCOrderDetail(params: HttpRequest<{ req: Ermcp.GZCJJCOrderDetailReq, rsp: Ermcp.GZCJJCOrderDetailRsp[] }>) {
+    return httpRequest('/Guangzuan/QueryGZCJJCOrderDetail', 'get', params);
+}
+
+/**
+ * 查询保税服务单据
+ */
+export function queryGZBSFWOrder(params: HttpRequest<{ req: Ermcp.GZBSFWOrderReq, rsp: Ermcp.GZBSFWOrderRsp[] }>) {
+    return httpRequest('/Guangzuan/QueryGZBSFWOrder', 'get', params);
+}
+
+/**
+ * 保税服务单据操作信息
+ */
+export function gzBSFWOrderOperate(params: HttpRequest<{ req: Ermcp.GZBSFWOrderOperateReq, rsp: Ermcp.GZBSFWOrderOperateRsp[] }>) {
+    return httpRequest('/Guangzuan/GZBSFWOrderOperate', 'get', params);
+}
+
+/**
+ * 查询保税服务单据明细
+ */
+export function queryGZBSFWOrderDetail(params: HttpRequest<{ req: Ermcp.GZBSFWOrderDetailReq, rsp: Ermcp.GZBSFWOrderDetailRsp[] }>) {
+    return httpRequest('/Guangzuan/QueryGZBSFWOrderDetail', 'get', params);
+}
+
+/**
+ * 出境保税单据文件
+ */
+export function queryGZCJBSOrderFile(params: HttpRequest<{ req: Ermcp.GZCJBSOrderFileReq, rsp: Ermcp.GZCJBSOrderFileRsp[] }>) {
+    return httpRequest('/Guangzuan/QueryGZCJBSOrderFile', 'get', params);
+}
+
+/**
+ * 出境检测申请
+ */
+export function cjjcApply(params: TradeRequest<Proto.CJJCApplyReq, Proto.CJJCApplyRsp>) {
+    return tradeServerRequest('CJJCApplyReq', 'CJJCApplyRsp', params);
+}
+
+/**
+ * 出境检测会员操作
+ */
+export function cjjcMemberOperate(params: TradeRequest<Proto.CJJCMemberOperateReq, Proto.CJJCMemberOperateRsp>) {
+    return tradeServerRequest('CJJCMemberOperateReq', 'CJJCMemberOperateRsp', params);
+}
+
+/**
+ * 出境检测确认预付款生成文件
+ */
+export function cjjcConfirmMarginBuildFileReq(params: TradeRequest<Proto.CJJCConfirmMarginBuildFileReq, Proto.CJJCConfirmMarginBuildFileRsp>) {
+    return tradeServerRequest('CJJCConfirmMarginBuildFileReq', 'BSFWMemberOperateRsp', params);
+}
+
+/**
+ * 保税服务会员操作
+ */
+export function bsfwMemberOperate(params: TradeRequest<Proto.BSFWMemberOperateReq, Proto.BSFWMemberOperateRsp>) {
+    return tradeServerRequest('BSFWMemberOperateReq', 'BSFWMemberOperateRsp', params);
+}

+ 10 - 0
src/services/api/favorite/index.ts

@@ -1,9 +1,19 @@
 import { httpRequest } from '@/services/http'
 import { HttpRequest } from '@/services/http/interface'
+import { tradeServerRequest } from '@/services/socket/trade'
+import { TradeRequest } from '@/services/socket/trade/interface'
+import { Market } from '@/constants/market'
 
 /**
  * 查询我的收藏
  */
 export function queryMyFavorite(params: HttpRequest<{ req: Ermcp.MyFavoriteReq, rsp: Ermcp.MyFavoriteRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyFavorite', 'get', params);
+}
+
+/**
+ * 商品收藏操作
+ */
+export function goodsFavoriteOperate(params: TradeRequest<Proto.GoodsFavoriteOperateReq, Proto.GoodsFavoriteOperateRsp>) {
+    return tradeServerRequest('GoodsFavoriteOperateReq', 'GoodsFavoriteOperateRsp', params, Market.GZ);
 }

+ 0 - 7
src/services/api/goods/index.ts

@@ -37,11 +37,4 @@ export function addDiamond(params: TradeRequest<Proto.AddZSGoodsReq, Proto.AddZS
  */
 export function receiptZSOutApply(params: TradeRequest<Proto.ReceiptZSOutApplyReq, Proto.ReceiptZSOutApplyRsp>) {
     return tradeServerRequest('ReceiptZSOutApplyReq', 'ReceiptZSOutApplyRsp', params, 4);
-}
-
-/**
- * 商品收藏操作
- */
-export function goodsFavoriteOperate(params: TradeRequest<Proto.GoodsFavoriteOperateReq, Proto.GoodsFavoriteOperateRsp>) {
-    return tradeServerRequest('GoodsFavoriteOperateReq', 'GoodsFavoriteOperateRsp', params, Market.GZ);
 }

+ 8 - 8
src/stores/@next.ts

@@ -109,7 +109,7 @@ setTimeout(() => {
 
 
 interface DefineStoreOptions<S extends object, A extends object> {
-    state: () => S;
+    state: S;
     actions: {
         [key in keyof A]: (context: S, ...args: never) => unknown
     }
@@ -119,8 +119,10 @@ function defineStore<S extends object, A extends object>(options: DefineStoreOpt
     const actions = {} as { [key in keyof A]: <T extends unknown[]>(...args: T) => unknown }
 
     for (const p in options.actions) {
+        const fn = options.actions[p]
+
         actions[p] = (...args) => {
-            return options.actions[p](options.state(), args as never)
+            return fn(options.state, args as never)
         }
     }
 
@@ -130,15 +132,13 @@ function defineStore<S extends object, A extends object>(options: DefineStoreOpt
 }
 
 const dStore = defineStore({
-    state() {
-        return {
-            id: 0,
-            userName: '李兔饼'
-        }
+    state: {
+        id: 0,
+        userName: '李兔饼'
     },
     actions: {
         getAllEnumList(context, userid: number) {
-            //context.id = userid
+            context.id = userid
             return context
         },
     }

+ 38 - 23
src/stores/modules/enum.ts

@@ -1,4 +1,4 @@
-import { toRefs, shallowReadonly, ShallowRef } from 'vue'
+import { toRefs, shallowRef, shallowReadonly, ShallowRef } from 'vue'
 import { queryAllEnums } from '@/services/api/common'
 import { VueStore } from '../base'
 import WebStorage from '@/utils/storage/base'
@@ -17,6 +17,8 @@ interface StoreState {
     allEnums: ShallowRef<Ermcp.EnumRsp[]>;
 }
 
+const enumKeys = ['ZSCategory', 'ZSCurrencyType', 'ZSCurrencyType', 'ZSColorType', 'ZSClarityType', 'ZSCutType', 'ZSShapeType', 'ZSSymmetryType', 'ZSPolishType', 'ZSFluorescenceType', 'ZSCertType', 'ZSCrystalType', 'ZSCZColor1Type', 'ZSCZColor2Type', 'ZSCZColor3Type', 'ZSStyleType', 'signstatus', 'applystatus', 'executetype', 'certificatetype', 'clientType', 'wrApplyStatus', 'performanceStatus', 'stepStatus'] as const
+
 /**
  * 枚举存储类
  */
@@ -28,49 +30,62 @@ const store = new (class extends VueStore<StoreState>{
             allEnums: storage.getRef(),
         }
         super(state)
+
+        // 初始化枚举列表
+        for (const key of enumKeys) {
+            this.enumMap.set(key, shallowRef<Ermcp.EnumRsp[]>([]))
+        }
+    }
+
+    private enumMap = new Map<typeof enumKeys[number], ShallowRef<Ermcp.EnumRsp[]>>()
+
+    private setEnumMap = () => {
+        // 清空列表数据
+        for (const item of this.enumMap.values()) {
+            item.value = []
+        }
+        this.state.allEnums.forEach((e) => {
+            const mapKey = enumKeys.find((key) => key === e.enumdiccode)
+            if (mapKey && e.enumitemstatus === 1) {
+                const enumRef = this.enumMap.get(mapKey)
+                enumRef?.value.push(e)
+            }
+        })
     }
 
     actions = {
         /** 获取所有枚举列表 */
         getAllEnumList: () => {
             if (this.state.allEnums.length) {
+                this.setEnumMap()
                 return Promise.resolve()
             }
             this.state.loading = true
             return queryAllEnums({
                 success: (res) => {
                     this.state.allEnums = res.data
+                    this.setEnumMap()
                 },
                 complete: () => {
                     this.state.loading = false
                 }
             })
         },
-        /** 获取枚举类型 */
-        getEnumTypes: <T extends string[]>(...args: T) => {
-            const enumMap = new Map<typeof args[number], Ermcp.EnumRsp[]>()
-            this.state.allEnums.forEach((e) => {
-                if (args.some((code) => code.toLowerCase() === e.enumdiccode.toLowerCase())) {
-                    const enums = enumMap.get(e.enumdiccode)
-                    if (enums) {
-                        enums.push(e)
-                    } else {
-                        enumMap.set(e.enumdiccode, [e])
-                    }
-                }
-            })
-            return enumMap
-        },
         /** 获取枚举信息 */
-        getEnumTypeInfo: (enums: Ermcp.EnumRsp[], value: number) => {
-            return enums.find((e) => e.enumitemstatus === 1 && e.enumitemname === value)
+        getEnumTypeInfo: (enumKey: typeof enumKeys[number], value: number) => {
+            const enums = this.enumMap.get(enumKey)
+            return enums?.value.find((e) => e.enumitemname === value)
         },
         /** 获取枚举列表 */
-        getEnumTypeList: (enums?: Ermcp.EnumRsp[]) => {
-            return enums?.map((e) => ({
-                label: e.enumdicname,
-                value: e.enumitemname,
-            })) ?? []
+        getEnumTypeList: (enumKey: typeof enumKeys[number]) => {
+            const enums = this.enumMap.get(enumKey)
+            if (enums) {
+                return enums.value.map((e) => ({
+                    label: e.enumdicname,
+                    value: e.enumitemname,
+                }))
+            }
+            return []
         },
         /** 根据枚举值获取枚举名称 */
         getEnumTypeName: (enums: EnumType[], value?: number) => {

+ 6 - 1
src/stores/modules/performance.ts

@@ -36,6 +36,10 @@ const store = new (class extends VueStore<StoreState>{
                 }
             })
         },
+        /** 根据 id 查找对应的履约模板 */
+        getPerformanceTemplateById: (id: number) => {
+            return this.state.performanceTemplates.find((e) => e.autoid === id)
+        },
         /** 获取履约步骤枚举列表 */
         getPerformanceStepTypeList: () => {
             if (this.state.performanceStepTypes.length) {
@@ -50,7 +54,8 @@ const store = new (class extends VueStore<StoreState>{
                     this.state.loading = true
                 }
             })
-        }
+        },
+
     }
 })
 

+ 37 - 0
src/types/ermcp/common.d.ts

@@ -82,4 +82,41 @@ declare namespace Ermcp {
         operatecode: string; // 所属操作
         rownumber: string; // 行号
     }
+
+    /** 钻石价格计算器 请求 */
+    interface PriceCalcReq {
+        zsshape: number; // 形状 - 1:BR(圆形) 2:PS(异形)
+        zscolor: string; // 颜色(D-M)
+        zsclarity: string; // 净度
+        weight: number; // 重量
+        rate: number; // 汇率
+        discount?: number; // 折扣(%), 方向(加:10, 减:-10 )
+    }
+
+    /** 钻石价格计算器 响应 */
+    interface PriceCalcRsp {
+        dollar: string; // 美元
+        rmb: string; // 人民币
+    }
+
+    /** Rapaport最新报价表(广钻) 响应 */
+    interface GzCertAddressConfigRsp {
+        certregion: number; // 证书地域 - 1:国内 2:国际
+        certtype: string; // 证书类型
+        orderindex: number; // 显示顺序
+        orgcnname: string; // 机构名称(中文)
+        orgenname: string; // 机构名称(英文)
+        queryaddress: string; // 查询地址
+        remark: string; // 备注
+        updatetime: string; // 更新时间
+    }
+
+    /** 钻石证书地址参数 响应 */
+    interface GzCertAddressParamRsp {
+        certtype: string; // 证书类型
+        orderindex: number; // 参数顺序
+        paramkey: string; // 参数Key
+        paramname: string; // 参数名称
+        updatetime: string; // 更新时间
+    }
 }

+ 201 - 0
src/types/ermcp/customs.d.ts

@@ -0,0 +1,201 @@
+/** 企业风管 */
+declare namespace Ermcp {
+    /** 查询出境检测单据 请求 */
+    interface GZCJJCOrderReq {
+        userid: number; // 用户ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 查询出境检测单据 响应 */
+    interface GZCJJCOrderRsp {
+        accountid: number; // 资金账户ID
+        addresscn: string; // 地址(中文)
+        addressen: string; // 地址(英文)
+        advanceamount: number; // 总预付款
+        colorrange: string; // 颜色范围
+        companynamecn: string; // 公司名称(中文)
+        companynameen: string; // 公司名称(英文)
+        contactname: string; // 联系人姓名
+        contactphoneno: string; // 联系人电话
+        contactposition: string; // 联系人职位
+        createtime: string; // 创建时间
+        email: string; // 邮箱
+        executestatus: number; // 执行状态 - 1:未生效 2:进行中 3:已结束
+        gzcjaccount: string; // 送检账户
+        gzcjaccounttype: number; // 检测账户类型 - 枚举"GZCJAccountType"
+        gzcjcategorytype: number; // 货物品类 - 枚举"GZCJCategoryType"
+        gzcjcategorytypedisplay: string; // 货物品类
+        gzcjdeliverytype: number; // 收货方式 - 枚举"GZCJDeliveryType"
+        gzcjdeliverytypedisplay: string; // 收货方式
+        gzcjstatus: number; // 单据状态(出境检测) - 枚举"GZCJStatus"
+        gzcjstatusdisplay: string; // 单据状态(出境检测)
+        handlestatus: number; // 处理状态
+        invoiceremark: string; // 复核备注 - 发票装箱单使用
+        orderid: number; // 单据ID(801+Unix秒时间戳(10位)+xxxxxx)
+        orderno: string; // 单据编号 - 合同编号:GZDECJJC+单据流水号
+        ordersn: string; // 单据流水号 - yymm000 - yy表示年份,mm表示月份,年份、月份以两位数表示;000表示流水序号,序号不足三位以0补全
+        origincountry: string; // 原产国
+        processingcountry: string; // 成品钻石加工国
+        realservicefee: number; // 应收综合服务费
+        servicefeesum: number; // 汇总综合服务费 - 明细上值汇总
+        settleamount: number; // 总结算费用
+        shaperange: string; // 形状范围
+        totalamount: number; // 总金额(美元)
+        totalgrossweight: number; // 总毛重(克) = 每100颗单颗裸石毛重200克,毛重不足200克按200克计 (TotalNumber/100 向上取整) * 200
+        totalnumber: number; // 总粒数
+        totalweight: number; // 总克拉数(保留3位小数)
+        totalweightgm: number; // 总净重(克) = TotalWeight * 0.2 (2位小数)
+        userid: number; // 用户ID
+        weightrange: string; // 重量规格范围 - Min(Weight) - Max(Weight)
+        zsorigin: string; // 天然钻石毛坯原产地
+    }
+
+    /** 查询出境检测单据明细(批次信息) 请求 */
+    interface GZCJJCOrderDetailReq {
+        userid: number; // 用户ID
+        orderid?: number; // 单据ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 查询出境检测单据明细(批次信息) 响应 */
+    interface GZCJJCOrderDetailRsp {
+        amount: number; // 参考货值(USD)
+        colorinfo: string; // 彩钻信息
+        createtime: string; // 创建时间
+        gzcjmarktype: number; // 刻印服务 - 枚举"GZCJMarkType" 【送检账户为“广钻账户”】
+        gzcjpublishtype: number; // 是否披露处理 - 枚举 GZCJPublishType【送检账户为“广钻账户”】
+        gzcjpublishtypestring: string; // 是否披露处理 - 枚举 GZCJPublishType 对应的显示值
+        gzcjservicetype: number; // 服务类别 - 枚举 GZCJServiceType【送检账户为“广钻账户”】
+        gzcjservicetypestring: string; // 服务类别 - 枚举 GZCJServiceType 对应的显示值
+        gzcjshapetype: number; // 形状 - 枚举"GZCJShapeType"
+        gzcjshapetypestring: string; // 形状(字符) - 枚举"GZCJShapeType"对应的显示值
+        gzno: string; // 货物编号
+        orderdetailid: number; // 单据明细ID(802+Unix秒时间戳(10位)+xxxxxx)
+        orderid: number; // 单据ID(801+Unix秒时间戳(10位)+xxxxxx)
+        orderindex: number; // 顺序
+        origincertno: string; // 原证书号【送检账户为“广钻账户”】
+        remark: string; // 备注(其它)
+        servicefee: number; // 综合服务费 - 根据市场配置计算
+        weight: number; // 重量(CT)
+    }
+
+    /** 查询保税服务单据 请求 */
+    interface GZBSFWOrderReq {
+        userid: number; // 用户ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 查询保税服务单据 响应 */
+    interface GZBSFWOrderRsp {
+        accountid: number; // 资金账户ID
+        addresscn: string; // 地址(中文)
+        addressen: string; // 地址(英文)
+        advanceamount: number; // 总预付款
+        colorrange: string; // 颜色范围
+        companynamecn: string; // 收货人(中文)
+        companynameen: string; // 收货人(英文)
+        contactfax: string; // 收货人传真
+        contactname: string; // 收货人姓名
+        contactphoneno: string; // 收货人电话
+        contentrange: string; // 【内容】内容范围
+        createtime: string; // 创建时间
+        executestatus: number; // 执行状态 - 1:未生效 2:进行中 3:已结束
+        gzbsdeliverytype: number; // 收货方式 - 枚举"GZBSDeliveryType"
+        gzbsstatus: number; // 单据状态(保税服务) - 枚举"GZBSStatus"
+        gzbsstatusdisplay: string; // 单据状态
+        handlestatus: number; // 处理状态
+        orderdate: string; // 单据日期
+        orderid: number; // 单据ID(804+Unix秒时间戳(10位)+xxxxxx)
+        orderno: string; // 单据编号 - GZDEBSFW+单据流水号
+        ordersn: string; // 单据流水号 - yymm000 - yy表示年份,mm表示月份,年份、月份以两位数表示;000表示流水序号,序号不足三位以0补全
+        origincountry: string; // 原产国
+        otherlogistics: string; // 指定其它物流
+        priceper: number; // 单价(美元/克拉) = 总值(美元) / 总净重(克拉)
+        settleamount: number; // 总结算费用 - 实际扣除资金,不含税费保证金
+        shaperange: string; // 形状范围
+        taxmargin: number; // 税费保证金 - 确认结算费用时退回
+        totalamount: number; // 总值(美元)
+        totalgrossweightgm: number; // 总毛重(克)
+        totalnetweightgm: number; // 总净重(克)
+        totalnetweigthct: number; // 总净重(克拉)
+        totalnumber: number; // 总粒数
+        userid: number; // 用户ID
+        weightrange: string; // 重量规格范围 - Min(NetWeigthCT)- Max(NetWeigthCT)
+    }
+
+    /** 保税服务单据操作信息 请求 */
+    interface GZBSFWOrderOperateReq {
+        orderid: number; // 单据ID
+    }
+
+    /** 保税服务单据操作信息 响应 */
+    interface GZBSFWOrderOperateRsp {
+        advanceproofaddr: string; // 预付款收款凭证(确认结算费用时)
+        bankfee: number; // 汇款银行手续费
+        bankproofaddr: string; // 广钻汇款银行手续费凭证(确认结算费用时)
+        customsproofaddr: string; // 海关税费保证金收据(确认结算费用时)
+        gzbsstatus: number; // 操作后单据状态 - 枚举"GZBSStatus"
+        logisticsfee: number; // 代缴物流保险费
+        logisticsproofaddr: string; // 代缴物流保险费凭证(确认结算费用时)
+        operatetime: string; // 操作时间
+        operatoraccount: string; // 操作人账号 - systemmanager的logincode 或 loginaccount的logincode,无则用loginid
+        operatorid: number; // 操作人ID - systemmanager的autoid 或 loginaccount的loginid
+        operatorname: string; // 操作人名称 - systemmanager的username 或 loginaccount的logincode,无则用loginid
+        operatorsrc: number; // 操作人来源 - 1:管理端 2:终端
+        orderid: number; // 单据ID(804+Unix秒时间戳(10位)+xxxxxx)
+        otherfee: number; // 其它费用
+        remark: string; // 操作备注
+        servicefee: number; // 综合服务费
+        taxmargin: number; // 税费保证金
+        totalfee: number; // 总费用 = 费用之和 (结算费用时不含税费保证金)
+    }
+
+    /** 查询保税服务单据明细 请求 */
+    interface GZBSFWOrderDetailReq {
+        userid: number; // 用户ID
+        orderid?: number; // 单据ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 查询保税服务单据明细 响应 */
+    interface GZBSFWOrderDetailRsp {
+        colorinfo: string; // 彩钻信息
+        createtime: string; // 创建时间
+        grossweightgm: number; // 毛重(克)
+        gzcjshape: string; // 形状(字符)
+        netweigthct: number; // 净重(克拉)
+        netweigthgm: number; // 净重(克)
+        ordercontent: string; // 内容
+        orderdetailid: number; // 单据明细ID(805+Unix秒时间戳(10位)+xxxxxx)
+        orderid: number; // 单据ID(804+Unix秒时间戳(10位)+xxxxxx)
+        orderindex: number; // 顺序
+        perprice: number; // 单价(美元/克拉) = 总值(美元) / 净重(克拉)
+        remark: string; // 备注(其它)
+        totalamount: number; // 总值(美元)
+    }
+
+    /** 出境保税单据文件 请求 */
+    interface GZCJBSOrderFileReq {
+        orderid: number; // 单据ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 出境保税单据文件 响应 */
+    interface GZCJBSOrderFileRsp {
+        canmembervisit: number; // 会员是否可访问 - 1:可 2:不可
+        fileaddress: string; // 文件地址
+        filegentype: number; // 文件生成类型 - 1:系统生成 2:手动上传
+        filename: string; // 文件名称
+        operatetime: string; // 操作时间
+        operatoraccount: string; // 操作人账号 - systemmanager的logincode 或 loginaccount的logincode,无则用loginid
+        operatorid: number; // 操作人ID - systemmanager的autoid 或 loginaccount的loginid
+        operatorsrc: number; // 操作人来源 - 1:管理端 2:终端
+        orderfileid: number; // 单据文件ID(803+Unix秒时间戳(10位)+xxxxxx)
+        orderid: number; // 单据ID(801+Unix秒时间戳(10位)+xxxxxx)
+    }
+}

+ 2 - 1
src/types/ermcp/trade.d.ts

@@ -244,6 +244,7 @@ declare namespace Ermcp {
         marketid: number; // 市场ID
         ordertime: string; // 委托时间
         origin: string; // 原产地
+        performancetemplateid: number; // 履约计划模板ID
         remark: string; // 备注
         userid: number; // 用户ID
         validtime: string; // 有效期限
@@ -475,7 +476,7 @@ declare namespace Ermcp {
         marketid: number; // 市场ID
         matchusername: string; // 对手方
         oritradeamount: number; // 成交金额[商品币种]
-        performanceplanid: number; // 履约计划ID/合同ID
+        performanceplanid: string; // 履约计划ID/合同ID
         qty: number; // 成交重量
         sellaccountid: number; // 卖方账号ID
         sellchargevalue: number; // 卖方手续费

+ 131 - 0
src/types/proto/customs.d.ts

@@ -0,0 +1,131 @@
+import { IMessageHead } from '@/services/socket/trade/protobuf/proto'
+import { number } from 'echarts/core';
+import Long from 'long'
+
+declare global {
+    namespace Proto {
+        /** 货物明细列表 */
+        interface GZCJCategoryDetail {
+            OrderIndex: number; // 顺序,必填
+            GZNo: string; // 货物编号,必填
+            GZCJShapeType: number; // 形状,必填
+            Weight: number; // 重量(CT),3位小数,必填
+            Amount: number; // 参考货值(USD),2位小数,必填
+            ColorInfo: string; // 彩钻信息
+            Remark: string; // 备注
+            GZCJMarkType: number; // 刻印服务,必填
+            GZCJPublishType: number; // 是否披露处理,必填
+            GZCJServiceType: number; // 服务类别,必填
+            OriginCertNo: string; // 原证书号
+        }
+
+        /** 文件列表 */
+        interface FileDetail {
+            FileName: string; // 文件名
+            FilePath: string; // 文件地址
+        }
+
+        /** 出境检测申请请求 */
+        interface CJJCApplyReq {
+            Header?: IMessageHead;
+            UserID: number; // 用户ID,必填
+            AccountID: number; // 资金账户ID,必填
+            OperateID: number; // 操作人ID,LoginAccount的LoginID,必填
+            OperateAccount: string; // 操作人账户,LoginAccount的LoginCode,LoginCode为空则填LoginID,必填
+            GZCJAccountType: number; // 检测账户类型,枚举"GZCJAccountType"NUMBER(2),必填
+            GZCJAccount: string; // 送检账户,GZCJAccountType=1:GIA自有账户
+            CompanyNameCN: string; // 公司名称(中文)
+            CompanyNameEn: string; // 公司名称(英文)
+            AddressCN: string; // 地址(中文)
+            AddressEN: string; // 地址(英文)
+            ContactName: string; // 联系人姓名
+            ContactPosition: string; // 联系人职位
+            ContactPhoneNo: string; // 联系人电话
+            Email: string; // 邮箱
+            GZCJCategoryType: number; // 货物品类,必填
+            ProcessingCountry: string; // 成品钻石加工国
+            ZSOrigin: string; // 天然钻石毛坯原产地
+            GZCJDeliveryType: number; // 收货方式,必填
+            GZCJCategoryDetails: GZCJCategoryDetail[]; // 货物明细列表
+            ApplyType: number; // 申请类型1:保存草稿2:修改草稿
+            OrderID: number; // 单据ID,ApplyType=2,3时,有则填
+            ClientType: number; // 终端类型
+            ClientSerialNo: string; // 客户端流水号
+        }
+
+        /** 出境检测申请响应 */
+        interface CJJCApplyRsp {
+            Header?: IMessageHead;
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            UserID: number; // 用户ID
+            AccountID: number; // 资金账号
+            OrderID: number; // 单据ID
+            ClientSerialNo: string; // 客户端流水号
+        }
+
+        /** 出境检测会员操作请求 */
+        interface CJJCMemberOperateReq {
+            Header?: IMessageHead;
+            UserID: number; // 用户ID,必填
+            OperateID: number; // 操作人ID,必填,LoginAccount的LoginID
+            OperateAccount: string; // 操作人账户,LoginAccount的LoginCode,LoginCode为空则填LoginID,必
+            OrderID: number; // 单据ID,必填
+            OperateType: number; // 操作类型,必填,1:撤回2:确认发货3:确认检测结果
+            Remark: string; // 备注
+            ClientType: number; // 终端类型
+            ClientSerialNo: string; // 客户端流水号
+        }
+
+        /** 出境检测会员操作响应 */
+        interface CJJCMemberOperateRsp {
+            Header?: IMessageHead;
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            UserID: number; // 用户ID
+            AccountID: number; // 资金账号
+            ClientSerialNo: string; // 客户端流水号
+        }
+
+        /** 出境检测确认预付款生成文件接口请求 */
+        interface CJJCConfirmMarginBuildFileReq {
+            Header?: IMessageHead;
+            OrderID: number; // 单据ID,必填
+        }
+
+        /** 出境检测确认预付款生成文件接口响应 */
+        interface CJJCConfirmMarginBuildFileRsp {
+            Header?: IMessageHead;
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            OrderID: number; // 单据ID,必填
+            IsSuccess: number; // 返回码
+        }
+
+        /** 保税服务会员操作请求 */
+        interface BSFWMemberOperateReq {
+            Header?: IMessageHead;
+            UserID: number; // 用户ID,必填
+            OperateID: number; // 操作人ID,必填,LoginAccount的LoginID
+            OperateAccount: string; // 操作人账户,LoginAccount的LoginCode,LoginCode为空则填LoginID,必
+            OrderID: number; // 单据ID,必填
+            OperateType: number; // 操作类型,必填,1:上传发货单2:上传盖章单据3:确认预付款
+            FileDetails: FileDetail[]; // 文件列表
+            Remark: string; // 备注
+            GZBSDeliveryType: number; // 收货方式,OperateType=1:上传发货单时必填,枚举“GZBSDeliveryType”
+            OtherLogistics: string; // 指定其它物流,OperateType=1:上传发货单时填写
+            ClientType: number; // 终端类型
+            ClientSerialNo: string; // 客户端流水号
+        }
+
+        /** 保税服务会员操作响应 */
+        interface BSFWMemberOperateRsp {
+            Header?: IMessageHead;
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            UserID: number; // 用户ID
+            AccountID: number; // 资金账号
+            ClientSerialNo: string; // 客户端流水号
+        }
+    }
+}