Bläddra i källkod

feature: 卡片类型页面,样式调整

ljc 7 månader sedan
förälder
incheckning
3bbb93bb23

+ 1 - 1
package.json

@@ -29,7 +29,7 @@
     "crypto-js": "^4.2.0",
     "dayjs": "^1.11.4",
     "echarts": "^5.3.1",
-    "element-plus": "^2.2.28",
+    "element-plus": "^2.11.7",
     "exceljs": "^4.3.0",
     "file-saver": "^2.0.5",
     "fuse.js": "^6.6.2",

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
public/css/element-ui.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
public/css/element@2.12.2.css


BIN
public/css/fonts/element-icons.woff


+ 88 - 0
public/css/index.css

@@ -0,0 +1,88 @@
+html,body{
+    width: 100%;
+    height: 100%;
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+}
+.container{
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    overflow-y: auto;
+    box-sizing: border-box;
+}
+.Va-document{
+    width: 100%;
+    height: auto;
+    box-sizing: border-box;
+    font-size: 12px;
+}
+.Va-document .title-head{
+    width: 100%;
+    background-color: #eb3f57 ;
+    text-align: center;
+    line-height: 2.5;
+    color: #ffffff;
+}
+.Va-document .content-info{
+    width: 100%;
+    padding: 15px;
+    box-sizing: border-box;
+}
+.Va-document .content-info .only-head{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+.Va-document .content-info .only-head .divider{
+    flex: 1;
+    height: 1px;
+    background-color: #C5C5C9;
+    margin: 0 5px;
+}
+.Va-document .content-info .my-form-item-label .des{
+    color: #949494;
+}
+.Va-document .content-info .avatar-uploader {
+    border: 1px dashed #C4C4C4;
+    margin: 10px;
+    width: 150px;
+    height: 80px;
+    line-height: 80px;
+    display: inline-block;
+    overflow: hidden;
+}
+.Va-document .content-info .avatar-uploader .el-upload {
+    width: 100%;
+    text-align: center;
+}
+div.menu-logo {
+    margin: 0 6px;
+    cursor: pointer;
+    user-select: none;
+}
+.menu-logo.chooseLang{
+    border: 1px solid #C5C5C9;
+    width: 130px;
+    margin-bottom: 10px;
+    text-align: center;
+}
+
+.s-btn{
+    background-color: #eb3f57 ;
+    border-color: #eb3f57 ;
+}
+.el-button--primary:active,.el-button:focus,.el-button--primary:hover{
+    background-color: #eb3f57 ;
+    border-color: #eb3f57 ;
+    opacity: 0.8;
+}
+.el-input__inner:focus{
+    border-color: #eb3f57 ;
+}
+
+.el-upload{
+    width: 100%;
+    height: 100%;
+}

+ 76 - 0
public/css/preloading.css

@@ -0,0 +1,76 @@
+.line-scale-party>div,
+.line-scale-pulse-out-rapid>div,
+.line-scale-pulse-out>div,
+.line-scale>div {
+    width: 4px;
+    height: 35px;
+    display: inline-block
+}
+
+.line-scale-party>div,
+.line-scale-pulse-out-rapid>div,
+.line-scale-pulse-out>div,
+.line-scale>div,
+.line-spin-fade-loader>div {
+    border-radius: 2px;
+    margin: 2px;
+    background-color: #fff
+}
+
+@-webkit-keyframes line-scale {
+
+    0%,
+    100% {
+        -webkit-transform: scaley(1);
+        transform: scaley(1)
+    }
+
+    50% {
+        -webkit-transform: scaley(.4);
+        transform: scaley(.4)
+    }
+}
+
+@keyframes line-scale {
+
+    0%,
+    100% {
+        -webkit-transform: scaley(1);
+        transform: scaley(1)
+    }
+
+    50% {
+        -webkit-transform: scaley(.4);
+        transform: scaley(.4)
+    }
+}
+
+.line-scale>div:nth-child(1) {
+    -webkit-animation: line-scale 1s -.4s infinite cubic-bezier(.2, .68, .18, 1.08);
+    animation: line-scale 1s -.4s infinite cubic-bezier(.2, .68, .18, 1.08)
+}
+
+.line-scale>div:nth-child(2) {
+    -webkit-animation: line-scale 1s -.3s infinite cubic-bezier(.2, .68, .18, 1.08);
+    animation: line-scale 1s -.3s infinite cubic-bezier(.2, .68, .18, 1.08)
+}
+
+.line-scale>div:nth-child(3) {
+    -webkit-animation: line-scale 1s -.2s infinite cubic-bezier(.2, .68, .18, 1.08);
+    animation: line-scale 1s -.2s infinite cubic-bezier(.2, .68, .18, 1.08)
+}
+
+.line-scale>div:nth-child(4) {
+    -webkit-animation: line-scale 1s -.1s infinite cubic-bezier(.2, .68, .18, 1.08);
+    animation: line-scale 1s -.1s infinite cubic-bezier(.2, .68, .18, 1.08)
+}
+
+.line-scale>div:nth-child(5) {
+    -webkit-animation: line-scale 1s 0s infinite cubic-bezier(.2, .68, .18, 1.08);
+    animation: line-scale 1s 0s infinite cubic-bezier(.2, .68, .18, 1.08)
+}
+
+.line-scale>div {
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both
+}

BIN
public/favicon.ico


+ 35 - 14
public/index.html

@@ -1,17 +1,38 @@
 <!DOCTYPE html>
 <html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width,initial-scale=1.0">
-    <link rel="icon" href="/favicon.ico">
-    <title><%= htmlWebpackPlugin.options.title %></title>
-  </head>
-  <body>
-    <noscript>
-      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
-    </noscript>
-    <div id="app"></div>
-    <!-- built files will be auto injected -->
-  </body>
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+  <link href="/css/preloading.css" rel="stylesheet" type="text/css">
+  <title>CWG-管理系统</title>
+
+</head>
+<body>
+<noscript>
+  <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
+    Please enable it to continue.</strong>
+</noscript>
+
+<div id="app">
+  <!-- preloadidng -->
+  <div id="pre" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 100000; ">
+    <div style="background-color: rgba(0, 0, 0, .8); width: 100%; height: 100%;">
+      <div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
+        <div class="line-scale">
+          <div></div>
+          <div></div>
+          <div></div>
+          <div></div>
+          <div></div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- built files will be auto injected -->
+
+
+</body>
 </html>

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
src/assets/theme/index.scss


+ 2 - 2
src/components/NavMenu.vue

@@ -2,7 +2,7 @@
   <el-menu id="NavMenu" :default-openeds="['0']" :collapse="isCollapse">
     <div class="logo">
       <img v-if="isCollapse" class="img2" :src="logo2" alt="" />
-      <img v-else class="img1" src="logo" alt="" />
+      <img v-else class="img1" :src="logo1" alt="" />
     </div>
     <div v-for="(item, key) in menus" :key="key">
       <el-submenu v-if="item.show && item.name != 'R-Shop'" :index="key + ''">
@@ -54,7 +54,7 @@
   import session from '@/lib/session' // 假设 session 已转换为 ES module
   // 引入图片
   import logo2 from '@/assets/image/logo2.png'
-  import logo from '@/assets/image/logo.png'
+  import logo1 from '@/assets/image/logo.png'
   const v3This = getCurrentInstance()
 
   // 组合式 API

+ 3 - 12
src/main.ts

@@ -1,14 +1,10 @@
-import { createApp, ref, toRef } from 'vue'
+import { createApp } from 'vue'
 import App from './App.vue'
 import router from './routers'
 import vuex from './vuexStore'
 import pinia from './store'
 
 import { registerElIcons } from '@/plugins/ElIcons'
-// 引入全局组件布局
-import PageWrapLayout from '@/components/PageWrapLayout/index.vue'
-// 权限路由
-// import './permission'
 // svg-icons注册导入
 // @ts-ignore: virtual module injected by svg-icons plugin
 import 'virtual:svg-icons-register'
@@ -24,30 +20,25 @@ import '@/styles/cwg_common.scss'
 // 引入阿里图标库
 import '@/assets/iconfont/iconfont.scss'
 import '@/assets/iconfont/iconfont.js'
-import '@/assets/theme/index.scss'
 // 引入国际化
 import i18n from './i18n'
 
-import Config from './config'
+// import Config from './config'
 
 // import Pigeon from './lib/pigeon.js'
 //定义mixin
 const mixins = {
   created() {
     // this.Session = SessionStorage
-    this.Config = Config
+    // this.Config = Config
   },
 }
 
 const app = createApp(App)
 registerElIcons(app)
 
-const instance = ref(null)
-app.config.globalProperties.$instance = instance
-app.provide('instance', toRef(instance))
 app.mixin(mixins)
 app.component('SvgIcon', SvgIcon)
-app.component('PageWrapLayout', PageWrapLayout)
 
 app.use(vuex)
 app.use(pinia)

+ 8 - 8
src/routers/modules/uCard.ts

@@ -25,14 +25,14 @@ const uCardRoute = {
     //     name: 'R-KycAuth',
     //     component: () => import(/* webpackChunkName: "KycAuth" */ '@/views/card/KycAuth.vue'),
     //   },
-    //   {
-    //     meta: {
-    //       OnBreadCrumb: true,
-    //     },
-    //     path: 'type',
-    //     name: 'R-CardType',
-    //     component: () => import(/* webpackChunkName: "CardType" */ '@/views/card/CardType.vue'),
-    //   },
+    {
+      meta: {
+        OnBreadCrumb: true,
+      },
+      path: 'type',
+      name: 'R-CardType',
+      component: () => import(/* webpackChunkName: "CardType" */ '@/views/card/CardType/index.vue'),
+    },
     //   {
     //     meta: {
     //       OnBreadCrumb: true,

+ 8 - 0
src/service/ucard.ts

@@ -95,6 +95,14 @@ class UCardService extends Service {
   async balanceUpdate(params = {}) {
     return await this.post('/wasabi/card/wallet/balance/update', params)
   }
+  // 更新卡片类型配置
+  async updateCardTypesConfig(params = {}) {
+    return await this.post('/wasabi/card/type/config/update', params)
+  }
+  // 更新卡片类型列表
+  async updateCardTypes(params = {}) {
+    return await this.post('/wasabi/card/types', params)
+  }
 }
 
 export default new UCardService()

+ 7 - 0
src/styles/common.scss

@@ -86,3 +86,10 @@ body {
   border: none !important;
   outline: none !important;
 }
+
+.mb20{
+  @include marBot (20px)
+}
+.mb30{
+  @include marBot (30px)
+}

+ 14 - 2
src/styles/cwg_common.scss

@@ -68,7 +68,7 @@ a {
 .crm-border-left-no{
   border-left: none!important;
   .el-input__wrapper{
-    padding: 0 !important;
+    //padding: 0 !important;
   }
   .el-input__inner, .el-button{
     border-left: none;
@@ -87,6 +87,10 @@ a {
   }
 }
 
+.el-input__wrapper{
+  width: 100%;
+}
+
 //下划线
 .crm-text-underline{
   text-decoration: underline;
@@ -190,6 +194,10 @@ a {
 }
 
 //dialog
+.el-dialog--center .el-dialog__body{
+  text-align:initial;
+  padding:25px 25px 30px;
+}
 .dialog_header_w.el-dialog {
   width: 650px;
   .el-dialog__header {
@@ -277,6 +285,9 @@ a {
     color: #EB3F57;
   }
 }
+.el-message-box__message{
+  width: 100%;
+}
 
 .el-table th {
   background-color: #f5f5f5;
@@ -522,6 +533,7 @@ a {
   .el-message-box__btns {
     margin-bottom: 10px;
     text-align: center;
+    justify-content: center;
     .el-button {
       width: 100px;
       height: 36px;
@@ -916,7 +928,7 @@ a {
 .el-date-editor.el-input,
 .el-date-editor.el-input__inner {
   width: 100%;
-  min-width: 120px;
+  min-width: 192px;
 }
 
 .el-select .el-input {

+ 1 - 0
src/styles/index.scss

@@ -1,5 +1,6 @@
 @import './variables.scss';
 @import './color.scss';
+@import './mixin.scss';
 @import './sidebar.scss';
 @import './transition.scss';
 @import './common.scss';

+ 16 - 0
src/styles/mixin.scss

@@ -0,0 +1,16 @@
+// 底部外边距
+@mixin marBot($width) {
+  margin-bottom: $width;
+}
+// 底部外边距
+@mixin marTop($width) {
+  margin-top: $width;
+}
+// 底部外边距
+@mixin marLeft($width) {
+  margin-left: $width;
+}
+// 底部外边距
+@mixin marRight($width) {
+  margin-right: $width;
+}

+ 4 - 5
src/views/card/CardOrder/index.vue

@@ -7,12 +7,13 @@
     element-loading-spinner="el-icon-loading"
   >
     <div class="crm_search">
-      <el-form ref="form" label-position="" :model="search" label-width="">
+      <el-form ref="formRef" :model="search" label-width="">
         <el-row>
           <el-col :span="24" :md="24" :lg="24">
             <el-form-item>
               <el-select
                 v-model="search.tag"
+                style="width: 140px; min-width: 140px"
                 class="crm_search_down crm-border-radius-no"
                 :placeholder="$t('Placeholder.Choose')"
               >
@@ -27,7 +28,6 @@
                 v-model.trim="search.cId"
                 class="crm-border-left-no crm-border-radius-no"
                 clearable
-                size="small"
                 :placeholder="$t('Placeholder.Input')"
                 @keyup.enter="toSearch"
               ></el-input>
@@ -351,7 +351,6 @@
   import { exportExcel } from '@/utils/export.js'
   import { useI18n } from 'vue-i18n'
   import { Search } from '@element-plus/icons-vue'
-  import { log } from 'echarts/types/src/util/log'
   // 混入
   const Session = inject('session')
   const pigeon = inject('pigeon')
@@ -371,6 +370,7 @@
     email: '',
     status: '',
   })
+  const formRef = ref()
   const editor = ref('')
   const addType = ref('')
   const myInfo = ref({})
@@ -566,6 +566,7 @@
   const searchFunc = async () => {
     pictLoading.value = true
     console.log(0)
+    console.log(display.value)
     if (!display.value['R-CardOrder-Search']?.show) {
       pigeon.MessageWarning(t('Msg.NotDisplay'))
       console.log(1)
@@ -581,7 +582,6 @@
           row: pagerInfo.row,
         },
       })
-      console.log(res, 2)
       if (res.code == Code.StatusOK) {
         mock_tableData.value = res.data
         if (res.page != null) {
@@ -590,7 +590,6 @@
         } else {
           pagerInfo.rowTotal = 0
         }
-        console.log(3)
         pigeon.MessageOK(t('Msg.SearchSuccess'))
       } else {
         pigeon.MessageError(res.msg)

+ 467 - 0
src/views/card/CardType/index.vue

@@ -0,0 +1,467 @@
+<template>
+  <div
+    id="review_Email"
+    v-loading="pictLoading"
+    class="view"
+    element-loading-background="rgba(43, 48, 67, 0.65)"
+    element-loading-spinner="el-icon-loading"
+  >
+    <div class="crm_search">
+      <el-form ref="formRef" label-position="" :model="search" label-width="">
+        <el-row>
+          <el-col :span="24" :md="24" :lg="24">
+            <el-form-item style="margin-right: 10px">
+              <el-input
+                v-model.trim="search.cardName"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="$t('Placeholder.Input') + $t('Ucard.CardType.s2')"
+                @keyup.enter="toSearch"
+              ></el-input>
+            </el-form-item>
+            <el-form-item style="margin-right: 10px">
+              <el-select
+                v-model="search.type"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="$t('Ucard.CardType.s1')"
+                @change="toSearch"
+              >
+                <el-option :label="$t('Ucard.CardType.t1')" value="Virtual"></el-option>
+                <el-option :label="$t('Ucard.CardType.t2')" value="Physical"></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item>
+              <el-select
+                v-model="search.status"
+                class="crm-border-radius-no"
+                clearable
+                :placeholder="$t('Ucard.CardType.s3')"
+                @change="toSearch"
+              >
+                <el-option :label="$t('Ucard.CardType.t5')" value="offline"></el-option>
+                <el-option :label="$t('Ucard.CardType.t6')" value="online"></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item>
+              <el-button class="crm-border-radius-no crm-border-left-no" @click="toSearch">
+                <el-icon><Search /></el-icon>
+              </el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item>
+          <div class="search_action_btn">
+            <span
+              v-if="display['R-CardType-Update']?.show"
+              class="crm-cursor"
+              @click="updateCardTypes"
+              ><span>{{ $t('Ucard.CardType.b1') }}</span></span
+            >
+          </div>
+        </el-form-item>
+      </el-form>
+
+      <div class="card-mock-demo" style="margin: 30px 0">
+        <el-table :data="mock_tableData" stripe style="margin-top: 20px; width: 100%">
+          <el-table-column prop="type" align="left" :label="$t('Ucard.CardType.item2')">
+          </el-table-column>
+          <el-table-column prop="cardName" align="left" :label="$t('Ucard.CardType.item4')" />
+          <el-table-column prop="cardDesc" align="left" :label="$t('Ucard.CardType.item5')" />
+          <el-table-column prop="needCardHolder" align="left" :label="$t('Ucard.CardType.item15')">
+            <template #default="scope">
+              <el-tag :type="scope.row.needCardHolder === true ? 'success' : 'info'">{{
+                scope.row.needCardHolder === true
+                  ? $t('Ucard.CardType.t7')
+                  : $t('Ucard.CardType.t8')
+              }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop="needDepositForActiveCard"
+            align="left"
+            :label="$t('Ucard.CardType.item16')"
+          >
+            <template #default="scope">
+              <el-tag :type="scope.row.needDepositForActiveCard === true ? 'success' : 'info'">{{
+                scope.row.needDepositForActiveCard === true
+                  ? $t('Ucard.CardType.t7')
+                  : $t('Ucard.CardType.t8')
+              }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column align="left" :label="$t('Ucard.CardType.item8')">
+            <template #default="scope">
+              <div>
+                {{ $t('Ucard.CardType.item9') }}: {{ scope.row.rechargeCurrency }},
+                {{ $t('Ucard.CardType.item10') }}: {{ scope.row.rechargeMinQuota }},
+                {{ $t('Ucard.CardType.item11') }}: {{ scope.row.rechargeMaxQuota }},
+                {{ $t('Ucard.CardType.item12') }}: {{ scope.row.rechargeDigital }},
+                {{ $t('card.CardType.item13') }}: {{ scope.row.rechargeFeeRate }} %,
+                {{ $t('card.CardType.item14') }}:
+                {{ scope.row.rechargeFixedFee }}
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column prop="status" align="left" :label="$t('Ucard.CardType.item7')">
+            <template #default="scope">
+              <el-tag :type="scope.row.status === 'online' ? 'success' : 'info'">{{
+                scope.row.status === 'online' ? $t('Ucard.CardType.t6') : $t('Ucard.CardType.t5')
+              }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="isContact" align="left" :label="$t('card.CardType.item15')">
+            <template #default="scope">
+              <el-tag :type="!scope.row.isContact ? 'info' : 'success'">{{
+                !scope.row.isContact ? $t('No') : $t('Yes')
+              }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column :label="$t('Ucard.Business.item20')" align="center">
+            <template #default="scope">
+              <el-dropdown trigger="click" @command="handleCommand">
+                <span class="el-dropdown-link crm-cursor">
+                  <i style="font-weight: bold; font-size: 20px" class="iconfont iconcaidan"></i>
+                </span>
+                <template #dropdown>
+                  <el-dropdown-menu>
+                    <el-dropdown-item
+                      v-if="display['R-CardType-Edit']?.show"
+                      :command="{ type: 1, row: scope.row }"
+                    >
+                      <i class="el-icon-edit"></i>
+                      <span>{{ $t('R-CardType-Edit') }}</span>
+                    </el-dropdown-item>
+                  </el-dropdown-menu>
+                </template>
+              </el-dropdown>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+    <div v-if="pagerInfo.rowTotal" class="crm_pagination">
+      <div class="crm_page_total">
+        <span>{{ $t('Page.total.item1') }}</span>
+        <span>{{ pagerInfo.rowTotal }}</span>
+        <span>{{ $t('Page.total.item2') }}</span>
+      </div>
+      <el-pagination
+        class="page"
+        background
+        layout="sizes, prev, pager, next"
+        :page-sizes="[10, 20, 50, 100]"
+        :page-size="pagerInfo.row"
+        :total="pagerInfo.rowTotal"
+        @current-change="handleCurrentChange"
+        @size-change="handleSizeChange"
+      >
+      </el-pagination>
+    </div>
+    <el-dialog
+      v-if="approvalAllDialog"
+      v-model="approvalAllDialog"
+      :title="$t('R-CardType-Edit')"
+      width="900px"
+    >
+      <el-form
+        ref="formDialogRef"
+        :rules="rules"
+        :model="form"
+        label-width="130px"
+        label-position="right"
+        class="business-edit-form"
+      >
+        <el-form-item prop="cardName" :label="$t('card.CardType.item4')">
+          <el-input v-model="form.cardName" :placeholder="$t('Placeholder.Input')" />
+        </el-form-item>
+        <el-form-item prop="cardDesc" :label="$t('card.CardType.item5')">
+          <el-input
+            v-model="form.cardDesc"
+            type="textarea"
+            :autosize="{ minRows: 2, maxRows: 10 }"
+            :placeholder="$t('Placeholder.Input')"
+          />
+        </el-form-item>
+        <el-form-item prop="rechargeMinQuota" :label="$t('card.CardType.item10')">
+          <el-input v-model="form.rechargeMinQuota" :placeholder="$t('Placeholder.Input')" />
+        </el-form-item>
+        <el-form-item prop="rechargeMaxQuota" :label="$t('card.CardType.item11')">
+          <el-input v-model="form.rechargeMaxQuota" :placeholder="$t('Placeholder.Input')" />
+        </el-form-item>
+        <el-form-item prop="rechargeDigital" :label="$t('card.CardType.item12')">
+          <el-input v-model="form.rechargeDigital" :placeholder="$t('Placeholder.Input')" />
+        </el-form-item>
+        <el-form-item prop="rechargeFeeRate" :label="$t('card.CardType.item13')">
+          <el-input v-model="form.rechargeFeeRate" :placeholder="$t('Placeholder.Input')" />
+        </el-form-item>
+        <el-form-item prop="rechargeFixedFee" :label="$t('card.CardType.item14')">
+          <el-input v-model="form.rechargeFixedFee" :placeholder="$t('Placeholder.Input')" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="approvalAllDialog = false"
+            ><span>{{ $t('Ucard.Business.p32') }}</span></el-button
+          >
+          <el-button type="primary" @click="updateCardTypesConfig">{{
+            $t('card.Btn.Confirm')
+          }}</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+  import { ref, reactive, computed, onMounted, watch, inject } from 'vue'
+  import Service from '@/service/ucard'
+  import Config from '@/config/index'
+  import { useI18n } from 'vue-i18n'
+  import { Search } from '@element-plus/icons-vue'
+
+  const { Code } = Config
+  const pigeon = inject('pigeon')
+  const Session = inject('session')
+  const { t } = useI18n()
+
+  // 响应式数据
+  const pictLoading = ref(false)
+  const formRef = ref(null)
+  const formDialogRef = ref(null)
+  const approvalAllDialog = ref(false)
+
+  const search = reactive({
+    tag: 1,
+    type: '',
+    cardName: '',
+    status: '',
+  })
+
+  const form = reactive({
+    cardTypeId: null,
+    cardName: null,
+    cardDesc: null,
+    bankCardBin: null,
+    rechargeMinQuota: null,
+    rechargeMaxQuota: null,
+    rechargeDigital: null,
+    rechargeFeeRate: null,
+    rechargeFixedFee: null,
+  })
+
+  const rules = reactive({
+    cardName: [
+      {
+        required: true,
+        message: t('Placeholder.Input'),
+        trigger: 'blur',
+      },
+    ],
+    cardDesc: [
+      {
+        required: true,
+        message: t('Placeholder.Input'),
+        trigger: 'blur',
+      },
+    ],
+    rechargeMinQuota: [
+      {
+        required: true,
+        message: t('Placeholder.Input'),
+        trigger: 'blur',
+      },
+    ],
+    rechargeMaxQuota: [
+      {
+        required: true,
+        message: t('Placeholder.Input'),
+        trigger: 'blur',
+      },
+    ],
+    rechargeDigital: [
+      {
+        required: true,
+        message: t('Placeholder.Input'),
+        trigger: 'blur',
+      },
+    ],
+    rechargeFeeRate: [
+      {
+        required: true,
+        message: t('Placeholder.Input'),
+        trigger: 'blur',
+      },
+    ],
+    rechargeFixedFee: [
+      {
+        required: true,
+        message: t('Placeholder.Input'),
+        trigger: 'blur',
+      },
+    ],
+  })
+
+  const mock_tableData = ref([])
+  const pagerInfo = reactive({
+    row: 10,
+    current: 1,
+    pageTotal: 0,
+    rowTotal: 0,
+  })
+
+  // 计算属性
+  const display = computed(() => {
+    return JSON.parse(Session.Get('display', true) || '{}')
+  })
+
+  // 方法
+  const updateCardTypesConfig = async () => {
+    try {
+      if (!formDialogRef.value) return
+
+      const valid = await formDialogRef.value.validate()
+      console.log(valid, 198)
+
+      if (!valid) return
+      let res = await Service.updateCardTypesConfig({ ...form })
+      if (res.code == 200) {
+        Object.assign(form, {
+          cardTypeId: null,
+          cardName: null,
+          cardDesc: null,
+          bankCardBin: null,
+          rechargeMinQuota: null,
+          rechargeMaxQuota: null,
+          rechargeDigital: null,
+          rechargeFeeRate: null,
+          rechargeFixedFee: null,
+        })
+        approvalAllDialog.value = false
+        toSearch()
+      } else {
+        pigeon.MessageError(res.msg)
+      }
+    } catch (error) {
+      console.log(error)
+    }
+  }
+
+  const handleCommand = (command) => {
+    switch (command.type) {
+      case 1: {
+        Object.assign(form, {
+          ...command.row,
+        })
+        console.log(form, command.row)
+        approvalAllDialog.value = true
+        break
+      }
+    }
+  }
+
+  const toSearch = () => {
+    pagerInfo.current = 1
+    searchFunc()
+  }
+
+  const updateCardTypes = async () => {
+    let res = await Service.updateCardTypes({})
+    if (res.code == Code.StatusOK) {
+      pigeon.MessageOK(t('Msg.SearchSuccess'))
+      searchFunc()
+    } else {
+      pigeon.MessageError(res.msg)
+    }
+  }
+
+  const searchFunc = async () => {
+    pictLoading.value = true
+    if (!display.value['R-CardType-Search']?.show) {
+      pigeon.MessageWarning(t('Msg.NotDisplay'))
+      pictLoading.value = false
+      return
+    }
+    let res = await Service.cardTypesList({
+      ...search,
+      page: {
+        current: pagerInfo.current,
+        row: pagerInfo.row,
+      },
+    })
+    if (res.code == Code.StatusOK) {
+      mock_tableData.value = res.data
+      if (res.page != null) {
+        pagerInfo.rowTotal = res.page.rowTotal
+        pagerInfo.pageTotal = res.page.pageTotal
+      } else {
+        pagerInfo.rowTotal = 0
+      }
+      pigeon.MessageOK(t('Msg.SearchSuccess'))
+    } else {
+      pigeon.MessageError(res.msg)
+    }
+    pictLoading.value = false
+  }
+
+  const handleSizeChange = (val) => {
+    pagerInfo.row = val
+    searchFunc()
+  }
+
+  const handleCurrentChange = (val) => {
+    pagerInfo.current = val
+    searchFunc()
+  }
+
+  // 生命周期
+  onMounted(() => {
+    searchFunc()
+  })
+
+  // 监听器
+  watch(
+    () => search.tag,
+    () => {
+      search.type = ''
+      search.cardName = ''
+      search.status = ''
+    }
+  )
+</script>
+
+<style scoped lang="scss">
+  #review_Email {
+    .crm_search {
+      .search_action_btn {
+        .delete {
+          background-color: #a1a1a1;
+        }
+
+        .delete.active {
+          background-color: #368fec;
+        }
+      }
+    }
+
+    .el-table .state {
+      display: inline-block;
+      min-width: 80px;
+      max-width: 150px;
+      box-sizing: border-box;
+      line-height: 1.5;
+      border-radius: 2px;
+      padding: 2px 10px;
+      color: #ffffff;
+    }
+  }
+</style>
+<style lang="scss">
+  #review_Email {
+    .dialog_header_w {
+      .crm_search_down {
+        width: 400px;
+      }
+    }
+  }
+</style>

+ 27 - 18
src/views/home2/Home.vue

@@ -27,7 +27,7 @@
             <el-dropdown trigger="click" class="language">
               <span class="el-dropdown-link">
                 <span>{{ langName }}</span
-                ><i class="el-icon-arrow-down el-icon--right"></i>
+                ><el-icon><ArrowDown /></el-icon>
               </span>
               <template #dropdown>
                 <el-dropdown-menu>
@@ -39,7 +39,7 @@
             <el-dropdown v-if="info.roteCode == 'ROLE_SALE'" trigger="click" class="role-switch">
               <span class="el-dropdown-link">
                 <span>{{ currentRoleName }}</span
-                ><i class="el-icon-arrow-down el-icon--right"></i>
+                ><el-icon><ArrowDown /></el-icon>
               </span>
               <template #dropdown>
                 <el-dropdown-menu>
@@ -55,12 +55,14 @@
                 </el-dropdown-menu>
               </template>
             </el-dropdown>
-            <i class="crm-cursor el-icon-bell icon" style="font-size: 20px"></i>
+            <el-icon class="crm-cursor" style="font-size: 20px; margin-left: 20px"
+              ><Bell
+            /></el-icon>
             <i class="crm-cursor iconquanping iconfont icon" @click="fullScreen"></i>
             <el-dropdown trigger="click" class="username crm-cursor">
               <span class="el-dropdown-link">
                 <span>{{ user.name || 'UserName' }}</span
-                ><i class="el-icon-arrow-down el-icon--right"></i>
+                ><el-icon><ArrowDown /></el-icon>
               </span>
               <template #dropdown>
                 <el-dropdown-menu>
@@ -98,10 +100,11 @@
 
     <!-- 修改密码弹出 -->
     <el-dialog
-      v-model:visible="dialogCheck"
+      key="pwd"
+      v-model="dialogCheck"
       :title="$t('Label.UpdatePwd')"
       center
-      custom-class="dialog_header_w"
+      class="dialog_header_w"
     >
       <div class="dia-content">
         <el-form
@@ -111,17 +114,20 @@
           label-width="135px"
           class="dialogCheck_form"
         >
-          <el-form-item prop="oldPassword" :label="$t('Label.oldPwd') + ':'">
+          <el-form-item
+            prop="oldPassword"
+            size="large"
+            class="mb30"
+            :label="$t('Label.oldPwd') + ':'"
+          >
             <el-input
               v-model.trim="dialogCheck_form.oldPassword"
-              size="small"
               :placeholder="$t('Placeholder.Input')"
             ></el-input>
           </el-form-item>
-          <el-form-item prop="newPassword" :label="$t('Label.newPwd') + ':'">
+          <el-form-item size="large" prop="newPassword" :label="$t('Label.newPwd') + ':'">
             <el-input
               v-model.trim="dialogCheck_form.newPassword"
-              size="small"
               :placeholder="$t('Placeholder.Input')"
             ></el-input>
           </el-form-item>
@@ -187,9 +193,9 @@
   import { useI18n } from 'vue-i18n'
 
   // 组件导入
-  import NavMenu from '@/components/NavMenu'
-  import BreadCrumb from '@/components/BreadCrumb'
-  import TabMenu from '@/components/TabMenu'
+  import NavMenu from '@/components/NavMenu.vue'
+  import BreadCrumb from '@/components/BreadCrumb.vue'
+  import TabMenu from '@/components/TabMenu.vue'
   // import QaList from './global/QAList'
   // import QaAdd from './global/QAAdd'
   import Service from '@/service/login'
@@ -270,6 +276,7 @@
   const initDisplay = () => {
     let display = {}
     const userData = safeGetUser(session)
+    console.log(userData, 'userData')
     if (userData && userData.display) {
       userData.display.forEach((item) => {
         item.children.forEach((item1) => {
@@ -440,12 +447,13 @@
     store.commit('ChangeLanguage', lang)
     axios.defaults.headers.common['Language'] = lang
     setTimeout(() => {
-      reload()
+      // reload()
     }, 800)
   }
 
   // 修改密码
   const updatePwd = () => {
+    console.log('updatePwd')
     dialogCheck.value = true
   }
 
@@ -549,7 +557,7 @@
       pigeon.MessageOK(t('Msg.LoginSuccess'))
       setTimeout(() => {
         loading.value = false
-        reload()
+        // reload()
         router.push({ path: '/' }).catch((arr) => arr)
       }, 1000)
     } else {
@@ -602,10 +610,11 @@
       info.value = {}
     }
   })
-  onMounted(() => {
-    // 初始化权限
+  onBeforeMount(() => {
+    // 初始化权限  需要在初始化之前处理,不然下面页面拿不到数据
     initDisplay()
-
+  })
+  onMounted(() => {
     // 初始化侧边栏状态
     isCollapse.value = session.Get('isCollapse', false) === 'true'
     InitLanguage()

+ 7 - 8
src/views/login/User.vue

@@ -8,13 +8,13 @@
           </div>
           <div class="menu-logo chooseLang crm-cursor">
             <img
-              v-if="langList[language] == 'ENGLISH'"
+              v-show="langList[language] == 'ENGLISH'"
               style="width: 15px; height: 10px; margin: 0 4px"
               :src="icon_en"
               alt
             />
             <img
-              v-if="langList[language] == '中文简体'"
+              v-show="langList[language] == '中文简体'"
               style="width: 15px; height: 10px; margin: 0 4px"
               :src="icon_cn"
               alt
@@ -56,9 +56,9 @@
   import icon_en from '@/assets/image/login/EN.jpg'
   import { log } from 'echarts/types/src/util/log'
 
-  const { proxy } = getCurrentInstance()
   // 注入 reload 方法
   const reload = inject('reload')
+  const session = inject('session')
   const store = useStore()
   const { locale } = useI18n()
 
@@ -84,7 +84,7 @@
     }
   }
   const initLanguage = () => {
-    const savedLang = sessionStorage.getItem('lang')
+    const savedLang = session.Get('lang')
 
     if (savedLang) {
       setLanguage(savedLang)
@@ -98,21 +98,20 @@
   }
 
   const setLanguage = (lang) => {
-    console.log(locale)
     locale.value = language.value = lang
     axios.defaults.headers.common['Language'] = lang
   }
 
   const chooseLang = async (key) => {
     setLanguage(key)
-    sessionStorage.setItem('lang', key)
+    session.Set('lang', key)
 
     // 调用后端语言切换
-    await switchLanguage(key)
+    // await switchLanguage(key)
 
     // 延迟重载页面
     setTimeout(() => {
-      reload?.()
+      // reload()
     }, 500)
   }
 

+ 2 - 1
src/views/login/index.scss

@@ -42,9 +42,10 @@
   }
   .getCode {
     margin-top: 15px;
-    padding: 6px 20px;
+    padding: 0 20px;
     border: 1px solid;
     border-radius: 4px;
+    line-height: 32px;
     cursor: pointer;
     user-select: none;
     white-space: nowrap;

+ 5 - 1
src/views/login/index.vue

@@ -69,7 +69,11 @@
                   </template>
                 </el-input>
               </el-col>
-              <el-col :span="9" :push="1" style="display: flex; justify-content: center">
+              <el-col
+                :span="9"
+                :push="1"
+                style="display: flex; justify-content: center; align-items: center"
+              >
                 <span class="getCode" @click="getCode(1)" v-text="getCodeString"></span>
               </el-col>
             </el-row>

Vissa filer visades inte eftersom för många filer har ändrats