Pārlūkot izejas kodu

feat: NG-22: 多国家

tyler 1 gadu atpakaļ
vecāks
revīzija
3ae3ec6797

+ 27 - 11
.env.development

@@ -19,17 +19,33 @@ ENV='development'
 # VUE_APP_SYSTEM_JS='http://ng-upload.elken.com'
 
 # api请求地址
-VUE_APP_BASE_API='http://16.163.228.151:8042'
-# 文件下载地址
-VUE_APP_BASE_DO_API='http://16.163.228.151:8042'
-# CDN文件地址
-VUE_APP_CDN_API='http://16.163.228.151:8042'
-# 区域js文件地址
-VUE_APP_SYSTEM_JS='http://ng-upload.elken.com'
-# 结算页面地址
-VUE_APP_BASE_WEBSITE='http://16.163.228.151:8042'
-# 会员页面地址
-VUE_APP_FRONTEND_WEBSITE='http://16.163.228.151:8045'
+#VUE_APP_BASE_API='http://16.163.228.151:8042'
+## 文件下载地址
+#VUE_APP_BASE_DO_API='http://16.163.228.151:8042'
+## CDN文件地址
+#VUE_APP_CDN_API='http://16.163.228.151:8042'
+## 区域js文件地址
+#VUE_APP_SYSTEM_JS='http://ng-upload.elken.com'
+## 结算页面地址
+#VUE_APP_BASE_WEBSITE='http://16.163.228.151:8042'
+## 会员页面地址
+#VUE_APP_FRONTEND_WEBSITE='http://16.163.228.151:8045'
+# PayStack支付key
+#VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
+## 请求token前缀
+#VUE_APP_ACCESS_TOKEN_PREFIX='Bearer '
+
+ VUE_APP_BASE_API='http://16.163.228.151:8020'
+ # 文件下载地址
+ VUE_APP_BASE_DO_API='http://16.163.228.151:8020'
+ # CDN文件地址
+ VUE_APP_CDN_API='http://16.163.228.151:8021'
+ # 区域js文件地址
+ VUE_APP_SYSTEM_JS='http://16.163.228.151:8021'
+ # 结算页面地址
+ VUE_APP_BASE_WEBSITE='http://16.163.228.151:8019'
+ # 会员页面地址
+ VUE_APP_FRONTEND_WEBSITE='http://16.163.228.151:8017'
 # PayStack支付key
 VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
 # 请求token前缀

+ 1 - 0
package.json

@@ -8,6 +8,7 @@
     "lint": "eslint --ext .js,.vue src",
     "build:prod": "vue-cli-service build",
     "build:stage": "vue-cli-service build --mode staging",
+    "build:dev": "vue-cli-service build --mode development",
     "preview": "node build/index.js --preview",
     "new": "plop",
     "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",

+ 57 - 0
src/api/config.js

@@ -258,3 +258,60 @@ export function updateOtherConfig(data) {
     data
   })
 }
+
+/**
+ * 获取货币
+ * @returns {*}
+ */
+export function fetchCurrenciesList() {
+  return request({
+    url: '/v1/currency/currencies',
+    method: 'get'
+  })
+}
+
+/**
+ * 获取汇率列表
+ * @returns {*}
+ */
+export function fetchCurrencyConversionsList() {
+  return request({
+    url: '/v1/currency/currencies-conversions',
+    method: 'get'
+  })
+}
+
+/**
+ * 设置汇率
+ * @returns {*}
+ */
+export function setCurrencyConversions(data) {
+  return request({
+    url: '/v1/currency/set-currencies-conversions',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 获取运费列表
+ * @returns {*}
+ */
+export function fetchTransportationList() {
+  return request({
+    url: '/v1/transportation/transportation',
+    method: 'get'
+  })
+}
+
+/**
+ * 设置汇率
+ * @returns {*}
+ */
+export function setTransportation(data) {
+  return request({
+    url: '/v1/transportation/set-transportation',
+    method: 'post',
+    data
+  })
+}

+ 2 - 1
src/api/member.js

@@ -340,10 +340,11 @@ export function updateNetworkMoveApply(data) {
  * 空单操作查询
  * @returns {*}
  */
-export function fetchUserAdd() {
+export function fetchUserAdd(data) {
   return request({
     url: '/v1/user/user-add',
     method: 'get',
+    params: data
   })
 }
 

+ 1 - 0
src/api/shop.js

@@ -208,3 +208,4 @@ export function orderDetail(query) {
 
 
 
+

+ 25 - 0
src/api/site.js

@@ -34,3 +34,28 @@ export function getBaseInfo() {
     method: 'get'
   })
 }
+
+/**
+ * 国家
+ * @returns {*}
+ */
+export function getCountries() {
+  return request({
+    url: '/v1/site/countries',
+    method: 'get'
+  })
+}
+
+export function getLanguages() {
+  return request({
+    url: '/v1/site/languages',
+    method: 'get'
+  })
+}
+export function getBank(query) {
+  return request({
+    url: '/v1/site/banks',
+    method: 'get',
+    params: query
+  })
+}

+ 2 - 2
src/components/TreeChart/index.vue

@@ -139,7 +139,7 @@ export default {
               "</div>" +
               "<div>" +
               '<span style="color: #606266;">' +
-              that.$t("atlas.periodNumber") +
+              that.$t("bonus.periodNum") +
               ": " +
               "</span>" +
               '<span style="color: #000000;">' +
@@ -189,7 +189,7 @@ export default {
               "</div>" +
               "<div>" +
               '<span style="color: #606266;">' +
-              that.$t("atlas.periodNumber") +
+              that.$t("bonus.periodNum") +
               ": " +
               "</span>" +
               '<span style="color: #000000;">' +

+ 60 - 8
src/components/Upload/index.vue

@@ -12,15 +12,16 @@
       :before-upload="uploaderHandleBefore"
       :on-success="uploaderHandleSuccess"
       :disabled="uploaderDisabled"
-      :style="isImgUpload ? `width:${width};height:${height};` : ''"
+      :style="isImgUpload ? `width:${width};min-height:${height};` : ''"
     >
       <template v-if="isImgUpload">
-        <img
+        <el-image
           v-if="uploaderImageUrl"
           :src="uploaderImageUrl"
           class="image-preview"
-          :style="`width:${width};height:${height};display: block;`"
-        >
+          fit="contain"
+          :style="`width:${width};min-height:${height};display: block;`"
+        ></el-image>
         <i
           v-else
           class="el-icon-plus uploader-icon"
@@ -33,9 +34,18 @@
     </el-upload>
     <template v-if="isImgUpload">
       <div v-show="!uploaderShow" class="image-show">
-        <img :src="uploaderImageUrl" alt="" :width="width" :height="height">
+        <el-image :src="uploaderImageUrl" alt="" :width="width" :height="height"></el-image>
       </div>
     </template>
+
+    <div class="previewImg">
+      <el-button v-show="uploaderImageUrl" type="info" class="previewImgButton"  @click="previewImg">{{ $t('shop.imagePreview') }}</el-button>
+    </div>
+    <el-dialog append-to-body top="5vh" :visible.sync="dialogVisible" custom-class="custom-dialog">
+      <div class="previewImage">
+        <el-image width="60%" :src="uploaderImageUrl"  alt=""></el-image>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -70,7 +80,7 @@ export default {
     },
     height: {
       type: String,
-      default: '100px'
+      default: '100%'
     }
   },
   data() {
@@ -88,7 +98,9 @@ export default {
       },
       uploaderDisabled: false,
       successImageUrl: null,
-      uploaderImage: null
+      uploaderImage: null,
+      dialogVisible: false,
+      uploadedImages: []
     }
   },
   computed: {
@@ -96,7 +108,6 @@ export default {
       if (this.uploaderImage != null) {
         return this.uploaderImage
       }
-      console.log(this.defaultImageUrl)
       if (this.successImageUrl !== null) {
         return this.successImageUrl
       } else if (this.defaultImageUrl !== null) {
@@ -120,6 +131,10 @@ export default {
     console.log(this.uploaderImage)
   },
   methods: {
+    previewImg(){
+      this.dialogVisible = true;
+    },
+
     uploaderHandleBefore() {
       const auth_token = localStorage.accessToken
       this.uploaderHeaders.Authorization = 'Bearer  ' + auth_token
@@ -164,6 +179,7 @@ export default {
   width: 100%;
   height: 100%;
   position: relative;
+  margin-bottom: 50px;
   .image-uploader {
     height: 100%;
   }
@@ -210,4 +226,40 @@ export default {
     }
   }
 }
+.previewImage{
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.previewImg{
+  display: flex;
+  justify-content: center;
+  .previewImgButton{
+    position: absolute;
+    bottom: -50px;
+  }
+}
+.custom-dialog {
+  //background: rgba(0, 0, 0, 0); /* 半透明的背景 */
+  background-color: transparent!important;
+}
+
+.custom-dialog {
+  background-color: transparent; /* 使对话框的背景透明 */
+  box-shadow: none; /* 移除阴影 */
+}
+
+.custom-dialog .el-dialog__header,
+.custom-dialog .el-dialog__body,
+.custom-dialog .el-dialog__footer {
+  background-color: transparent; /* 透明的头部、内容和底部 */
+}
+
+.custom-dialog .el-dialog__header {
+  border-bottom: none; /* 移除对话框头部的边框 */
+}
+
+.custom-dialog .el-dialog__footer {
+  border-top: none; /* 移除底部的边框 */
+}
 </style>

+ 30 - 6
src/lang/en.js

@@ -401,7 +401,9 @@ export default {
     hideSelectedData: 'Are you sure to hide the selected data?',
     unHideSelectedData: 'Are you sure to un-hide the selected data?',
     exportCurrentData: 'Are you sure you want to export the current data?',
-    all: 'All'
+    all: 'All',
+    countryName: 'Country Name',
+    language: "Language"
   },
 
   filter: {
@@ -477,7 +479,9 @@ export default {
     memberHighestEmpLevelAdjustment:'Highest Director Level Adjust',
     // Second level menu/interface-networkChart
     placementNetwork: 'Placement Network',
+    placementNetworkEx: 'Placement Network Ex',
     sponsorNetwork: 'Sponsor Network',
+    sponsorNetworkEx: 'Sponsor Network Ex',
     // Second level menu/interface-bonusManagement
     closurePeriod: 'Closure Period',
     memberBonusBalance: 'Member Bonus Balance',
@@ -518,7 +522,8 @@ export default {
     otherConfig: 'Other configuration',
     decLevelConfig: 'Member level configuration',
     empLevelConfig: 'Member rank level configuration',
-    decRoleConfig: 'Stockist level configuration'
+    decRoleConfig: 'Stockist level configuration',
+    transportationConfig: "Transportation Config",
   },
 
   // Member
@@ -636,7 +641,8 @@ export default {
     byPlacementNetwork: 'By placement network',
     byMembershipSystem: 'By membership system',
     byProvinceAndRegion: 'By province and region',
-    exportDataHint: 'Are you sure you want to export the current data?'
+    exportDataHint: 'Are you sure you want to export the current data?',
+    modifyCountry: "Whether to change the country?"
   },
 
   // Network
@@ -695,7 +701,10 @@ export default {
     memberAbout: 'Member related',
     homeAbout: 'Member management related',
     withdrawalAbout: 'Withdrawal related',
-    otherAbout: 'Others'
+    otherAbout: 'Others',
+    modifyShippingRates: 'Edit shipping rates',
+    modifyExchangeRate: 'Edit Exchange Rate',
+    refreshProductPricePrompt: 'After opening, the prices of listed products will be refreshed according to the new product exchange rate'
   },
 
   // Financial Management
@@ -817,9 +826,11 @@ export default {
     productCode: 'Product Code',
     unit: 'Unit',
     taxRate: 'Tax Rate',
+    enterTaxRate: 'Tax rate is required',
     uSPrice: 'US Price($)',
-    salesPrice: 'Sales Price(₦)',
-    marketPrice: 'Market Price(₦)',
+    standardPrice: "Standard price($)",
+    salesPrice: 'DP',
+    marketPrice: 'RP',
     priceBV: 'Price BV',
     inventory: 'Inventory',
     productDetails: 'Product details',
@@ -845,6 +856,9 @@ export default {
     pleaseSelectPcNo: 'Please select Period No.',
     modifyOrderPcNoHits: 'Do you want to modify the order period No.?',
     consignee: 'consignee',
+    availableCountries: "Available countries",
+    modifyAvailableCountries: "Modify available countries",
+    imagePreview: 'Image Preview'
   },
 
   // Administrator management
@@ -876,4 +890,14 @@ export default {
     addAdmin: 'Add administrator',
     delNotice: 'Determine to delete the selected data'
   },
+  exchangeRateConfig: {
+    currencyType: "Currency Type",
+    ProductExchangeRate: 'Product Exchange Rate',
+    BonusExchangeRate: "Bonus Exchange Rate"
+  },
+  transportationConfig: {
+    countryName: "Country",
+    free: 'Free',
+    freeShipping: "Free shipping threshold"
+  },
 }

+ 36 - 14
src/lang/zh.js

@@ -79,10 +79,10 @@ export default {
     financeRecharge:'充值管理',
     rechargeStateManagement:'状态管理',
     financeWithdraw:'提现管理',
-    atlasRelationOpt:'开拓网络',
+    atlasRelationOpt:'推荐网络',
     atlasNetworkOpt:'安置网络',
-    sponsorNetworkEx:'安置网络 Ex',
-    placementNetworkEx:'开拓网络 Ex',
+    sponsorNetworkEx:'推荐网络 Ex',
+    placementNetworkEx:'安置网络 Ex',
     shopIndex:'商品列表',
     shopGoodsAdd:'商品添加',
     shopOrderDecList:'外部商城报单列表',
@@ -95,7 +95,7 @@ export default {
     modifyStockistLevel:'修改报单中心级别',
     metaPeriod:'封期管理',
     metaBalanceList:'会员账户余额',
-    metaOtherPeriodBonus:'往期奖金',
+    metaOtherPeriodBonus:'奖金列表',
     metaFlowBonus:'奖金流水',
     metaUserPerf:'用户业绩',
     metaPerfOrder:'业绩单',
@@ -401,7 +401,8 @@ export default {
     hideSelectedData: '您确定要隐藏所选数据吗?',
     unHideSelectedData: '您确定要展示所选数据吗?',
     exportCurrentData: '您确定要导出当前数据吗?',
-    all: '全部'
+    all: '全部',
+    language: "语言"
   },
 
   filter: {
@@ -477,14 +478,14 @@ export default {
     modifyStockistLevel: '修改报单中心级别',
     memberHighestEmpLevelAdjustment:'调整最高总监级别',
     // 二级菜单/接口-networkChart
+    sponsorNetwork: '推荐网络',
+    sponsorNetworkEx: '推荐网络 Ex',
     placementNetwork: '安置网络',
-    sponsorNetwork: '推荐网路',
-    placementNetworkEx: '推荐网络 Ex',
-    sponsorNetworkEx: '安置网路 Ex',
+    placementNetworkEx: '安置网络 Ex',
     // 二级菜单/接口-bonusManagement
     closurePeriod: '封期管理',
     memberBonusBalance: '会员账户余额',
-    memberBonus: '往期奖金',
+    memberBonus: '奖金列表',
     bonusFlow: '奖金流水',
     memberPerformance: '用户业绩',
     salesRecord: '业绩单',
@@ -521,7 +522,8 @@ export default {
     otherConfig: '其他配置',
     decLevelConfig: '会员级别配置',
     empLevelConfig: '会员聘级配置',
-    decRoleConfig: '报单中心级别配置'
+    decRoleConfig: '报单中心级别配置',
+    transportationConfig: "运费配置",
   },
 
   // 会员
@@ -631,7 +633,9 @@ export default {
     paymentPassword: '支付密码',
     selectMemberData: '请勾选要操作的会员',
     sureWant: '确定要对所选会员',
-    exportDataHint: '确定要导出所选数据?'
+    exportDataHint: '确定要导出所选数据?',
+    modifyCountry: "是否修改国家?"
+
   },
 
   // 网络
@@ -688,7 +692,10 @@ export default {
     memberAbout: '会员相关',
     homeAbout: '前台相关',
     withdrawalAbout: '提现相关',
-    otherAbout: '其他'
+    otherAbout: '其他',
+    modifyShippingRates: '编辑运费',
+    modifyExchangeRate: '编辑汇率',
+    refreshProductPricePrompt: '开启后根据新产品汇率刷新上架商品价格'
   },
 
   // 财务
@@ -810,9 +817,11 @@ export default {
     productCode: '商品编号',
     unit: '单位',
     taxRate: '税率',
+    enterTaxRate: '税率必填',
     uSPrice: '美元价格($)',
-    salesPrice: '销售价格(₦)',
-    marketPrice: '市场价格(₦)',
+    standardPrice: "标准价格($)",
+    salesPrice: 'DP',
+    marketPrice: 'RP',
     priceBV: '价格BV',
     inventory: '库存',
     productDetails: '商品详情',
@@ -837,6 +846,9 @@ export default {
     afterAdjustmentPcNo: '调整后期数',
     pleaseSelectPcNo: '请选择要调整到的期数',
     modifyOrderPcNoHits: '是否要修改当前订单期数?',
+    availableCountries: "可购买国家",
+    modifyAvailableCountries: "修改可购买国家",
+    imagePreview: '图片预览'
   },
 
   // 管理员管理
@@ -868,4 +880,14 @@ export default {
     addAdmin: '添加管理员',
     delNotice: '确定删除选定的数据?'
   },
+  exchangeRateConfig: {
+    currencyType: "货币类型",
+    ProductExchangeRate: '产品汇率',
+    BonusExchangeRate: "奖金汇率"
+  },
+  transportationConfig: {
+    countryName: "国家",
+    free: '运费',
+    freeShipping: "免运费阈值"
+  },
 }

+ 11 - 7
src/router/index.js

@@ -9,7 +9,8 @@ import Layout from '@/layout'
 /* Router Modules */
 import configRouter from '@/router/modules/config'
 import memberRouter from '@/router/modules/member'
-
+import currencyRouter from "@/router/modules/currency"
+import transportationRouter from "@/router/modules/transportation"
 /**
  * Note: sub-menu only appear when route children.length >= 1
  * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
@@ -169,13 +170,13 @@ export const constantRoutes = [
         path: '/atlas/relation-list', // 开拓网络Ex
         component: () => import('@/views/atlas/relation-ex'),
         name: 'atlas_relation-ex',
-        meta: {title: 'placementNetworkEx',},
+        meta: {title: 'sponsorNetworkEx',},
       },
       {
         path: '/atlas/network-list', // 安置网络Ex
         component: () => import('@/views/atlas/network-ex'),
         name: 'atlas_network-ex',
-        meta: {title: 'sponsorNetworkEx',},
+        meta: {title: 'placementNetworkEx',},
       },
     ]
   },
@@ -295,11 +296,14 @@ export const constantRoutes = [
  */
 export const asyncRoutes = [
   /** when your routing map is too long, you can split it into small modules **/
-  // 会员
-  memberRouter,
-  // 设置
-  configRouter,
+    // 会员
+    memberRouter,
+    // 设置
+    configRouter,
+
+    currencyRouter,
 
+    transportationRouter,
   {
     path: '/ad',
     component: Layout,

+ 2 - 2
src/router/modules/config.js

@@ -15,10 +15,10 @@ const configRouter = {
       meta: { title: '站点配置', icon: 'user', noCache: true }
     },
     {
-      path: 'exchange-rate', // 汇率配置
+      path: 'currency-conversions', // 汇率配置
       component: () => import('@/views/config/exchange-rate'),
       name: 'exchangeRate',
-      meta: { title: '汇率配置', icon: 'user', noCache: true }
+      meta: { title: '汇率列表', icon: 'user', noCache: true }
     },
     {
       path: 'dec-role', // 报单中心配置

+ 20 - 0
src/router/modules/currency.js

@@ -0,0 +1,20 @@
+/** When your routing table is too long, you can split it into small modules **/
+
+import Layout from '@/layout'
+
+const currencyRouter = {
+  path: '/currency',
+  component: Layout,
+  redirect: '/currency/currencies-conversions',
+  hidden: true,
+  children: [
+    {
+      path: 'currencies-conversions', // 汇率配置
+      component: () => import('@/views/config/exchange-rate'),
+      name: 'exchangeRate',
+      meta: { title: '汇率列表', icon: 'user', noCache: true }
+    }
+  ]
+}
+
+export default currencyRouter

+ 21 - 0
src/router/modules/transportation.js

@@ -0,0 +1,21 @@
+/** When your routing table is too long, you can split it into small modules **/
+
+import Layout from '@/layout'
+
+const transportationRouter = {
+  path: '/transportation',
+  component: Layout,
+  redirect: '/transportation/transportation',
+  hidden: true,
+  children: [
+    {
+      path: 'transportation',
+      component: () => import('@/views/config/transportation-config'),
+      name: 'transportation',
+      meta: { title: '运费配置', icon: 'user', noCache: true }
+    },
+
+  ]
+}
+
+export default transportationRouter

+ 23 - 0
src/styles/element-ui.scss

@@ -82,3 +82,26 @@
 .el-range-separator {
   box-sizing: content-box;
 }
+input[type=number] {
+  -moz-appearance:textfield;
+}
+input[type=number]::-webkit-inner-spin-button,
+input[type=number]::-webkit-outer-spin-button {
+  -webkit-appearance: none;
+  margin: 0;
+}
+.el-input-number .el-input__suffix .el-input-number__decrease,
+.el-input-number .el-input__suffix .el-input-number__increase {
+  display: none;
+}
+.flexJfAc{
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+
+}
+.el-form-item__label{
+  word-wrap:break-word;
+  word-break: break-word;
+  overflow-wrap: break-word;
+}

+ 6 - 0
src/styles/index.scss

@@ -189,3 +189,9 @@ aside {
 .multiselect--active {
   z-index: 1000 !important;
 }
+
+.break-word{
+  word-wrap:break-word;
+  word-break: break-word;
+  overflow-wrap: break-word;
+}

+ 54 - 54
src/views/atlas/relation-ex.vue

@@ -35,67 +35,67 @@
               <tree-chart :tree-data="treeData" :top-deep="topDeep" type="relation" @clickNode="getNodeData" :clickNodeList="clickNodeList" />
             </div>
           </el-tab-pane>
-          <el-tab-pane :label="$t('atlas.sponsorNetworkList')" name="two" v-if="permission.hasPermission(`atlas/relation-list`)"><!-- 开拓网络列表 -->
-            <div class="filter-user">
-              <el-input v-model="filterForm.userName" size="small" style="width:300px;">
-                <template slot="prepend"><!-- 会员编号 -->{{ $t('atlas.memberCode') }}</template>
-              </el-input>
-              <el-input v-model="filterForm.deep" size="small" style="width:150px;">
-                <template slot="prepend"><!-- 深度 -->{{ $t('atlas.depth') }}</template>
-              </el-input>
-              <el-input v-model="filterForm.periodNum" size="small" style="width:150px;" v-show="false">
-                <template slot="prepend"><!-- 期数 -->{{ $t('atlas.numberOfPeriods') }}</template>
-              </el-input>
-              <el-button type="primary" size="small" @click="handleFilter">{{ $t('common.confirm') }}<!-- 确定 --></el-button>
-            </div>
+<!--          <el-tab-pane :label="$t('atlas.sponsorNetworkList')" name="two" v-if="permission.hasPermission(`atlas/relation-list`)">-->
+<!--            <div class="filter-user">-->
+<!--              <el-input v-model="filterForm.userName" size="small" style="width:300px;">-->
+<!--                <template slot="prepend">{{ $t('atlas.memberCode') }}</template>-->
+<!--              </el-input>-->
+<!--              <el-input v-model="filterForm.deep" size="small" style="width:150px;">-->
+<!--                <template slot="prepend">{{ $t('atlas.depth') }}</template>-->
+<!--              </el-input>-->
+<!--              <el-input v-model="filterForm.periodNum" size="small" style="width:150px;" v-show="false">-->
+<!--                <template slot="prepend">{{ $t('atlas.numberOfPeriods') }}</template>-->
+<!--              </el-input>-->
+<!--              <el-button type="primary" size="small" @click="handleFilter">{{ $t('common.confirm') }}</el-button>-->
+<!--            </div>-->
 
-            <el-table :data="tableData" stripe style="width: 100%;" :height="tool.getTableHeight(true)">
-              <!--<el-table-column type="selection" width="55" v-if="tableHeaders"></el-table-column>-->
-              <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''">
-                <template slot-scope="scope">
-                  <template v-if="scope.row[tableHeader.index].other.tag" >
-                    <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null" >{{scope.row[tableHeader.index].value}}</el-tag>
-                  </template>
-                  <template v-else-if="scope.row[tableHeader.index].other.progress" >
-                    <el-progress type="circle" :percentage="Number.parseInt(percentList['MOVE_PERCENT'][scope.row.ID])"
-                                 :width="50"
-                                 :stroke-width="3"></el-progress>
-                  </template>
-                  <template v-else>
-                    <template v-if="tableHeader.index === 'USER_NAME'">
-                      <el-tooltip class="item" effect="dark" :content="$t('atlas.subordinatesMember')" placement="top"><!-- 查看该会员的下级 -->
-                        <el-button @click.native="handleShow(scope.row)" size="small" type="primary">
-                          {{scope.row[tableHeader.index].value}}
-                        </el-button>
-                      </el-tooltip>
-                    </template>
-                    <template v-else>
-                      <div v-html="scope.row[tableHeader.index].value"></div>
-                    </template>
-                  </template>
-                </template>
-              </el-table-column>
-            </el-table>
-            <div class="white-box-footer">
-              <el-button type="success" size="small" @click="handleExport"
-                         v-show="permission.hasPermission(`atlas/relation-list-export`)">{{ $t('common.exportExcel') }}<!-- 导出Excel -->
-              </el-button>
-              <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange"></pagination>
-            </div>
-          </el-tab-pane>
+<!--            <el-table :data="tableData" stripe style="width: 100%;" :height="tool.getTableHeight(true)">-->
+<!--              &lt;!&ndash;<el-table-column type="selection" width="55" v-if="tableHeaders"></el-table-column>&ndash;&gt;-->
+<!--              <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''">-->
+<!--                <template slot-scope="scope">-->
+<!--                  <template v-if="scope.row[tableHeader.index].other.tag" >-->
+<!--                    <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null" >{{scope.row[tableHeader.index].value}}</el-tag>-->
+<!--                  </template>-->
+<!--                  <template v-else-if="scope.row[tableHeader.index].other.progress" >-->
+<!--                    <el-progress type="circle" :percentage="Number.parseInt(percentList['MOVE_PERCENT'][scope.row.ID])"-->
+<!--                                 :width="50"-->
+<!--                                 :stroke-width="3"></el-progress>-->
+<!--                  </template>-->
+<!--                  <template v-else>-->
+<!--                    <template v-if="tableHeader.index === 'USER_NAME'">-->
+<!--                      <el-tooltip class="item" effect="dark" :content="$t('atlas.subordinatesMember')" placement="top">-->
+<!--                        <el-button @click.native="handleShow(scope.row)" size="small" type="primary">-->
+<!--                          {{scope.row[tableHeader.index].value}}-->
+<!--                        </el-button>-->
+<!--                      </el-tooltip>-->
+<!--                    </template>-->
+<!--                    <template v-else>-->
+<!--                      <div v-html="scope.row[tableHeader.index].value"></div>-->
+<!--                    </template>-->
+<!--                  </template>-->
+<!--                </template>-->
+<!--              </el-table-column>-->
+<!--            </el-table>-->
+<!--            <div class="white-box-footer">-->
+<!--              <el-button type="success" size="small" @click="handleExport"-->
+<!--                         v-show="permission.hasPermission(`atlas/relation-list-export`)">{{ $t('common.exportExcel') }}&lt;!&ndash; 导出Excel &ndash;&gt;-->
+<!--              </el-button>-->
+<!--              <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange"></pagination>-->
+<!--            </div>-->
+<!--          </el-tab-pane>-->
         </el-tabs>
       </div>
     </div>
   </template>
 
   <script>
-    import { getRelation, mainUserInfo, relationList, relationListExport } from '@/api/atlas'
-import Pagination from '@/components/Pagination'
-import treeChart from '@/components/TreeChart/index.vue'
-import baseInfo from '@/utils/baseInfo'
-import permission from '@/utils/permission'
-import tool from '@/utils/tool'
-import store from '@/utils/vuexStore'
+  import { getRelation, mainUserInfo, relationList, relationListExport } from '@/api/atlas'
+  import Pagination from '@/components/Pagination'
+  import treeChart from '@/components/TreeChart/index.vue'
+  import baseInfo from '@/utils/baseInfo'
+  import permission from '@/utils/permission'
+  import tool from '@/utils/tool'
+  import store from '@/utils/vuexStore'
 
     export default {
       name: 'atlas_relation-ex',

+ 97 - 20
src/views/config/exchange-rate.vue

@@ -1,31 +1,63 @@
 <template>
   <div class="app-container">
     <div v-loading="loading" class="white-box">
-      <el-form ref="form" :model="form" label-width="250px" :label-position="labelPosition" class="form-page">
-        <el-form-item :key="form.CONFIG_NAME" :label="form.TITLE">
-          <el-input v-model="form.VALUE" style="max-width: 300px;">
-            <template slot="append">naira / $</template>
-          </el-input>
-        </el-form-item>
-        <el-form-item :label="$t('config.refreshShopPrice')">
-          <el-switch v-model="synchronize" />
-          <el-divider direction="vertical" />
-          <span style="font-weight: bold; color: red; font-size: 14px;">{{ $t('config.refreshShopNaraPriceThenSave') }}</span>
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" size="medium" :loading="submitButtonStat" @click="onSubmit">{{ $t('common.confirm') }}</el-button>
+      <el-table :data="conversionsList" stripe style="width: 100%;">
+        <el-table-column prop="NAME" :label="$t('exchangeRateConfig.currencyType')" />
+        <el-table-column prop="PRODUCT_RATE" :label="$t('exchangeRateConfig.ProductExchangeRate')" min-width="90px;" />
+        <el-table-column prop="BONUSES_RATE" :label="$t('exchangeRateConfig.BonusExchangeRate')" min-width="90px;" />
+<!--        <el-table-column :label="$t('common.createdAt')" min-width="100px;">-->
+<!--          <template slot-scope="{row}">-->
+<!--            {{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}-->
+<!--          </template>-->
+<!--        </el-table-column>-->
+<!--        <el-table-column :label="$t('common.updatedAt')" min-width="100px;">-->
+<!--          <template slot-scope="{row}">-->
+<!--            {{ row.UPDATED_AT | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}-->
+<!--          </template>-->
+<!--        </el-table-column>-->
+        <el-table-column :label="$t('common.action')" min-width="100px;">
+          <template slot-scope="scope">
+            <el-button type="primary" size="mini" icon="el-icon-edit" plain @click="edit(scope.row)">{{ $t('common.edit') }}</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 编辑	-->
+    <el-dialog v-loading="editLoading" :title="$t('config.modifyExchangeRate')" :visible.sync="dialog" :width="screenWidth" style="margin-top: -80px">
+      <el-form ref="editForm" :model="editForm" :label-position="labelPosition" label-width="130px" style="width: 100%; margin-top: -30px; margin-bottom: -15px;">
+        <el-row :gutter="3">
+          <el-col :xs="24" :sm="24" :lg="12">
+            <el-input v-show="false" v-model="editForm.ID" size="small" type="text" />
+            <el-form-item :label="$t('exchangeRateConfig.ProductExchangeRate')" prop="Product_Exchange_Rate" style="margin-bottom: 10px; width: 100%;">
+              <el-input-number v-model.trim="editForm.product_rate" :precision="6" :min="0" size="small" type="text" style="min-width: 300px;" readonly />
+            </el-form-item>
+            <el-form-item :label="$t('exchangeRateConfig.BonusExchangeRate')" prop="Bonus_Exchange_Rate" style="margin-bottom: 10px; width: 100%;">
+              <el-input-number v-model="editForm.bonuses_rate" :precision="6" :min="0" size="small" type="text" style="min-width: 300px;" />
+            </el-form-item>
+            <el-form-item :label="$t('config.refreshShopPrice')" style="min-width: 420px;" >
+              <el-switch v-model="editForm.synchronize" /> <div class="synchronize break-word">( {{$t('config.refreshProductPricePrompt')}} )</div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item style="margin-bottom: 15px;">
+          <el-button type="warning" size="mini" @click="dialog = false">{{ $t('table.cancel') }}</el-button>
+          <el-button type="primary" size="mini" @click="editSubmit">{{ $t('table.confirm') }}</el-button>
         </el-form-item>
       </el-form>
-    </div>
+    </el-dialog>
+
   </div>
 </template>
 
 <script>
-import { fetchExchangeRateConfig, updateExchangeRateConfig } from '@/api/config'
+import {
+  fetchCurrencyConversionsList, setCurrencyConversions, fetchCurrenciesList
+} from '@/api/config'
 import { getScreenWidth } from '@/utils'
 
 export default {
-  name: 'ExchangeRate',
+  name: 'Currencies',
   data() {
     return {
       form: {
@@ -37,7 +69,18 @@ export default {
       submitButtonStat: false,
       synchronize: false,
       screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
-      labelPosition: getScreenWidth() > 600 ? 'right' : 'top'
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+      conversionsList: [],
+      editLoading: false,
+      editForm: {
+        from_currency_id: '149',
+        to_currency_id: '',
+        product_rate: '',
+        bonuses_rate: '',
+        synchronize: false,
+      },
+      dialog: false,
+
     }
   },
   created() {
@@ -46,14 +89,38 @@ export default {
   methods: {
     fetchData() {
       this.loading = true
-      fetchExchangeRateConfig().then(response => {
-        this.form = response.data
-
+      fetchCurrencyConversionsList().then(response => {
+        this.conversionsList = response
         setTimeout(() => {
           this.loading = false
         }, 0.5 * 1000)
       })
     },
+    edit(data){
+      this.editForm = {
+            from_currency_id: '149',
+            to_currency_id: data.ID,
+            product_rate: data.PRODUCT_RATE,
+            bonuses_rate: data.BONUSES_RATE,
+            synchronize: false,
+      }
+      this.dialog = true
+    },
+    editSubmit(){
+      setCurrencyConversions(this.editForm).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+        this.dialog = false
+        this.fetchData()
+      }).catch(error => {
+        this.$message({
+          message: error,
+          type: 'warning'
+        })
+      })
+    },
     onSubmit() {
       this.$confirm(this.$t('config.confirmToChangeExchangeRate'), this.$t('common.hint'), {
         confirmButtonText: this.$t('common.confirm'),
@@ -105,4 +172,14 @@ export default {
 .form-page {
 	width: 100%;
 }
+.synchronize{
+  color: #F56C6C;
+}
+
+::v-deep .el-form-item__label{
+  word-wrap:break-word;
+  word-break: break-word;
+  overflow-wrap: break-word;
+}
+
 </style>

+ 6 - 6
src/views/config/transfer-config.vue

@@ -15,14 +15,14 @@
           <el-table-column :label="$t('config.lowerLimitAmountTransferOut')" min-width="150px">
             <template slot-scope="scope">
               <el-input v-model="scope.row.outMin" size="small" maxlength="16">
-                <template slot="append">₦</template>
+
               </el-input>
             </template>
           </el-table-column>
           <el-table-column :label="$t('config.upperLimitAmountTransferOut')" min-width="150px">
             <template slot-scope="scope">
               <el-input v-model="scope.row.outMax" size="small" maxlength="16">
-                <template slot="append">₦</template>
+
               </el-input>
             </template>
           </el-table-column>
@@ -34,28 +34,28 @@
           <el-table-column :label="$t('config.lowerLimitServiceCharge')" min-width="150px">
             <template slot-scope="scope">
               <el-input v-model="scope.row.feeMin" size="small" maxlength="16">
-                <template slot="append">₦</template>
+
               </el-input>
             </template>
           </el-table-column>
           <el-table-column :label="$t('config.upperLimitServiceCharge')" min-width="150px">
             <template slot-scope="scope">
               <el-input v-model="scope.row.feeMax" size="small" maxlength="16">
-                <template slot="append">₦</template>
+
               </el-input>
             </template>
           </el-table-column>
           <el-table-column :label="$t('config.periodUpperLimitAmountTransferOut')" min-width="150px">
             <template slot-scope="scope">
               <el-input v-model="scope.row.weekMax" size="small" maxlength="16">
-                <template slot="append">₦</template>
+
               </el-input>
             </template>
           </el-table-column>
           <el-table-column :label="$t('config.monthUpperLimitAmountTransferOut')" min-width="150px">
             <template slot-scope="scope">
               <el-input v-model="scope.row.monthMax" size="small" maxlength="16">
-                <template slot="append">₦</template>
+
               </el-input>
             </template>
           </el-table-column>

+ 138 - 0
src/views/config/transportation-config.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="app-container">
+    <div v-loading="loading" class="white-box">
+      <el-table :data="conversionsList" stripe style="width: 100%;">
+        <el-table-column prop="NAME" :label="$t('transportationConfig.countryName')" />
+        <el-table-column prop="currency.NAME" :label="$t('exchangeRateConfig.currencyType')" />
+        <el-table-column prop="free_shipping" :label="$t('transportationConfig.freeShipping')" min-width="90px;" />
+        <el-table-column prop="freight" :label="$t('transportationConfig.free')" min-width="90px;" />
+<!--        <el-table-column :label="$t('common.createdAt')" min-width="100px;">-->
+<!--          <template slot-scope="{row}">-->
+<!--            {{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}-->
+<!--          </template>-->
+<!--        </el-table-column>-->
+<!--        <el-table-column :label="$t('common.updatedAt')" min-width="100px;">-->
+<!--          <template slot-scope="{row}">-->
+<!--            {{ row.UPDATED_AT | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}-->
+<!--          </template>-->
+<!--        </el-table-column>-->
+        <el-table-column :label="$t('common.action')" min-width="100px;">
+          <template slot-scope="scope">
+            <el-button type="primary" size="mini" icon="el-icon-edit" plain @click="edit(scope.row)">{{ $t('common.edit') }}</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 编辑	-->
+    <el-dialog v-loading="editLoading" :title="$t('config.modifyShippingRates')" :visible.sync="dialog" :width="screenWidth" style="margin-top: -80px">
+      <el-form ref="editForm" :model="editForm" :label-position="labelPosition" label-width="130px" style="width: 100%; margin-top: -30px; margin-bottom: -15px;">
+        <el-row :gutter="3">
+          <el-col :xs="24" :sm="24" :lg="12">
+            <el-input v-show="false" v-model="editForm.ID" size="small" type="text" />
+            <el-form-item :label="$t('transportationConfig.freeShipping')" prop="freeShipping" style="margin-bottom: 10px; width: 100%;">
+              <el-input-number v-model.trim="editForm.freeShipping" :precision="0" :controls="false" :min="0" size="small" style="min-width: 300px;" />
+            </el-form-item>
+            <el-form-item :label="$t('transportationConfig.free')" prop="free" style="margin-bottom: 10px; width: 100%;">
+              <el-input-number v-model.trim="editForm.freight" :precision="0" :controls="false" :min="0" size="small" style="min-width: 300px;" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item style="margin-bottom: 15px;">
+          <el-button type="warning" size="mini" @click="dialog = false">{{ $t('table.cancel') }}</el-button>
+          <el-button type="primary" size="mini" @click="editSubmit">{{ $t('table.confirm') }}</el-button>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import {
+  fetchTransportationList, setTransportation
+} from '@/api/config'
+import { getScreenWidth } from '@/utils'
+
+export default {
+  name: 'transportation',
+  data() {
+    return {
+      form: {
+        CONFIG_NAME: '',
+        VALUE: 0,
+        TITLE: ''
+      },
+      loading: true,
+      submitButtonStat: false,
+      synchronize: false,
+      screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+      conversionsList: [],
+      editLoading: false,
+      editForm: {
+        countryId: "",
+        freight: "",
+        freeShipping: "",
+      },
+      dialog: false,
+
+    }
+  },
+  created() {
+    this.fetchData()
+  },
+  methods: {
+    fetchData() {
+      this.loading = true
+      fetchTransportationList().then(response => {
+        this.conversionsList = response
+        setTimeout(() => {
+          this.loading = false
+        }, 0.5 * 1000)
+      })
+    },
+    edit(data){
+      this.editForm = {
+            countryId: data.ID,
+            freight: data.freight,
+            freeShipping: data.free_shipping,
+      }
+      this.dialog = true
+    },
+    editSubmit(){
+      setTransportation(this.editForm).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+        this.dialog = false
+        this.fetchData()
+      }).catch(error => {
+        this.$message({
+          message: error,
+          type: 'warning'
+        })
+      })
+    },
+  }
+}
+</script>
+
+<style scoped>
+.app-main {
+	padding: 15px;
+}
+.app-container {
+	padding: 0;
+}
+.white-box {
+	padding: 15px;
+}
+.form-page {
+	width: 100%;
+}
+::v-deep .el-input-number .el-input__inner {
+  text-align: left;
+}
+</style>

+ 428 - 32
src/views/shop/goods-add.vue

@@ -32,23 +32,26 @@
                 <el-form-item :label="$t('shop.unit')"><!-- 单位 -->
                     <el-input v-model="form.unit"></el-input>
                 </el-form-item>
-                <el-form-item :label="$t('shop.taxRate')"><!-- 税率 -->
-                  <el-input v-model="form.taxRate">
-                    <template slot="append">%</template>
-                  </el-input>
-                </el-form-item>
-                <el-form-item :label="$t('shop.uSPrice')" p>
-                    <el-input v-model="form.sellPriceStandard"></el-input>
-                </el-form-item>
-                <el-form-item :label="$t('shop.salesPrice')">
-                    <el-input v-model="form.sellPrice"></el-input>
-                </el-form-item>
-                <el-form-item :label="$t('shop.marketPrice')">
-                  <el-input v-model="form.marketPrice"></el-input>
+<!--                <el-form-item :label="$t('shop.taxRate')">&lt;!&ndash; 税率 &ndash;&gt;-->
+<!--                  <el-input v-model="form.taxRate">-->
+<!--                    <template slot="append">%</template>-->
+<!--                  </el-input>-->
+<!--                </el-form-item>-->
+                <el-form-item :label="$t('shop.standardPrice')">
+                    <el-input-number v-model="form.sellPriceStandard" @input="handleInput" class="left-aligned-input" :precision="2" :step="0.1" :min="0" :controls="false" style="text-align: left"></el-input-number>
                 </el-form-item>
+<!--                <el-form-item :label="$t('shop.salesPrice')">-->
+<!--                    <el-input v-model="form.sellPrice"></el-input>-->
+<!--                </el-form-item>-->
+<!--                <el-form-item :label="$t('shop.marketPrice')">-->
+<!--                  <el-input v-model="form.marketPrice"></el-input>-->
+<!--                </el-form-item>-->
                 <el-form-item :label="$t('shop.priceBV')" v-show="pvDisabled"><!-- 价格BV -->
                     <el-input v-model="form.pricePv"></el-input>
                 </el-form-item>
+                <el-form-item :label="$t('shop.availableCountries')"><!-- 可购买国家 -->
+                  <el-button type="primary" size="small" :disabled="!form.sellPriceStandard" @click="editAvailableCountries">{{ $t('shop.modifyAvailableCountries') }}</el-button>
+                </el-form-item>
                 <el-form-item :label="$t('shop.inventory')"><!-- 库存 -->
                     <el-input v-model="form.storeNums"></el-input>
                 </el-form-item>
@@ -82,11 +85,105 @@
                 </el-form-item>
             </el-form>
         </div>
+      <el-dialog :title="$t('shop.modifyAvailableCountries')" :visible.sync="editAvailableCountriesDialog" top="3%" width="60%"><!-- 修改可购买国家 -->
+        <el-form ref="form"  label-width="130px" class="">
+          <el-form-item :label="$t('shop.productName')"><!-- 商品名称 -->
+            <el-input v-model="form.goodsName" disabled></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('transportationConfig.countryName')">
+            <el-input
+              v-model="searchQuery"
+              placeholder=""
+              @input="updateTableData"
+            ></el-input>
+          </el-form-item>
+        </el-form>
+
+        <el-form :model="availableCountriesTableForm" ref="availableCountriesTableForm" :rules="rules">
+          <el-table v-show="!searchQuery" :data="availableCountriesTableForm.availableCountriesList" ref="multipleTable" @row-click="handleRowClick" @selection-change="handleSelectionChange" @select="selectOne" :selectable="isRowSelectable" :header-cell-class-name="cellClass" stripe height="500" style="width: 100%;">
+            <el-table-column
+                type="selection"
+                width="55"
+                :selectable="selectable"
+                :show-select-all="false"
+            >
+            </el-table-column>
+            <el-table-column prop="NAME" :label="$t('transportationConfig.countryName')" />
+            <el-table-column prop="LOCAL_CURRENCY_NAME" :label="$t('exchangeRateConfig.currencyType')" />
+            <el-table-column :label="$t('shop.salesPrice')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`availableCountriesList.${scope.$index}.sellPrice`" >
+                  <el-input-number v-model="scope.row.sellPrice" :controls="false" disabled></el-input-number>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column :label="$t('shop.marketPrice')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`availableCountriesList.${scope.$index}.marketPrice`">
+                  <el-input-number v-model="scope.row.marketPrice" :precision="2" :min="0" :controls="false" clearable></el-input-number>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column :label="$t('shop.taxRate')" min-width="100px;">
+              <template slot-scope="scope">
+                  <el-form-item :prop="`availableCountriesList.${scope.$index}.taxRate`" >
+                    <div class="flexJfAc">
+                      <el-input-number v-model="scope.row.taxRate" :precision="2" :step="0.1" :min="0" :controls="false"></el-input-number><span>%</span>
+                    </div>
+                  </el-form-item>
+              </template>
+            </el-table-column>
+          </el-table>
+
+          <el-table v-show="searchQuery" :data="availableCountriesTableForm.tempData" ref="multipleTableTemp" @row-click="handleRowClickTemp" @selection-change="handleSelectionChangeTemp" @select="selectOneTemp" :selectable="isRowSelectable" :header-cell-class-name="cellClass" stripe height="500" style="width: 100%;">
+            <el-table-column
+                type="selection"
+                width="55"
+                :selectable="selectable"
+                :show-select-all="false"
+            >
+            </el-table-column>
+            <el-table-column prop="NAME" :label="$t('transportationConfig.countryName')" />
+            <el-table-column prop="LOCAL_CURRENCY_NAME" :label="$t('exchangeRateConfig.currencyType')" />
+            <el-table-column :label="$t('shop.salesPrice')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`tempData.${scope.$index}.sellPrice`" >
+                  <el-input-number v-model="scope.row.sellPrice" :controls="false" disabled></el-input-number>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column :label="$t('shop.marketPrice')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`tempData.${scope.$index}.marketPrice`">
+                  <el-input-number v-model="scope.row.marketPrice" :precision="2" :min="0" :controls="false" clearable></el-input-number>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column :label="$t('shop.taxRate')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`tempData.${scope.$index}.taxRate`" >
+                  <div class="flexJfAc">
+                    <el-input-number v-model="scope.row.taxRate" :precision="2" :step="0.1" :min="0" :controls="false"></el-input-number><span>%</span>
+                  </div>
+                </el-form-item>
+              </template>
+            </el-table-column>
+          </el-table>
+
+        </el-form>
+
+        <div slot="footer" class="dialog-footer">
+          <el-button type="warning" size="mini" @click="editAvailableCountriesDialog = false">{{ $t('table.cancel') }}</el-button>
+          <el-button type="primary" size="mini" @click="submitAvailableCountries">{{ $t('table.confirm') }}</el-button>
+        </div>
+
+      </el-dialog>
     </div>
 </template>
 
 <script>
 import { addGoods, getAddGoodsConfig, getUploadToken } from '@/api/shop'
+import { getCountries } from "@/api/site"
 import Upload from '@/components/Upload'
 import baseInfo from '@/utils/baseInfo'
 
@@ -134,8 +231,9 @@ export default {
         textarea: '',
         sellDiscount: '',
         categoryType: '',
-        sellPriceStandard: '',
-        taxRate: 0
+        sellPriceStandard: undefined,
+        taxRate: 0,
+        nature: []
       },
       submitButtonStat: false,
       goodsType: [],
@@ -145,7 +243,22 @@ export default {
       width: '100px',
       height: '100px',
       pvDisabled: true,
-      exchangeRate: baseInfo.exchangeRate()
+      exchangeRate: baseInfo.exchangeRate(),
+      editAvailableCountriesDialog: false,
+      availableCountriesTableForm: {
+        availableCountriesList: [],
+        tempData:[],
+      },
+      multipleSelection: [],
+      multipleSelectionTemp: [],
+
+      rules: {},
+      rulesTemp: {},
+      searchQuery: '',
+
+      selectionTempData: [],
+      selectedIds: [], // 存储选中的项的 ID
+      selectedIdsTemp: [],
     }
   },
   watch: {
@@ -158,16 +271,251 @@ export default {
       handler (modern, origin) {
         this.pvDisabled = (parseInt(modern) === 1)
       }
-    }
+    },
     // 监听商品标准价格,自动计算销售价格
-    // 'form.sellPriceStandard': {
-    //     deep: true,
-    //     handler(modern, origin) {
-    //         this.form.sellPrice = modern * this.exchangeRate
-    //     }
-    // },
+    'form.sellPriceStandard': {
+        deep: true,
+        handler(modern, origin) {
+            // this.form.sellPrice = modern * this.exchangeRate
+          if(modern){
+            this.form.nature = []
+            this.availableCountriesTableForm.availableCountriesList = []
+            this.toggleSelection(this.form.nature)
+          }
+        }
+    },
+  },
+  computed: {
+    filteredData() {
+      if (!this.searchQuery) {
+        return this.availableCountriesTableForm.availableCountriesList;
+      }
+      const query = this.searchQuery.toLowerCase();
+      // this.$refs.multipleTable.toggleRowSelection(JSON.parse(JSON.stringify(this.multipleSelection)),true)
+      return this.availableCountriesTableForm.availableCountriesList.filter(row => {
+        return row.NAME.toLowerCase().includes(query);
+      });
+
+    }
   },
   methods: {
+    updateTableData() {
+      // if (!this.searchQuery) {
+      //   return this.availableCountriesTableForm.availableCountriesList;
+      // }
+      // 临时存储原始数据,保持搜索时不改变其他列的值
+      const query = this.searchQuery.toLowerCase();
+      // this.$refs.multipleTable.toggleRowSelection(JSON.parse(JSON.stringify(this.multipleSelection)),true)
+
+      if (this.availableCountriesTableForm.tempData.length === 0) {
+        // this.availableCountriesTableForm.tempData = JSON.parse(JSON.stringify(this.availableCountriesTableForm.availableCountriesList));
+        // this.selectionTempData = JSON.parse(JSON.stringify(this.multipleSelection));
+
+      }
+      // const query = this.searchQuery.toLowerCase();
+      this.$nextTick(() => {
+        // 在数据更新后,重新设置选中的项
+        if(!this.searchQuery){
+          this.setSelectionTemp();
+        } else {
+          this.availableCountriesTableForm.tempData = this.availableCountriesTableForm.availableCountriesList.filter(row => {
+            // const originalRow = this.availableCountriesTableForm.availableCountriesList.find(item => item.NAME === row.NAME);
+            // console.log(originalRow);
+            //
+            return row.NAME.toLowerCase().includes(query);
+          });
+          this.setSelection();
+
+        }
+      });
+      // this.availableCountriesTableForm.availableCountriesList.forEach(row => {
+      //   if (row.NAME.toLowerCase().includes(query)) {
+      //   } else {
+      //     const originalRow = this.filteredData.find(item => item.NAME === row.NAME);
+      //     if (originalRow) {
+      //       if(originalRow.selected === true){
+      //         console.log('originalRow true')
+      //       }
+      //       row = originalRow;
+      //
+      //     }
+      //   }
+      // });
+      // this.$refs.multipleTable.toggleRowSelection(this.selectionTempData)
+
+    },
+    setSelection() {
+      console.log(this.selectedIds)
+      console.log(this.availableCountriesTableForm.tempData)
+      this.availableCountriesTableForm.tempData.forEach(row => {
+        console.log('----1111')
+        console.log(this.selectedIds.includes(row.ID))
+        if (this.selectedIds.includes(row.ID)) {
+          console.log('----1111----------aaa')
+          console.log(row)
+          this.$nextTick(() => {
+            this.$refs.multipleTableTemp.toggleRowSelection(row, true);
+          });
+        }
+      });
+    },
+    setSelectionTemp() {
+      // this.$refs.multipleTable.clearSelection();
+      let selectedIds = JSON.parse(JSON.stringify(this.selectedIds))
+      let selectedIdsTemp = JSON.parse(JSON.stringify(this.selectedIdsTemp))
+
+      console.log('----2222')
+      let list = selectedIds.concat(selectedIdsTemp)
+      console.log("list=====+" + list)
+      this.availableCountriesTableForm.availableCountriesList.forEach(row => {
+        console.log('----3333')
+        if (list.includes(row.ID)) {
+          this.$refs.multipleTable.toggleRowSelection(row, true);
+        }
+      });
+    },
+    handleRowClick(row) {
+      console.log(row)
+
+      // 手动控制行点击时的选中状态
+      // this.$refs.multipleTable.toggleRowSelection(row,true);
+    },
+    handleRowClickTemp(row) {
+      console.log(row)
+      console.log('temp 选中')
+      // 手动控制行点击时的选中状态
+      // this.$refs.multipleTableTemp.toggleRowSelection(row,true);
+    },
+
+    handleInputBlur(row) {
+      // 当输入框失去焦点时,将修改应用到原始数据
+      let originalRow = this.availableCountriesTableForm.tempData.find(item => item.NAME === row.NAME);
+      if (originalRow) {
+        originalRow = row;
+      }
+    },
+      handleInput(value) {
+          // console.log(value)
+          // if (value < 0 || value === 0) {
+          //     this.form.sellPriceStandard = "";
+          // }
+      },
+    // 隐藏表头中的全选框
+    cellClass(row) {
+      if (row.columnIndex === 0) {
+        return 'disabledCheck'
+      }
+    },
+    isRowSelectable(row, index) {
+      return row.CURRENCY_PRODUCT_RATE == 0;
+    },
+    selectable(row, index) {
+      return row.CURRENCY_PRODUCT_RATE !== 0;
+    },
+
+    taxRateInput(scope){
+      // 检查输入值是否为正数
+      const value = scope.row.taxRate
+      if (value > 0) {
+        let moment = this.availableCountriesTableForm.availableCountriesList[scope.$index]
+        this.$set(this.availableCountriesTableForm.availableCountriesList,scope.$index, moment)
+      } else {
+        scope.row.taxRate = ''; // 更新输入框的值
+      }
+
+    },
+    marketPriceInput(scope){
+      const value = scope.row.marketPrice
+      if (value > 0) {
+        let moment = this.availableCountriesTableForm.availableCountriesList[scope.$index]
+        this.$set(this.availableCountriesTableForm.availableCountriesList,scope.$index, moment)
+      } else {
+        scope.row.marketPrice = ''; // 更新输入框的值
+
+      }
+    },
+    edit(){
+
+    },
+    submitAvailableCountries(){
+      this.$refs.availableCountriesTableForm.validate((valid) => {
+        if (valid) {
+          this.form.nature = this.multipleSelection
+          this.editAvailableCountriesDialog = false
+        } else {
+
+          return false;
+        }
+      });
+
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+      // 更新选中的项
+      this.selectedIds = val.map(item => item.ID);
+      this.updateRules();
+    },
+    handleSelectionChangeTemp(val) {
+      this.multipleSelectionTemp = val;
+      // 更新选中的项
+      this.selectedIdsTemp = val.map(item => item.ID);
+      this.updateRulesTemp();
+    },
+    updateRules() {
+      this.rules = {}; // 重置规则
+      this.multipleSelection.forEach((row, index) => {
+        this.rules[`availableCountriesList.${this.availableCountriesTableForm.availableCountriesList.indexOf(row)}.taxRate`] = [
+          { required: true, message: this.$t('shop.enterTaxRate'), trigger: 'blur' }
+        ];
+
+      });
+    },
+    updateRulesTemp() {
+      this.rules = {}; // 重置规则
+      this.multipleSelectionTemp.forEach((row, index) => {
+        this.rules[`tempData.${this.availableCountriesTableForm.tempData.indexOf(row)}.taxRate`] = [
+          { required: true, message: this.$t('shop.enterTaxRate'), trigger: 'blur' }
+        ];
+
+      });
+    },
+    selectOne(selection,row){
+      row.sellPrice = (row.CURRENCY_PRODUCT_RATE * this.form.sellPriceStandard).toFixed(2)
+      row.marketPrice = (row.sellPrice * 1.2).toFixed(2)
+    },
+    selectOneTemp(selection,row){
+      row.sellPrice = (row.CURRENCY_PRODUCT_RATE * this.form.sellPriceStandard).toFixed(2)
+      row.marketPrice = (row.sellPrice * 1.2).toFixed(2)
+    },
+    editAvailableCountries(){
+      getCountries().then(response => {
+        this.availableCountriesTableForm.availableCountriesList = response
+        this.editAvailableCountriesDialog = true
+        // this.multipleSelection = this.form.nature
+        this.toggleSelection(this.form.nature)
+      }).catch(err => {
+
+      })
+    },
+    toggleSelection(rows) {
+      if (rows) {
+        rows.forEach(item => { // checkedData为已选数据
+          this.$nextTick( ()=>{
+            this.availableCountriesTableForm.availableCountriesList.find(obj => { //  表单数据
+              if(item.ID === obj.ID) {
+                obj.sellPrice = item.sellPrice
+                obj.marketPrice = item.marketPrice
+                obj.taxRate = item.taxRate
+                this.$refs.multipleTable.toggleRowSelection(obj)
+
+              }
+            })
+          })
+        })
+      } else {
+        this.$refs.multipleTable.clearSelection();
+      }
+    },
     handleRemove (file) {
       console.log(file)
     },
@@ -191,7 +539,7 @@ export default {
                 message: this.$t('common.modifyData'),
                 type: 'info'
             })
-        }) 
+        })
     },
     getData (page, pageSize) {
       getAddGoodsConfig(this.filterModel).then(response => {
@@ -201,7 +549,7 @@ export default {
         this.sellType = response.data.sellType
       }).catch(err => {
         this.$message({
-          message: err, 
+          message: err,
           type: 'error'
         })
       })
@@ -228,8 +576,8 @@ export default {
         categoryType: this.form.categoryType,
         goodsNo: this.form.goodsNo,
         unit: this.form.unit,
-        marketPrice: this.form.marketPrice,
-        sellPrice: this.form.sellPrice,
+        // marketPrice: this.form.marketPrice,
+        // sellPrice: this.form.sellPrice,
         sellPriceStandard: this.form.sellPriceStandard,
         pricePv: this.form.pricePv,
         // point: this.form.point,
@@ -237,7 +585,8 @@ export default {
         content: this.form.content,
         sort: this.form.sort,
         cover: this.form.cover,
-        taxRate: this.form.taxRate
+        // taxRate: this.form.taxRate
+        nature: this.form.nature,
       }
       addGoods(postData).then(response => {
         this.$message({
@@ -258,13 +607,23 @@ export default {
 }
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
 /* 小于760 */
  @media (max-width:759px) {
-    
+
     ::v-deep .el-input {
         width: 100% !important;
     }
+   ::v-deep .el-input-number {
+     width: 100% !important;
+     .el-input {
+       width: auto !important;
+       padding: 0 5px;
+     }
+   }
+   ::v-deep .el-input-number--medium {
+     width: 100% !important;
+   }
     ::v-deep .el-select {
         width: 100% !important;
     }
@@ -282,16 +641,26 @@ export default {
         width:100%;
         padding-left: 1%;
     }
-    ::v-deep img { 
+    ::v-deep img {
         width: 100% !important;
         height: 100% !important;
     }
-} 
+}
 
 @media (min-width:760px) {
     ::v-deep .el-input {
         width: 400px !important;
     }
+    ::v-deep .el-input-number {
+      width: 100% !important;
+      .el-input {
+        width: auto !important;
+        padding: 0 5px;
+      }
+    }
+    ::v-deep .el-input-number--medium {
+      width: 100% !important;
+    }
     ::v-deep .el-select {
         width: 400px !important;
     }
@@ -306,4 +675,31 @@ export default {
         padding-left: 10%;
     }
 }
+
+.el-input{
+  width: 90%!important;
+}
+/* 去掉全选按钮 */
+::v-deep .el-table .disabledCheck .cell .el-checkbox__inner {
+  display: none !important;
+}
+
+::v-deep .el-table .disabledCheck .cell::before {
+  content: '';
+  text-align: center;
+  line-height: 37px;
+}
+
+.left-aligned-input .el-input-number__inner {
+  text-align: left;
+}
+::v-deep .el-input-number .el-input__inner {
+  text-align: left;
+}
+
+::v-deep .el-form-item{
+  //margin-bottom: 16px !important;
+  transform: translateY(6px);
+}
+
 </style>

+ 369 - 20
src/views/shop/index.vue

@@ -104,26 +104,29 @@
             <el-form-item :label="$t('shop.unit')"><!-- 单位 -->
               <el-input v-model="form.unit"></el-input>
             </el-form-item>
-            <el-form-item :label="$t('shop.taxRate')"><!-- 税率 -->
-              <el-input v-model="form.taxRate">
-                <template slot="append">%</template>
-              </el-input>
-            </el-form-item>
-            <el-form-item :label="$t('shop.uSPrice')" p>
-              <el-input v-model="form.sellPriceStandard"></el-input>
-            </el-form-item>
-            <el-form-item :label="$t('shop.salesPrice')" p>
-              <el-input v-model="form.sellPrice"></el-input>
-            </el-form-item>
-            <el-form-item :label="$t('shop.marketPrice')">
-              <el-input v-model="form.marketPrice"></el-input>
+<!--            <el-form-item :label="$t('shop.taxRate')">&lt;!&ndash; 税率 &ndash;&gt;-->
+<!--              <el-input v-model="form.taxRate">-->
+<!--                <template slot="append">%</template>-->
+<!--              </el-input>-->
+<!--            </el-form-item>-->
+            <el-form-item :label="$t('shop.standardPrice')" p>
+              <el-input v-model="form.sellPriceStandard" @input="sellPriceStandardInput"></el-input>
             </el-form-item>
+<!--            <el-form-item :label="$t('shop.salesPrice')" p>-->
+<!--              <el-input v-model="form.sellPrice"></el-input>-->
+<!--            </el-form-item>-->
+<!--            <el-form-item :label="$t('shop.marketPrice')">-->
+<!--              <el-input v-model="form.marketPrice"></el-input>-->
+<!--            </el-form-item>-->
             <el-form-item :label="$t('shop.priceBV')" v-show="pvDisabled"> <!-- 价格BV -->
               <el-input v-model="form.pricePv"></el-input>
             </el-form-item>
   <!--                    <el-form-item label="Exchange points" v-show="false"> &lt;!&ndash; 兑换积分 &ndash;&gt;-->
   <!--                        <el-input v-model="form.point"></el-input>-->
   <!--                    </el-form-item>-->
+          <el-form-item :label="$t('shop.availableCountries')"><!-- 可购买国家 -->
+            <el-button type="primary" size="small" @click="editAvailableCountries">{{ $t('shop.modifyAvailableCountries') }}</el-button>
+          </el-form-item>
             <el-form-item :label="$t('shop.inventory')"> <!-- 库存 -->
               <el-input v-model="form.storeNums"></el-input>
             </el-form-item>
@@ -145,8 +148,8 @@
                   v-model="form.image"
                   :request-route="'v1/shop/upload'"
                   :default-image-url="form.cover"
-                  width="400px"
-                  height="160px"
+                  width="100%"
+                  height="260px"
                   @on-success="upLoadSuccess"
                 ></Upload>
               </div>
@@ -157,6 +160,99 @@
             <el-button type="primary" @click.native="handleEdit">{{ $t('table.edit') }}<!-- 修 改 --></el-button>
           </div>
       </el-dialog>
+
+      <el-dialog :title="$t('shop.modifyAvailableCountries')" :visible.sync="editAvailableCountriesDialog" top="3%" width="60%"><!-- 修改可购买国家 -->
+        <el-form ref="form"  label-width="130px" class="">
+          <el-form-item :label="$t('shop.productName')"><!-- 商品名称 -->
+            <el-input v-model="form.goodsName" style="width: 90%"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('transportationConfig.countryName')">
+            <el-input
+              v-model="searchQuery"
+              placeholder=""
+              style="width: 90%"
+              @input="updateTableData"
+            ></el-input>
+          </el-form-item>
+        </el-form>
+        <el-form :model="availableCountriesTableForm" ref="availableCountriesTableForm" :rules="rules">
+          <el-table v-show="!searchQuery" :data="availableCountriesTableForm.availableCountriesList" ref="multipleTableCountries" @selection-change="countriesSelectionChange" @select="selectOne" :selectable="isRowSelectable" stripe :header-cell-class-name="cellClass" height="500" style="width: 100%;">
+            <el-table-column
+                type="selection"
+                width="55"
+                :selectable="selectable"
+                :show-select-all="false"
+            >
+            </el-table-column>
+            <el-table-column prop="NAME" :label="$t('transportationConfig.countryName')" />
+            <el-table-column prop="LOCAL_CURRENCY_NAME" :label="$t('exchangeRateConfig.currencyType')" />
+            <el-table-column :label="$t('shop.salesPrice')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`availableCountriesList.${scope.$index}.sellPrice`" >
+                  <el-input-number v-model="scope.row.sellPrice" :controls="false" disabled></el-input-number>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column :label="$t('shop.marketPrice')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`availableCountriesList.${scope.$index}.marketPrice`" >
+                  <el-input-number v-model="scope.row.marketPrice" :precision="2" :min="0.01" :controls="false" clearable></el-input-number>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column :label="$t('shop.taxRate')" min-width="100px;">
+              <template slot-scope="scope">
+                <el-form-item :prop="`availableCountriesList.${scope.$index}.taxRate`" >
+                  <div class="flexJfAc">
+                    <el-input-number v-model="scope.row.taxRate" :precision="2" :min="0.01" :controls="false"></el-input-number><span>%</span>
+                  </div>
+                </el-form-item>
+              </template>
+            </el-table-column>
+          </el-table>
+
+            <el-table v-show="searchQuery" :data="availableCountriesTableForm.tempData" ref="multipleTableTemp" @row-click="handleRowClickTemp" @selection-change="handleSelectionChangeTemp" @select="selectOneTemp" :selectable="isRowSelectable" :header-cell-class-name="cellClass" stripe height="500" style="width: 100%;">
+                <el-table-column
+                        type="selection"
+                        width="55"
+                        :selectable="selectable"
+                        :show-select-all="false"
+                >
+                </el-table-column>
+                <el-table-column prop="NAME" :label="$t('transportationConfig.countryName')" />
+                <el-table-column prop="LOCAL_CURRENCY_NAME" :label="$t('exchangeRateConfig.currencyType')" />
+                <el-table-column :label="$t('shop.salesPrice')" min-width="100px;">
+                    <template slot-scope="scope">
+                        <el-form-item :prop="`tempData.${scope.$index}.sellPrice`" >
+                            <el-input-number v-model="scope.row.sellPrice" :controls="false" disabled></el-input-number>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column :label="$t('shop.marketPrice')" min-width="100px;">
+                    <template slot-scope="scope">
+                        <el-form-item :prop="`tempData.${scope.$index}.marketPrice`">
+                            <el-input-number v-model="scope.row.marketPrice" :precision="2" :min="0" :controls="false" clearable></el-input-number>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column :label="$t('shop.taxRate')" min-width="100px;">
+                    <template slot-scope="scope">
+                        <el-form-item :prop="`tempData.${scope.$index}.taxRate`" >
+                            <div class="flexJfAc">
+                                <el-input-number v-model="scope.row.taxRate" :precision="2" :step="0.1" :min="0" :controls="false"></el-input-number><span>%</span>
+                            </div>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+            </el-table>
+
+
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button type="warning" size="mini" @click="editAvailableCountriesDialog = false">{{ $t('table.cancel') }}</el-button>
+          <el-button type="primary" size="mini" @click="submitAvailableCountries">{{ $t('table.confirm') }}</el-button>
+        </div>
+      </el-dialog>
     </div>
   </template>
 
@@ -251,9 +347,191 @@
         pvDisabled: true,
         exchangeRate: baseInfo.exchangeRate(),
         labelPosition: getScreenWidth() >= 600 ? 'left' : 'top',
+        editAvailableCountriesDialog: false,
+        availableCountriesTableForm: {
+          availableCountriesList: [],
+          tempData:[],
+        },
+        multipleSelectionCountries: [],
+          multipleSelectionTemp: [],
+
+        rules: {},
+          rulesTemp: {},
+          searchQuery: '',
+
+          selectionTempData: [],
+          selectedIdsCountry: [], // 存储选中的项的 ID
+          selectedIdsTemp: [],
       }
     },
     methods: {
+        updateTableData() {
+            let that = this;
+            // if (!this.searchQuery) {
+            //   return this.availableCountriesTableForm.availableCountriesList;
+            // }
+            // 临时存储原始数据,保持搜索时不改变其他列的值
+            const query = that.searchQuery.toLowerCase();
+            // this.$refs.multipleTable.toggleRowSelection(JSON.parse(JSON.stringify(this.multipleSelection)),true)
+
+            if (that.availableCountriesTableForm.tempData.length === 0) {
+                // this.tempData = JSON.parse(JSON.stringify(this.availableCountriesTableForm.availableCountriesList));
+                // this.selectionTempData = JSON.parse(JSON.stringify(this.multipleSelection));
+
+            }
+            // const query = this.searchQuery.toLowerCase();
+            that.$nextTick(() => {
+                // 在数据更新后,重新设置选中的项
+                console.log(this.searchQuery === "")
+                console.log(query)
+
+                if(!that.searchQuery){
+                    console.log('no---')
+                    that.setSelectionTemp();
+                } else {
+                    console.log('yes---')
+                    that.availableCountriesTableForm.tempData = that.availableCountriesTableForm.availableCountriesList.filter(row => {
+                        return row.NAME.toLowerCase().includes(query);
+                    });
+                    that.setSelection();
+
+                }
+            });
+            // this.availableCountriesTableForm.availableCountriesList.forEach(row => {
+            //   if (row.NAME.toLowerCase().includes(query)) {
+            //   } else {
+            //     const originalRow = this.filteredData.find(item => item.NAME === row.NAME);
+            //     if (originalRow) {
+            //       if(originalRow.selected === true){
+            //         console.log('originalRow true')
+            //       }
+            //       row = originalRow;
+            //
+            //     }
+            //   }
+            // });
+            // this.$refs.multipleTable.toggleRowSelection(this.selectionTempData)
+
+        },
+        setSelection() {
+            // this.$refs.multipleTable.clearSelection();
+            console.log('----00000')
+            this.availableCountriesTableForm.tempData.forEach(row => {
+                console.log('----1111')
+                if (this.selectedIdsCountry.includes(row.ID)) {
+                  this.$nextTick(() => {
+                    this.$refs.multipleTableTemp.toggleRowSelection(row, true);
+                  });
+                }
+            });
+        },
+        setSelectionTemp() {
+            // this.$refs.multipleTable.clearSelection();
+            let selectedIds = JSON.parse(JSON.stringify(this.selectedIdsCountry))
+            let selectedIdsTemp = JSON.parse(JSON.stringify(this.selectedIdsTemp))
+
+            console.log('----2222')
+            let list = selectedIds.concat(selectedIdsTemp)
+            console.log("list=====+" + list)
+            this.availableCountriesTableForm.availableCountriesList.forEach(row => {
+                console.log('----3333')
+                if (list.includes(row.ID)) {
+                    this.$refs.multipleTableCountries.toggleRowSelection(row, true);
+                }
+            });
+        },
+        handleRowClickTemp(row) {
+            // 手动控制行点击时的选中状态
+            // this.$refs.multipleTableTemp.toggleRowSelection(row,true);
+        },
+        handleSelectionChangeTemp(val) {
+            this.multipleSelectionTemp = val;
+            // 更新选中的项
+            this.selectedIdsTemp = val.map(item => item.ID);
+            this.updateRulesTemp();
+        },
+        updateRulesTemp() {
+            this.rules = {}; // 重置规则
+            this.multipleSelectionTemp.forEach((row, index) => {
+                this.rules[`tempData.${this.availableCountriesTableForm.tempData.indexOf(row)}.taxRate`] = [
+                    { required: true, message: this.$t('shop.enterTaxRate'), trigger: 'blur' }
+                ];
+
+            });
+        },
+
+        // 隐藏表头中的全选框
+      cellClass(row) {
+        if (row.columnIndex === 0) {
+          return 'disabledCheck'
+        }
+      },
+      isRowSelectable(row, index) {
+        return row.CURRENCY_PRODUCT_RATE == 0;
+      },
+      selectable(row, index) {
+        return row.CURRENCY_PRODUCT_RATE !== 0;
+      },
+      sellPriceStandardInput(value){
+        console.log(value)
+        // this.form.nature = []
+        this.toggleSelection(this.form.nature, 'input')
+
+      },
+      countriesSelectionChange(val) {
+        this.multipleSelectionCountries = val;
+          this.selectedIdsCountry = val.map(item => item.ID);
+
+        this.updateRules();
+      },
+      updateRules() {
+        this.rules = {}; // 重置规则
+        this.multipleSelectionCountries.forEach((row, index) => {
+          this.rules[`availableCountriesList.${this.availableCountriesTableForm.availableCountriesList.indexOf(row)}.taxRate`] = [
+            { required: true, message: this.$t('shop.enterTaxRate'), trigger: 'blur' }
+          ];
+
+        });
+      },
+      selectOne(selection,row){
+        row.sellPrice = (row.CURRENCY_PRODUCT_RATE * this.form.sellPriceStandard).toFixed(2)
+        row.marketPrice = (row.sellPrice * 1.2).toFixed(2)
+      },
+        selectOneTemp(selection,row){
+            console.log(row.CURRENCY_PRODUCT_RATE)
+            // if(!row.CURRENCY_PRODUCT_RATE){
+            //   return false
+            // }
+            row.sellPrice = (row.CURRENCY_PRODUCT_RATE * this.form.sellPriceStandard).toFixed(2)
+            row.marketPrice = (row.sellPrice * 1.2).toFixed(2)
+        },
+      taxRateInput(scope){
+        const value = parseFloat(scope.row.taxRate) || 0;
+        if (value <= 0) {
+          scope.row.taxRate = ''; // 更新输入框的值
+        } else {
+          let moment = this.availableCountriesTableForm.availableCountriesList[scope.$index]
+          this.$set(this.availableCountriesTableForm.availableCountriesList,scope.$index, moment)
+        }
+      },
+      marketPriceInput(scope){
+        const value = parseFloat(scope.row.marketPrice) || 0;
+        if (value <= 0) {
+          scope.row.marketPrice = ''; // 更新输入框的值
+        } else {
+          let moment = this.availableCountriesTableForm.availableCountriesList[scope.$index]
+          this.$set(this.availableCountriesTableForm.availableCountriesList,scope.$index, moment)
+        }
+      },
+      submitAvailableCountries(){
+        this.form.nature = this.multipleSelectionCountries
+        this.editAvailableCountriesDialog = false
+      },
+      editAvailableCountries(){
+        this.editAvailableCountriesDialog = true
+        this.toggleSelection(this.form.nature,'data')
+
+      },
       handleSelectionChange (val) {
         this.multipleSelection = val
       },
@@ -323,12 +601,60 @@
             vueObj.form.taxRate = response.data.goodsInfo.TAX_RATE
             vueObj.form.coverOrigin = response.data.goodsInfo.COVER
             vueObj.form.cover = tool.getArImage(response.data.goodsInfo.COVER, '/files/')
+            vueObj.availableCountriesTableForm.availableCountriesList = response.data.goodsInfo.SHOP_GOODS_NATURE
+            const goods = JSON.parse(JSON.stringify(response.data.goodsInfo.SHOP_GOODS_NATURE))
+            let nature = []
+            goods.find(item => { //  表单数据
+              if(item.SHOP_GOODS_NATURE.length > 0) {
+                item.sellPrice = item.SHOP_GOODS_NATURE[0].SELL_PRICE
+                item.taxRate = item.SHOP_GOODS_NATURE[0].TAX_RATE
+                item.marketPrice = item.SHOP_GOODS_NATURE[0].MARKET_PRICE
+                nature.push(item)
+              }
+              vueObj.form.nature = JSON.parse(JSON.stringify(nature))
+            })
+            console.log(vueObj.form.nature)
 
             this.$forceUpdate()
         }).catch(err => {
 
         })
       },
+      toggleSelection(rows, type) {
+        let data = JSON.parse(JSON.stringify(rows))
+        if(data.length > 0 && type === 'input'){
+          let checkedData = this.form.nature
+          checkedData.forEach(item => { // checkedData为已选数据
+            this.$nextTick( ()=>{
+              this.availableCountriesTableForm.availableCountriesList.find(obj => { //  表单数据
+                if(item.ID === obj.ID) {
+                  obj.sellPrice = (item.CURRENCY_PRODUCT_RATE * this.form.sellPriceStandard).toFixed(2)
+                  obj.taxRate = item.taxRate
+                  obj.marketPrice = (obj.sellPrice * 1.2).toFixed(2)
+                  this.$refs.multipleTableCountries.toggleRowSelection(obj,true)
+                }
+              })
+            })
+          })
+          return false
+        }
+        else if (data.length > 0 && type === 'data') {
+          data.forEach(item => { // checkedData为已选数据
+            this.$nextTick( ()=>{
+              this.availableCountriesTableForm.availableCountriesList.find(obj => { //  表单数据
+                if(item.ID === obj.ID) {
+                  obj.sellPrice = item.sellPrice
+                  obj.taxRate = item.taxRate
+                  obj.marketPrice = item.marketPrice
+                  this.$refs.multipleTableCountries.toggleRowSelection(obj,true)
+                }
+              })
+            })
+          })
+        } else {
+          this.$refs.multipleTableCountries.clearSelection();
+        }
+      },
       handleEdit () {
         this.dialogEditFormVisible = false
         this.$message({
@@ -468,7 +794,7 @@
                 })
             })
         })
-      }
+      },
     },
     watch: {
       // 监听商品分类,控制PV是否展示
@@ -477,12 +803,12 @@
         handler (modern, origin) {
           this.pvDisabled = (parseInt(modern) === 1)
         }
-      }
-      // // 监听商品标准价格,自动计算销售价格
+      },
+      // 监听商品标准价格,自动计算销售价格
       // 'form.sellPriceStandard': {
       //     deep: true,
       //     handler(modern, origin) {
-      //         this.form.sellPrice = modern * this.exchangeRate
+      //
       //     }
       // },
     }
@@ -509,11 +835,34 @@
         width: 100% !important;
         height: 100% !important;
       }
-      
+
       @media (max-width:862px) {
         /deep/ .el-dialog {
           width:100%;
         }
       }
+      ::v-deep .el-input-number {
+        width: 100% !important;
+        .el-input {
+          width: auto !important;
+          padding: 0 5px;
+        }
+      }
+
+      ::v-deep .el-input-number .el-input__inner {
+        text-align: left;
+      }
+      ::v-deep .el-form-item{
+        transform: translateY(6px);
+      }
+      /* 去掉全选按钮 */
+      ::v-deep .el-table .disabledCheck .cell .el-checkbox__inner {
+        display: none !important;
+      }
 
+      ::v-deep .el-table .disabledCheck .cell::before {
+        content: '';
+        text-align: center;
+        line-height: 37px;
+      }
   </style>

+ 38 - 4
src/views/user/empty-order-operation.vue

@@ -6,7 +6,16 @@
           <el-form ref="form" :model="form" label-width="250px" :label-position="labelPosition">
 
             <div class="hr-tip"><span>{{ $t('member.accountInformation') }}</span></div>
-
+            <el-form-item :label="$t('transportationConfig.countryName')" required>
+              <el-select ref="select" @change="countriesChange" v-model="form.countryId" filterable placeholder="">
+                <el-option v-for="(item, index) in countries" :key="item.ID" :label="item.NAME" :value="item.ID" />
+              </el-select>
+            </el-form-item>
+            <el-form-item :label="$t('common.language')" required>
+              <el-select ref="select" v-model="form.languageId" filterable placeholder="">
+                <el-option v-for="(item, index) in languageList" :key="item.ID" :label="item.NAME" :value="item.ID" />
+              </el-select>
+            </el-form-item>
             <el-form-item :label="$t('member.memberCode')" required>
               <el-input v-model="form.userName"></el-input>
             </el-form-item>
@@ -96,15 +105,18 @@
 	import {getScreenWidth} from "@/utils"
 	import region from "@/store/modules/region"
 	import {fetchMemberFullInfo, fetchUserAdd, updateUserAdd} from "@/api/member"
-
+  import { getCountries, getLanguages } from "@/api/site"
   export default {
     name: 'emptyOrderOperation',
     mounted() {
-      this.getData()
+      this.getCountries()
+      this.getLanguageList()
     },
     data() {
       return {
         form: {
+          countryId: '',
+          languageId: '',
           userName: '',
           nation: '',
           realName: '',
@@ -160,9 +172,31 @@
         permission: permission,
 				screenWidth: getScreenWidth() > 650 ? '650px' : getScreenWidth() + 'px',
 				labelPosition: getScreenWidth() >= 600 ? 'right' : 'top',
+        countries: [],
+        languageList: []
       }
     },
     methods: {
+      countriesChange(e){
+        this.getData()
+      },
+      getLanguageList(){
+        getLanguages().then(response => {
+          let obj = response
+          let list = []
+          Object.keys(obj).forEach(function(key) {
+            list.push(obj[key])
+          });
+          this.languageList = list
+        })
+      },
+      getCountries(){
+        getCountries().then(response => {
+          this.countries = response
+        }).catch(err => {
+
+        })
+      },
       getData() {
         if (permission.hasPermission(`user/user-del`)) {
           this.tabActiveName = 'third'
@@ -173,7 +207,7 @@
         if (permission.hasPermission(`user/user-add`)) {
           this.tabActiveName = 'first'
 					this.loading = true
-					fetchUserAdd().then(response => {
+					fetchUserAdd({countryId: this.form.countryId}).then(response => {
 						this.loading = false
 						this.allNation = response.data.allNation
 						this.allOpenBank = response.data.allOpenBank

+ 58 - 3
src/views/user/member-list.vue

@@ -112,7 +112,7 @@
 		</el-dialog>
 
 		<!-- 修改会员信息 -->
-		<el-dialog :title="formModifyProfile.typeName" :visible.sync="dialogModifyProfileVisible" :width="screenWidth">
+		<el-dialog :title="formModifyProfile.typeName" :visible.sync="dialogModifyProfileVisible" :width="screenWidth" :destroy-on-close="true">
 			<el-form ref="form" :model="formModifyProfile" label-width="150px" :label-position="labelPosition">
 				<el-form-item :label="$t('member.memberName')">
 					<el-input v-model="formModifyProfile.realName"></el-input>
@@ -120,6 +120,16 @@
 				<el-form-item :label="$t('member.identityNo')">
 					<el-input v-model="formModifyProfile.idCard"></el-input>
 				</el-form-item>
+        <el-form-item :label="$t('transportationConfig.countryName')">
+          <el-select v-model="formModifyProfile.country" filterable ref="countryId" @change="countryChange" @blur="countryVisibleChange($event)">
+            <el-option v-for="(item,index) in allCountry" :key="index" :label="item.NAME" :value="item.ID"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="$t('common.language')">
+          <el-select v-model="formModifyProfile.language">
+            <el-option v-for="(item,index) in allLanguage" :key="index" :label="item.NAME" :value="item.ID"></el-option>
+          </el-select>
+        </el-form-item>
 				<el-form-item :label="$t('member.phoneNumber')">
 					<el-input v-model="formModifyProfile.mobile"></el-input>
 				</el-form-item>
@@ -156,6 +166,7 @@ import {
 	fetchCloseDec, fetchCloseDecGet, fetchCloseLoginGet, fetchMemberExport, fetchMemberList, fetchProfileGet,
 	updateModifyPassword, updateModifyProfile, updateSetActive, updateSetAsStockist, updateSetChartDisplay, updateSetLock, updateSetModifyPassword, updateSetRechargeDisplay,
 } from "@/api/member"
+import {getBank} from "@/api/site";
 
 export default {
 	name: 'memberList',
@@ -274,6 +285,8 @@ export default {
 			],
 			allOpenBank:null,
 			allNation:null,
+      allCountry: null,
+      allLanguage: null,
 			submitDecButtonStat: false,
 			submitPasswordButtonStat: false,
 			submitProfileButtonStat: false,
@@ -291,9 +304,48 @@ export default {
 			fixed: getScreenWidth() < 500 ? false : 'right',
 			// leftFixed: ['Android', 'ios'].includes(getOperatingSystem()) ? false : 'left',
 			// fixed: ['Android', 'ios'].includes(getOperatingSystem()) ? false : 'right',
+      originalCountry: '',
 		}
 	},
 	methods: {
+    countryVisibleChange(event){
+    },
+    countryChange(row){
+      this.$nextTick(() => {
+        this.$refs.countryId.blur()
+        this.$confirm( this.$t('member.modifyCountry'), this.$t('common.hint'), {
+          confirmButtonText: this.$t('common.confirm'),
+          cancelButtonText: this.$t('common.cancel'),
+          type: 'warning'
+        }).then(() => {
+          // this.$message({
+          //   type: 'success',
+          //   message: '!'
+          // });
+          this.getBanks(row)
+
+        }).catch(() => {
+          this.formModifyProfile.country = this.originalCountry
+          this.getBanks(this.originalCountry)
+        });
+
+      });
+
+
+    },
+
+    getBanks(countryId){
+      getBank( { countryId: countryId, }).then(response => {
+        this.formModifyProfile.openBank = null
+        this.allOpenBank = response
+      }).catch(error => {
+        this.$message({
+          message: error,
+          type: 'warning'
+        })
+
+      })
+    },
 		handleSelectionChange(val) {
 			this.multipleSelection = val
 		},
@@ -472,6 +524,9 @@ export default {
 				this.formModifyProfile = response.data.userInfo
 				this.allOpenBank = response.data.allOpenBank
 				this.allNation = response.data.allNation
+        this.allCountry = response.data.country
+        this.allLanguage = response.data.language
+        this.originalCountry = JSON.parse(JSON.stringify(response.data.userInfo.country))
 			}).catch(error => {
 				this.$message({
 					message: error,
@@ -566,10 +621,10 @@ export default {
 			}).catch(error => {
 				this.$message({
 					message: error,
-					type: 'success'
+					type: 'warning'
 				})
 				this.submitProfileButtonStat = false
-				this.dialogModifyProfileVisible = false
+				// this.dialogModifyProfileVisible = false
 			})
 		},
 	}