Parcourir la source

固定横向展示及添加侧边栏固定列表操作栏

yangg il y a 11 mois
Parent
commit
bda737fbb1

+ 35 - 0
src/components/MenuItem.vue

@@ -0,0 +1,35 @@
+<template>
+    <li>
+      <div @click="toggle">{{ item.label }}</div>
+      <ul v-if="isOpen">
+        <MenuItem v-for="child in item.children" :key="child.id" :item="child" />
+      </ul>
+    </li>
+  </template>
+  
+  <script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  
+  export default defineComponent({
+    name: 'MenuItem',
+    props: {
+      item: {
+        type: Object as () => { id: number; label: string; children?: any[] },
+        required: true,
+      },
+    },
+    setup() {
+      const isOpen = ref(false);
+      const toggle = () => {
+        isOpen.value = !isOpen.value;
+      };
+      return { isOpen, toggle };
+    },
+  });
+  </script>
+  
+  <style scoped>
+  li {
+    cursor: pointer;
+  }
+  </style>

+ 1 - 1
src/components/layout/Footer.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="dark:text-white-dark text-center ltr:sm:text-left rtl:sm:text-right p-6 pt-0 mt-auto">
+    <div class="dark:text-white-dark text-center  rtl:sm:text-right p-6 pt-0 mt-auto "><!-- ltr:sm:text-left -->
         © {{ new Date().getFullYear() }}. Raycos All rights reserved.
     </div>
 </template>

+ 3 - 3
src/components/layout/Header.vue

@@ -21,9 +21,8 @@
 
         <!-- 头部中间功能--待开发 -->
         <div class="ltr:mr-2 rtl:ml-2 hidden sm:block">
-          <ul class="flex items-center space-x-2 rtl:space-x-reverse dark:text-[#d0d2d6]">
+          <!-- <ul class="flex items-center space-x-2 rtl:space-x-reverse dark:text-[#d0d2d6]">
             <li>
-              <!--   to="/apps/calendar" -->
               <router-link
                 to=""
                 class="block p-2 rounded-full bg-white-light/40 dark:bg-dark/40 hover:text-primary hover:bg-white-light/90 dark:hover:bg-dark/60"
@@ -47,7 +46,7 @@
                 <icon-chat-notification />
               </router-link>
             </li>
-          </ul>
+          </ul> -->
         </div>
         <!-- items-center -->
         <div class="sm:flex-1 ltr:sm:ml-0 ltr:ml-auto sm:rtl:mr-0 rtl:mr-auto flex space-x-1.5 lg:space-x-2 rtl:space-x-reverse dark:text-[#d0d2d6]">
@@ -252,6 +251,7 @@
         </div>
       </div>
       <ul
+      style="box-shadow: 0 0px 0px #ccc;"
         class="horizontal-menu hidden py-1.5 font-semibold px-6 lg:space-x-1.5 xl:space-x-8 rtl:space-x-reverse bg-white border-t border-[#ebedf2] dark:border-[#191e3a] dark:bg-[#0e1726] text-black dark:text-white-dark"
       >
         <li class="menu nav-item relative">

+ 436 - 83
src/layouts/app-layout.vue

@@ -1,106 +1,459 @@
 <template>
-    <!--  BEGIN MAIN CONTAINER  -->
-      <!-- <div>112</div> -->
-    <div class="relative">
-        <!-- sidebar menu overlay -->
-        <div class="fixed inset-0 bg-[black]/60 z-50 lg:hidden" :class="{ hidden: !store.state.sidebar }"
-            @click="toggleSidebar"></div>
-
-        <!-- screen loader -->
-        <div v-show="store.state.isShowMainLoader"
-            class="screen_loader fixed inset-0 bg-[#fafafa] dark:bg-[#060818] z-[60] grid place-content-center animate__animated">
-            <svg width="64" height="64" viewBox="0 0 135 135" xmlns="http://www.w3.org/2000/svg" fill="#4361ee">
-                <path
-                    d="M67.447 58c5.523 0 10-4.477 10-10s-4.477-10-10-10-10 4.477-10 10 4.477 10 10 10zm9.448 9.447c0 5.523 4.477 10 10 10 5.522 0 10-4.477 10-10s-4.478-10-10-10c-5.523 0-10 4.477-10 10zm-9.448 9.448c-5.523 0-10 4.477-10 10 0 5.522 4.477 10 10 10s10-4.478 10-10c0-5.523-4.477-10-10-10zM58 67.447c0-5.523-4.477-10-10-10s-10 4.477-10 10 4.477 10 10 10 10-4.477 10-10z">
-                    <animateTransform attributeName="transform" type="rotate" from="0 67 67" to="-360 67 67" dur="2.5s"
-                        repeatCount="indefinite" />
-                </path>
-                <path
-                    d="M28.19 40.31c6.627 0 12-5.374 12-12 0-6.628-5.373-12-12-12-6.628 0-12 5.372-12 12 0 6.626 5.372 12 12 12zm30.72-19.825c4.686 4.687 12.284 4.687 16.97 0 4.686-4.686 4.686-12.284 0-16.97-4.686-4.687-12.284-4.687-16.97 0-4.687 4.686-4.687 12.284 0 16.97zm35.74 7.705c0 6.627 5.37 12 12 12 6.626 0 12-5.373 12-12 0-6.628-5.374-12-12-12-6.63 0-12 5.372-12 12zm19.822 30.72c-4.686 4.686-4.686 12.284 0 16.97 4.687 4.686 12.285 4.686 16.97 0 4.687-4.686 4.687-12.284 0-16.97-4.685-4.687-12.283-4.687-16.97 0zm-7.704 35.74c-6.627 0-12 5.37-12 12 0 6.626 5.373 12 12 12s12-5.374 12-12c0-6.63-5.373-12-12-12zm-30.72 19.822c-4.686-4.686-12.284-4.686-16.97 0-4.686 4.687-4.686 12.285 0 16.97 4.686 4.687 12.284 4.687 16.97 0 4.687-4.685 4.687-12.283 0-16.97zm-35.74-7.704c0-6.627-5.372-12-12-12-6.626 0-12 5.373-12 12s5.374 12 12 12c6.628 0 12-5.373 12-12zm-19.823-30.72c4.687-4.686 4.687-12.284 0-16.97-4.686-4.686-12.284-4.686-16.97 0-4.687 4.686-4.687 12.284 0 16.97 4.686 4.687 12.284 4.687 16.97 0z">
-                    <animateTransform attributeName="transform" type="rotate" from="0 67 67" to="360 67 67" dur="8s"
-                        repeatCount="indefinite" />
-                </path>
-            </svg>
-        </div>
+  <!--  BEGIN MAIN CONTAINER  -->
+  <!-- <div>112</div> -->
+  <div class="relative">
+    <!-- sidebar menu overlay -->
+    <div class="fixed inset-0 bg-[black]/60 z-50 lg:hidden" :class="{ hidden: !store.state.sidebar }" @click="toggleSidebar"></div>
 
-        <div class="fixed bottom-6 ltr:right-6 rtl:left-6 z-50">
-            <template v-if="showTopButton">
-                <button type="button"
-                    class="btn btn-outline-primary rounded-full p-2 animate-pulse bg-[#fafafa] dark:bg-[#060818] dark:hover:bg-primary"
-                    @click="goToTop">
-                    <svg width="24" height="24" class="h-4 w-4" viewBox="0 0 24 24" fill="none"
-                        xmlns="http://www.w3.org/2000/svg">
-                        <path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
-                            d="M12 20.75C12.4142 20.75 12.75 20.4142 12.75 20L12.75 10.75L11.25 10.75L11.25 20C11.25 20.4142 11.5858 20.75 12 20.75Z"
-                            fill="currentColor" />
-                        <path
-                            d="M6.00002 10.75C5.69667 10.75 5.4232 10.5673 5.30711 10.287C5.19103 10.0068 5.25519 9.68417 5.46969 9.46967L11.4697 3.46967C11.6103 3.32902 11.8011 3.25 12 3.25C12.1989 3.25 12.3897 3.32902 12.5304 3.46967L18.5304 9.46967C18.7449 9.68417 18.809 10.0068 18.6929 10.287C18.5768 10.5673 18.3034 10.75 18 10.75L6.00002 10.75Z"
-                            fill="currentColor" />
-                    </svg>
-                </button>
-            </template>
-        </div>
+    <!-- screen loader -->
+    <div
+      v-show="store.state.isShowMainLoader"
+      class="screen_loader fixed inset-0 bg-[#fafafa] dark:bg-[#060818] z-[60] grid place-content-center animate__animated"
+    >
+      <svg width="64" height="64" viewBox="0 0 135 135" xmlns="http://www.w3.org/2000/svg" fill="#4361ee">
+        <path
+          d="M67.447 58c5.523 0 10-4.477 10-10s-4.477-10-10-10-10 4.477-10 10 4.477 10 10 10zm9.448 9.447c0 5.523 4.477 10 10 10 5.522 0 10-4.477 10-10s-4.478-10-10-10c-5.523 0-10 4.477-10 10zm-9.448 9.448c-5.523 0-10 4.477-10 10 0 5.522 4.477 10 10 10s10-4.478 10-10c0-5.523-4.477-10-10-10zM58 67.447c0-5.523-4.477-10-10-10s-10 4.477-10 10 4.477 10 10 10 10-4.477 10-10z"
+        >
+          <animateTransform attributeName="transform" type="rotate" from="0 67 67" to="-360 67 67" dur="2.5s" repeatCount="indefinite" />
+        </path>
+        <path
+          d="M28.19 40.31c6.627 0 12-5.374 12-12 0-6.628-5.373-12-12-12-6.628 0-12 5.372-12 12 0 6.626 5.372 12 12 12zm30.72-19.825c4.686 4.687 12.284 4.687 16.97 0 4.686-4.686 4.686-12.284 0-16.97-4.686-4.687-12.284-4.687-16.97 0-4.687 4.686-4.687 12.284 0 16.97zm35.74 7.705c0 6.627 5.37 12 12 12 6.626 0 12-5.373 12-12 0-6.628-5.374-12-12-12-6.63 0-12 5.372-12 12zm19.822 30.72c-4.686 4.686-4.686 12.284 0 16.97 4.687 4.686 12.285 4.686 16.97 0 4.687-4.686 4.687-12.284 0-16.97-4.685-4.687-12.283-4.687-16.97 0zm-7.704 35.74c-6.627 0-12 5.37-12 12 0 6.626 5.373 12 12 12s12-5.374 12-12c0-6.63-5.373-12-12-12zm-30.72 19.822c-4.686-4.686-12.284-4.686-16.97 0-4.686 4.687-4.686 12.285 0 16.97 4.686 4.687 12.284 4.687 16.97 0 4.687-4.685 4.687-12.283 0-16.97zm-35.74-7.704c0-6.627-5.372-12-12-12-6.626 0-12 5.373-12 12s5.374 12 12 12c6.628 0 12-5.373 12-12zm-19.823-30.72c4.687-4.686 4.687-12.284 0-16.97-4.686-4.686-12.284-4.686-16.97 0-4.687 4.686-4.687 12.284 0 16.97 4.686 4.687 12.284 4.687 16.97 0z"
+        >
+          <animateTransform attributeName="transform" type="rotate" from="0 67 67" to="360 67 67" dur="8s" repeatCount="indefinite" />
+        </path>
+      </svg>
+    </div>
+
+    <div class="fixed bottom-6 ltr:right-6 rtl:left-6 z-50">
+      <template v-if="showTopButton">
+        <button
+          type="button"
+          class="btn btn-outline-primary rounded-full p-2 animate-pulse bg-[#fafafa] dark:bg-[#060818] dark:hover:bg-primary"
+          @click="goToTop"
+        >
+          <svg width="24" height="24" class="h-4 w-4" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+            <path
+              opacity="0.5"
+              fill-rule="evenodd"
+              clip-rule="evenodd"
+              d="M12 20.75C12.4142 20.75 12.75 20.4142 12.75 20L12.75 10.75L11.25 10.75L11.25 20C11.25 20.4142 11.5858 20.75 12 20.75Z"
+              fill="currentColor"
+            />
+            <path
+              d="M6.00002 10.75C5.69667 10.75 5.4232 10.5673 5.30711 10.287C5.19103 10.0068 5.25519 9.68417 5.46969 9.46967L11.4697 3.46967C11.6103 3.32902 11.8011 3.25 12 3.25C12.1989 3.25 12.3897 3.32902 12.5304 3.46967L18.5304 9.46967C18.7449 9.68417 18.809 10.0068 18.6929 10.287C18.5768 10.5673 18.3034 10.75 18 10.75L6.00002 10.75Z"
+              fill="currentColor"
+            />
+          </svg>
+        </button>
+      </template>
+    </div>
+
+    <!-- BEGIN APP SETTING LAUNCHER -->
+    <Setting />
+    <!-- END APP SETTING LAUNCHER -->
+
+    <div class="main-container text-black dark:text-white-dark min-h-screen" :class="[store.state.navbar]">
+      <!--  BEGIN SIDEBAR  -->
+      <Sidebar />
+      <!--  END SIDEBAR  -->
+
+      <div class="main-content flex flex-col min-h-screen">
+        <!--  BEGIN TOP NAVBAR  -->
+        <Header />
+        <!--  END TOP NAVBAR  -->
+
+        <!--  BEGIN CONTENT AREA  -->
+        <div class="p-4 animation" :class="sidebarShow? 'ml-64':'ml-0'">
+          <!--侧边栏 -->
+          <div :class="{ 'dark text-white-dark': store.state.semidark }">
+            <!-- z-50 top-32-->
+            <nav
+              class="sidebar  fixed min-h-screen h-full bottom-0 w-[260px] shadow-[5px_0_25px_0_rgba(94,92,154,0.1)] transition-all duration-300"
+              :class="sidebarShow? '!left-0':''"
+              style="top: 120px"
+            >
+              <!-- mt-5 -->
+              <div class="bg-white dark:bg-[#0e1726] h-full">
+                <div class="flex justify-between items-center px-2 py-1"></div>
+                <perfect-scrollbar
+                  v-if="superMenu == 'super'"
+                  :options="{
+                    swipeEasing: true,
+                    wheelPropagation: false,
+                  }"
+                  class="h-[calc(100vh-80px)] relative"
+                >
+                  <ul class="relative font-semibold space-y-0.5 p-4 py-0">
+                    <li class="menu nav-item">
+                      <button
+                        type="button"
+                        class="nav-link group w-full"
+                        :class="{ active: activeDropdown === 'package' }"
+                        @click="activeDropdown === 'package' ? (activeDropdown = null) : (activeDropdown = 'package')"
+                      >
+                        <div class="flex items-center">
+                          <icon-menu-users class="group-hover:!text-primary shrink-0" />
+
+                          <span class="ltr:pl-3 rtl:pr-3 text-black dark:text-[#506690] dark:group-hover:text-white-dark">{{ $t('package') }}</span>
+                        </div>
+                        <div :class="{ 'rtl:rotate-90 -rotate-90': activeDropdown == 'package' }">
+                          <icon-caret-down />
+                        </div>
+                      </button>
+                      <vue-collapsible :isOpen="activeDropdown === 'package'">
+                        <ul class="sub-menu text-gray-500">
+                          <li>
+                            <router-link to="/package/packageList" @click="toggleMobileMenu">{{ $t('packageList') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/package/packagePermissions" @click="toggleMobileMenu">{{ $t('packagePermissions') }}</router-link>
+                          </li>
+                        </ul>
+                      </vue-collapsible>
+                      <vue-collapsible :isOpen="activeDropdown === 'package'">
+                        <ul class="sub-menu text-gray-500"></ul>
+                      </vue-collapsible>
+                    </li>
+                    <li class="menu nav-item">
+                      <button
+                        type="button"
+                        class="nav-link group w-full"
+                        :class="{ active: activeDropdown === 'templateManage' }"
+                        @click="activeDropdown === 'templateManage' ? (activeDropdown = null) : (activeDropdown = 'templateManage')"
+                      >
+                        <div class="flex items-center">
+                          <icon-menu-users class="group-hover:!text-primary shrink-0" />
+
+                          <span class="ltr:pl-3 rtl:pr-3 text-black dark:text-[#506690] dark:group-hover:text-white-dark">{{ $t('templateManage') }}</span>
+                        </div>
+                        <div :class="{ 'rtl:rotate-90 -rotate-90': activeDropdown == 'templateManage' }">
+                          <icon-caret-down />
+                        </div>
+                      </button>
+                      <vue-collapsible :isOpen="activeDropdown === 'templateManage'">
+                        <ul class="sub-menu text-gray-500">
+                          <li>
+                            <router-link to="/templateManage/smsTemplate" @click="toggleMobileMenu">{{ $t('smsTemplate') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/templateManage/emailtemplate" @click="toggleMobileMenu">{{ $t('emailtemplate') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/templateManage/accountTemplate" @click="toggleMobileMenu">{{ $t('accountTemplate') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/templateManage/systemMessage" @click="toggleMobileMenu">{{ $t('systemMessage') }}</router-link>
+                          </li>
+                        </ul>
+                      </vue-collapsible>
+                      <vue-collapsible :isOpen="activeDropdown === 'package'">
+                        <ul class="sub-menu text-gray-500"></ul>
+                      </vue-collapsible>
+                    </li>
+                    <li class="menu nav-item">
+                      <button
+                        type="button"
+                        class="nav-link group w-full"
+                        :class="{ active: activeDropdown === 'users' }"
+                        @click="activeDropdown === 'users' ? (activeDropdown = null) : (activeDropdown = 'users')"
+                      >
+                        <div class="flex items-center">
+                          <icon-menu-users class="group-hover:!text-primary shrink-0" />
 
-        <!-- BEGIN APP SETTING LAUNCHER -->
-        <Setting />
-        <!-- END APP SETTING LAUNCHER -->
-
-        <div class="main-container text-black dark:text-white-dark min-h-screen" :class="[store.state.navbar]">
-            <!--  BEGIN SIDEBAR  -->
-            <Sidebar />
-            <!--  END SIDEBAR  -->
-
-            <div class="main-content flex flex-col min-h-screen">
-                <!--  BEGIN TOP NAVBAR  -->
-                <Header />
-                <!--  END TOP NAVBAR  -->
-
-                <!--  BEGIN CONTENT AREA  -->
-                <div class="p-4 animation">
-                    <router-view></router-view>
-                </div>
-                <!--  END CONTENT AREA  -->
-
-                <!-- BEGIN FOOTER -->
-                <Footer />
-                <!-- END FOOTER -->
-            </div>
+                          <span class="ltr:pl-3 rtl:pr-3 text-black dark:text-[#506690] dark:group-hover:text-white-dark">{{ $t('setting') }}</span>
+                        </div>
+                        <div :class="{ 'rtl:rotate-90 -rotate-90': activeDropdown == 'users' }">
+                          <icon-caret-down />
+                        </div>
+                      </button>
+                      <vue-collapsible :isOpen="activeDropdown === 'users'">
+                        <ul class="sub-menu text-gray-500">
+                          <li>
+                            <router-link to="/setting/companyList" @click="toggleMobileMenu">{{ $t('companyList') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/setting/dicData" @click="toggleMobileMenu">{{ $t('dicData') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/setting/menuManage" @click="toggleMobileMenu">{{ $t('menuManage') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/setting/express" @click="toggleMobileMenu">{{ $t('express') }}</router-link>
+                          </li>
+                          <!-- express -->
+                        </ul>
+                      </vue-collapsible>
+                      <vue-collapsible :isOpen="activeDropdown === 'users'">
+                        <ul class="sub-menu text-gray-500"></ul>
+                      </vue-collapsible>
+                    </li>
+                  </ul>
+                </perfect-scrollbar>
+                <perfect-scrollbar
+                  v-if="superMenu == 'compan'"
+                  :options="{
+                    swipeEasing: true,
+                    wheelPropagation: false,
+                  }"
+                  class="h-[calc(100vh-80px)] relative"
+                >
+                  <ul class="relative font-semibold space-y-0.5 p-4 py-0">
+                    <li class="menu nav-item">
+                      <button
+                        type="button"
+                        class="nav-link group w-full"
+                        :class="{ active: activeDropdown === 'dashboard' }"
+                        @click="activeDropdown === 'dashboard' ? (activeDropdown = null) : (activeDropdown = 'dashboard')"
+                      >
+                        <div class="flex items-center">
+                          <!-- <icon-menu-dashboard class="group-hover:!text-primary shrink-0" /> -->
+                          <span class="ltr:pl-3 rtl:pr-3 text-black dark:text-[#506690] dark:group-hover:text-white-dark">
+                            {{ $t('warehouse') }}
+                          </span>
+                        </div>
+                        <div :class="{ 'rtl:rotate-90 -rotate-90': activeDropdown == 'dashboard' }">
+                          <icon-caret-down />
+                        </div>
+                      </button>
+                      <vue-collapsible :isOpen="true"
+                        ><!-- -->
+                        <ul class="sub-menu text-gray-500">
+                          <li>
+                            <router-link to="/stock/warehouseList" @click="toggleMobileMenu">{{ $t('warehouseList') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/warehouseLocation" @click="toggleMobileMenu">{{ $t('warehouseLocation') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/goodsLend" @click="toggleMobileMenu">{{ $t('goodsLend') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/goodsTransfer" @click="toggleMobileMenu">{{ $t('goodsTransfer') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/goodsExchange" @click="toggleMobileMenu">{{ $t('goodsExchange') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/goodsOutBound" @click="toggleMobileMenu">{{ $t('goodsOutBound') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/goodsInventory" @click="toggleMobileMenu">{{ $t('goodsInventory') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/goodsInventoryLoss" @click="toggleMobileMenu">{{ $t('goodsInventoryLoss') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/stock/goodsUnderstock" @click="toggleMobileMenu">{{ $t('goodsUnderstock') }}</router-link>
+                          </li>
+                        </ul>
+                      </vue-collapsible>
+                    </li>
+                    <!--  <li class="menu nav-item">
+                      <button
+                        type="button"
+                        class="nav-link group w-full"
+                        :class="{ active: activeDropdown === 'goods' }"
+                        @click="activeDropdown === 'goods' ? (activeDropdown = null) : (activeDropdown = 'goods')"
+                      >
+                        <div class="flex items-center">
+                          <icon-menu-users class="group-hover:!text-primary shrink-0" />
+
+                          <span class="ltr:pl-3 rtl:pr-3 text-black dark:text-[#506690] dark:group-hover:text-white-dark">{{ $t('goods') }}</span>
+                        </div>
+                        <div :class="{ 'rtl:rotate-90 -rotate-90': activeDropdown == 'goods' }">
+                          <icon-caret-down />
+                        </div>
+                      </button>
+                      <vue-collapsible :isOpen="activeDropdown === 'goods'">
+                        <ul class="sub-menu text-gray-500">
+                          <li>
+                            <router-link to="/goods/SKUlist" @click="toggleMobileMenu">{{ $t('SKUList') }}</router-link>
+                          </li>
+                        </ul>
+                      </vue-collapsible>
+                      <vue-collapsible :isOpen="activeDropdown === 'goods'">
+                        <ul class="sub-menu text-gray-500"></ul>
+                      </vue-collapsible>
+                    </li>
+                    <li class="menu nav-item">
+                      <button
+                        type="button"
+                        class="nav-link group w-full"
+                        :class="{ active: activeDropdown === 'companyMent' }"
+                        @click="activeDropdown === 'companyMent' ? (activeDropdown = null) : (activeDropdown = 'companyMent')"
+                      >
+                        <div class="flex items-center">
+                          <icon-menu-users class="group-hover:!text-primary shrink-0" />
+
+                          <span class="ltr:pl-3 rtl:pr-3 text-black dark:text-[#506690] dark:group-hover:text-white-dark">{{ $t('companyMent') }}</span>
+                        </div>
+                        <div :class="{ 'rtl:rotate-90 -rotate-90': activeDropdown == 'companyMent' }">
+                          <icon-caret-down />
+                        </div>
+                      </button>
+                      <vue-collapsible :isOpen="activeDropdown === 'companyMent'">
+                        <ul class="sub-menu text-gray-500">
+                          <li>
+                            <router-link to="/companyMent/administratorManage" @click="toggleMobileMenu">{{ $t('administratorManage') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/setting/roleManage" @click="toggleMobileMenu">{{ $t('roleManage') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/companyMent/branch" @click="toggleMobileMenu">{{ $t('branch') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/companyMent/configMsg" @click="toggleMobileMenu">{{ $t('configMsg') }}</router-link>
+                          </li>
+                          <li>
+                            <router-link to="/setting/systemLog" @click="toggleMobileMenu">{{ $t('systemLog') }}</router-link>
+                          </li>
+                        </ul>
+                      </vue-collapsible>
+                      <vue-collapsible :isOpen="activeDropdown === 'companyMent'">
+                        <ul class="sub-menu text-gray-500"></ul>
+                      </vue-collapsible>
+                    </li> -->
+                  </ul>
+                </perfect-scrollbar>
+              </div>
+              <span id="sidebarSwitch" title="Shortcut:S" :style="sidebarShow? '':'left:-12px;'">
+                <span class="w" @click="contract" :style="sidebarShow? '':'width:16px;'">
+                  <b class="caret caret-left"  v-if="sidebarShow"></b>
+                  <b class="caret caret-right"  v-else></b>
+                </span>
+              </span>
+            </nav>
+          </div>
+          <!-- 页面主体部分 -->
+          <router-view></router-view>
         </div>
+        <!--  END CONTENT AREA  -->
+
+        <!-- BEGIN FOOTER -->
+
+        <!-- END FOOTER -->
+      </div>
+      <Footer />
     </div>
+  </div>
 </template>
 <script setup lang="ts">
-import { ref, onMounted } from 'vue';
+import { ref, onMounted, computed } from 'vue';
 //import Sidebar from '@/components/sidebar/index.vue'
+import VueCollapsible from 'vue-height-collapsible/vue3';
 import Sidebar from '@/components/layout/Sidebar.vue';
 import Header from '@/components/layout/Header.vue';
 import Footer from '@/components/layout/Footer.vue';
- import Setting from '@/components/ThemeCustomizer.vue';
+import Setting from '@/components/ThemeCustomizer.vue';
 import appSetting from '@/app-setting';
+import IconMenuUsers from '@/components/icon/menu/icon-menu-users.vue';
+import IconCaretDown from '@/components/icon/icon-caret-down.vue';
+import IconCaretsDown from '@/components/icon/icon-carets-down.vue';
+import IconMenuDashboard from '@/components/icon/menu/icon-menu-dashboard.vue';
 
 import store from '@/stores';
 const showTopButton = ref(false);
+const activeDropdown: any = ref('');
+const superMenu = computed(() => store.state.superMenu);
+const toggleMobileMenu = () => {
+  if (window.innerWidth < 1024) {
+    store.dispatch('toggleSidebar');
+  }
+};
+const toggleSidebars = () => {
+  store.dispatch('toggleSidebar');
+};
 onMounted(() => {
-    window.onscroll = () => {
-        if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
-            showTopButton.value = true;
-        } else {
-            showTopButton.value = false;
-        }
-    };
-
-    const eleanimation: any = document.querySelector('.animation');
-    eleanimation.addEventListener('animationend', function () {
-        appSetting.changeAnimation('remove');
-    });
-    store.dispatch('toggleMainLoader');
-    /*     store.toggleMainLoader(); */
+  window.onscroll = () => {
+    if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
+      showTopButton.value = true;
+    } else {
+      showTopButton.value = false;
+    }
+  };
+
+  const eleanimation: any = document.querySelector('.animation');
+  eleanimation.addEventListener('animationend', function () {
+    appSetting.changeAnimation('remove');
+  });
+  store.dispatch('toggleMainLoader');
+  /*     store.toggleMainLoader(); */
+  const selector = document.querySelector('.sidebar ul a[href="' + window.location.pathname + '"]');
+  if (selector) {
+    selector.classList.add('active');
+    const ul: any = selector.closest('ul.sub-menu');
+    if (ul) {
+      let ele: any = ul.closest('li.menu').querySelectorAll('.nav-link') || [];
+      if (ele.length) {
+        ele = ele[0];
+        setTimeout(() => {
+          ele.click();
+        });
+      }
+    }
+  }
 });
 
 const goToTop = () => {
-    document.body.scrollTop = 0;
-    document.documentElement.scrollTop = 0;
+  document.body.scrollTop = 0;
+  document.documentElement.scrollTop = 0;
 };
 const toggleSidebar = () => {
-    store.dispatch('toggleSidebar');
+  store.dispatch('toggleSidebar');
 };
+
+const sidebarShow=ref(true)
+/* 收缩 */
+const contract=()=>{
+    sidebarShow.value= !sidebarShow.value
+}
+/* 展开 */
+const expand=()=>{
+    sidebarShow.value=true
+}
+
 </script>
+<style>
+#sidebarSwitch {
+    position: fixed;
+    left: 245px;
+    top: 43%;
+    z-index: 5;
+    display: inline-block;
+    width: 30px;
+    height: 90px;
+    cursor: pointer;
+    text-align: center;
+}
+#sidebarSwitch .w {
+    display: inline-block;
+    width: 8px;
+    text-align: center;
+    height: 40px;
+    background: #fff;
+    margin: 23px 0 0;
+    border: 1px solid #ddd;
+    border-radius: 5px;
+}
+#sidebarSwitch .w .caret {
+    margin: 17px 0 0;
+}
+.caret {
+  display: inline-block;
+  transform: translate(0, -2px) rotate(-45deg);
+  width: 5px;
+  height: 5px;
+  border-left: 1px solid #999;
+  border-bottom: 1px solid #999;
+  border-top: 0;
+  border-right: 0;
+  content: '';
+}
+.caret-left {
+  transform: translate(1px, 0) rotate(45deg);
+}
+.caret-right {
+    transform: translate(-1px, 0) rotate(-135deg);
+}
+</style>

+ 305 - 262
src/locales/en.json

@@ -1,5 +1,5 @@
 {
-    "warehouse": "Warehouse Management",
+  "warehouse": "Warehouse Management",
   "warehouseList": "Warehouse List",
   "goodsLend": "Location Management",
   "goodsTransfer": "Inventory List",
@@ -10,282 +10,325 @@
   "goodsUnderstock": "Transfer List",
   "configMsg": "Message Configuration",
 
-    "setting": "System Management",
-    "companyList": "Company List",
-    "roleManage": "Role Management",
-    "dicData": "Data Dictionary",
-    "menuManage": "Menu Management",
-    "systemLog": "Operation Records",
-    "branch": "Department Management",
-    "package": "Package Management",
-    "packageList": "Package List",
-    "packagePermissions": "Package Permissions",
-    "templateManage": "Template Management",
-    "smsTemplate": "SMS Template",
-    "systemMessage": "System Message Template",
-    "emailtemplate": "Email Template",
-    "accountTemplate": "Public Account Template",
+  "setting": "System Management",
+  "companyList": "Company List",
+  "roleManage": "Permission Management",
+  "dicData": "Data Dictionary",
+  "menuManage": "Menu Management",
+  "systemLog": "Operation Records",
+  "branch": "Department Management",
+  "package": "Package Management",
+  "packageList": "Package List",
+  "packagePermissions": "Package Permissions",
+  "templateManage": "Template Management",
+  "smsTemplate": "SMS Template",
+  "systemMessage": "System Message Template",
+  "emailtemplate": "Email Template",
+  "accountTemplate": "Public Account Template",
 
-    "companyMent": "Company Management",
-    "administratorManage": "Personnel Management",
-    "companyInfo": "Company Details",
-    "goods": "Goods Management",
-    "SKUList": "Goods List",
-    "warehouseLocation": "Warehouse Location",
-    "addInventory": "Add Inventory",
-    "synchronous": "Synchronize",
+  "companyMent": "Company Management",
+  "administratorManage": "Personnel Management",
+  "companyInfo": "Company Details",
+  "goods": "Product Management",
+  "SKUList": "Product List",
+  "warehouseLocation": "Location Area",
+  "addInventory": "Add Inbound",
+  "synchronous": "Synchronous",
 
-    "add": "Add",
-    "edit": "Edit",
-    "view": "View",
-    "delete": "Delete",
-    "restore":"Restore",
-    "review": "Review",
-    "down": "Reject",
-    "print": "Print",
-    "preview": "Preview",
-    "search": "Search",
-    "operate": "Operate",
-    "submit": "Submit",
-    "cancel": "Cancel",
-    "return": "Return",
-    "save": "Save",
-    "place": "Please Enter",
-    "content": "Content",
-    "select": "Select",
-    "scan_code": "Scan Code for Entry",
-    "out_code": "Scan Code for Exit",
-    "change": "Please Select",
-    "notes": "Notes",
-    "date": "Date and Time",
-    "diff": "Difference",
-    "type": "Type",
-    "unknown": "Unknown Type",
-    "add_success": "Added Successfully",
-    "sub_success": "Saved Successfully",
-    "edit_success": "Edited Successfully",
-    "set_success": "Set Successfully",
-    "audit_success": "Reviewed Successfully",
-    "down_success": "Rejected Successfully",
-    "prompt": "Prompt",
-    "rejected": "Rejected!",
-    "reject_reason": "Please Fill in the Rejection Reason!",
-    "confirm_rejec": "Are You Sure to Reject?",
-    "del_info": "Are You Sure to Delete?",
-    "del_success": "Deleted Successfully",
-    "form_erroe": "Form Filling Error, Please Check!",
-    "search_placeholde": "Please Enter Keywords to Search",
+  "add": "Add",
+  "edit": "Edit",
+  "view": "View",
+  "delete": "Delete",
+  "restore": "Restore",
+  "renew": "Renew",
+  "agree_with": "Agree",
+  "review": "Review",
+  "down": "Reject",
+  "print": "Print",
+  "preview": "Preview",
+  "search": "Search",
+  "operate": "Operate",
+  "submit": "Confirm",
+  "cancel": "Cancel",
+  "return": "Return",
+  "disable": "Disable",
+  "open": "Open",
+  "save": "Save",
+  "place": "Please enter",
+  "content": "Content",
+  "select": "Select",
+  "scan_code": "Scan Inbound",
+  "out_code": "Scan Outbound",
+  "change": "Please select",
+  "notes": "Notes",
+  "date": "Date and Time",
+  "diff": "Difference",
+  "type": "Type",
+  "unknown": "Unknown Type",
+  "add_success": "Added Successfully",
+  "sub_success": "Saved Successfully",
+  "edit_success": "Modified Successfully",
+  "set_success": "Set Successfully",
+  "audit_success": "Audit Successful",
+  "down_success": "Rejected Successfully",
+  "created_success": "Created Successfully",
+  "renew_success": "Renewed Successfully!",
+  "renew_info": "Effective immediately after payment!",
+  "pass_error": "This is the login password, please record it carefully",
+  "prompt": "Prompt",
+  "rejected": "Rejected!",
+  "reject_reason": "Please provide a rejection reason!",
+  "confirm_rejec": "Are you sure you want to reject?",
+  "del_info": "Are you sure you want to delete?",
+  "del_success": "Deleted Successfully",
+  "form_erroe": "Form submission error, please check!",
+  "search_placeholde": "Please enter keywords to search",
 
-    "warechouse": "Warehouse",
-    "warechouse_sn": "Warehouse Number",
-    "warechouse_name": "Warehouse Name",
-    "warechouse_user_name": "Person in Charge Name",
-    "warechouse_phone": "Person in Charge Phone",
-    "warechouse_address": "Warehouse Address",
-    "warechouse_remark": "Warehouse Description",
-    "warechouse_code": "Location Number",
-    "warechouse_area": "Location Area",
-    "warechouse_sku": "Bound SKU Count",
-    "location_notes": "Location Description",
-    "location_code": "Area Number",
-    "location_name": "Area Name",
-    "actual_stock": "Actual Stock",
-    "usable_stock": "Usable Stock",
-    "transit_stock": "In-Transit Stock",
-    "locked_stock": "Frozen Stock",
-    "warning_stock": "Warning Stock",
-    "transitDetails": "In-Transit Details",
-    "order_sn": "Order Number",
-    "transit_num": "In-Transit Quantity",
-    "return_date": "Return Date",
-    "setNumber": "Set Warning Quantity",
-    "warningQuantity": "Warning Quantity",
-    "integer": "Positive Integer",
-    "warehousing": "Warehousing",
-    "access_time": "Access Time",
-    "start_time": "Start Time",
-    "end_time": "End Time",
-    "storage_type": "Storage Type",
-    "customer_name": "Customer Name",
-    "phone": "Phone",
-    "warehousing_sn": "Warehousing Number",
-    "warehousing_num": "Warehousing Quantity",
-    "warehousing_in_num": "Warehoused Quantity",
-    "not_entry_num": "Not Warehoused Quantity",
-    "warehousing_type": "Warehousing Type",
-    "warehousing_time": "Warehousing Time",
-    "warehousing_state": "Status",
-    "inStock": "Warehoused",
-    "notStock": "Not Warehoused",
-    "reject": "Rejection Reason",
+  "warechouse": "Warehouse",
+  "warechouse_sn": "Warehouse Number",
+  "warechouse_name": "Warehouse Name",
+  "warechouse_user_name": "Person in Charge Name",
+  "warechouse_phone": "Person in Charge Phone",
+  "warechouse_address": "Warehouse Address",
+  "warechouse_remark": "Warehouse Description",
+  "warechouse_code": "Location Number",
+  "warechouse_area": "Location Area",
+  "warechouse_sku": "Bound SKU Count",
+  "location_notes": "Location Description",
+  "location_code": "Area Number",
+  "location_name": "Area Name",
+  "actual_stock": "Actual Stock",
+  "usable_stock": "Available Stock",
+  "transit_stock": "In-Transit Stock",
+  "locked_stock": "Frozen Stock",
+  "warning_stock": "Warning Stock",
+  "transitDetails": "In-Transit Details",
+  "order_sn": "Order Number",
+  "transit_num": "In-Transit Quantity",
+  "return_date": "Return Date",
+  "setNumber": "Set Warning Quantity",
+  "warningQuantity": "Warning Quantity",
+  "integer": "Positive Integer",
+  "warehousing": "Inbound",
+  "access_time": "Access Time",
+  "start_time": "Start Time",
+  "end_time": "End Time",
+  "storage_type": "Inbound Type",
+  "customer_name": "Customer Name",
+  "phone": "Phone",
+  "warehousing_sn": "Inbound Order Number",
+  "warehousing_num": "Inbound Quantity",
+  "warehousing_in_num": "Quantity Inbound",
+  "not_entry_num": "Not Inbound Quantity",
+  "warehousing_type": "Inbound Type",
+  "warehousing_time": "Inbound Time",
+  "warehousing_state": "Status",
+  "inStock": "Inbound",
+  "notStock": "Not Inbound",
+  "reject": "Rejection Reason",
 
-    "addOut":"Add Outbound",
-    "outBound": "Outbound",
-    "out_sn": "Outbound Number",
-    "out_type": "Outbound Type",
-    "out_num": "Outbound Quantity",
+  "addOut": "Add Outbound",
+  "outBound": "Outbound",
+  "out_sn": "Outbound Order Number",
+  "out_type": "Outbound Type",
+  "out_num": "Outbound Quantity",
 
-    "inven": "Inventory",
-    "inventory": "Inventory List",
-    "creator": "Creator",
-    "reviewer": "Reviewer",
-    "notifiedre": "Notify Reviewer",
-    "goods_code": "Goods Scan Code",
-    "inventoryType": "Inventory Type",
-    "inventoryDate": "Inventory Date",
-    "inventoryPeople": "Inventory Person",
-    "inventorySn": "Inventory Number",
-    "inventory_time": "Inventory Time",
-    "stock": "Stock Quantity",
-    "inventory_num": "Inventory Quantity",
+  "inven": "Inventory Check",
+  "inventory": "Inventory Order",
+  "creator": "Creator",
+  "reviewer": "Reviewer",
+  "notifiedre": "Notify Reviewer",
+  "goods_code": "Product Scan",
+  "inventoryType": "Inventory Type",
+  "inventoryDate": "Inventory Date",
+  "inventoryPeople": "Inventory Personnel",
+  "inventorySn": "Inventory Order Number",
+  "inventory_time": "Inventory Time",
+  "stock": "Stock Quantity",
+  "inventory_num": "Inventory Quantity",
 
-    "goods_info": "Goods",
-    "goods_sn": "Goods Number",
-    "goods_name": "Goods Name",
-    "goods_unit": "Unit",
-    "goods_inventory": "Goods Details",
-    "goods_brand": "Brand",
-    "goods_bar_code": "Barcode",
-    "goods_weight": "Weight",
-    "goods_image": "Product Image",
+  "goods_info": "Product",
+  "goods_sn": "Product Number",
+  "goods_name": "Product Name",
+  "goods_unit": "Unit",
+  "goods_inventory": "Product Details",
+  "goods_brand": "Brand",
+  "goods_bar_code": "Barcode",
+  "goods_weight": "Weight",
+  "goods_image": "Product Image",
 
-    "user_name": "Login Name",
-    "user_name_length": "Length must be between 2 and 20 characters",
-    "user_name_bination": "Only supports combinations of Chinese characters, letters, numbers, '-', and '_'!",
-    "real_name": "Username",
-    "nick_name": "User Nickname",
-    "admin_sn": "User Code",
-    "dept_name": "Department",
-    "post_name": "Position",
-    "user_state": "Status",
-    "role_name": "Associated Role",
-    "admin_normal": "Normal",
-    "admin_password": "Password",
-    "pass_info": "Password must be 6-20 characters long, including numbers, letters, or special characters!",
-    "admin_not_pass": "Leave blank if not modifying",
-    "admin_info": "6-20 characters including numbers, letters, or special characters",
-    "role_name_info": "Super administrator does not need to select a role",
-    "role_name_sel": "Please select a role",
-    "admin_super": "Super User",
-    "restore_success": "Restore successful!",
-    "role_names": "Role Name",
-    "role_describe": "Role Description",
-    "role_permission": "Role Permissions",
-    "role_name_error": "Length must be between 1 and 10 characters",
-    "sel_all": "Select All",
+  "user_name": "Login Name",
+  "user_name_length": "Length between 2 to 20 characters",
+  "user_name_bination": "Only supports combinations of Chinese characters, letters, numbers, '-', and '_'!",
+  "real_name": "Username",
+  "nick_name": "User Nickname",
+  "admin_sn": "User Code",
+  "dept_name": "Department",
+  "post_name": "Position",
+  "user_state": "Status",
+  "role_name": "Associated Role",
+  "admin_normal": "Normal",
+  "admin_password": "Password",
+  "pass_info": "Password should be 6-20 characters long, including numbers, letters, or special characters!",
+  "admin_not_pass": "Leave blank if not modifying",
+  "admin_info": "6-20 characters including numbers, letters, or special characters",
+  "role_name_info": "Super Admin does not need to select a role",
+  "role_name_sel": "Please select a role",
+  "admin_super": "Super Personnel",
+  "restore_success": "Restored Successfully!",
+  "role_names": "Role Name",
+  "role_describe": "Role Description",
+  "role_permission": "Role Permissions",
+  "role_name_error": "Length between 1 to 10 characters",
+  "sel_all": "Select All",
 
-    "dept_names": "Department Name",
-    "dept_sn": "Department Code",
-    "dept_auth_regular": "Superior Department",
-    "dept_type": "Department Type",
-    "dept_sort": "Department Sort",
-    "dept_remark": "Department Description",
+  "dept_names": "Department Name",
+  "dept_sn": "Department Code",
+  "dept_auth_regular": "Superior Department",
+  "dept_type": "Department Type",
+  "dept_sort": "Department Sort",
+  "dept_remark": "Department Description",
 
-    "MSG_info": "Message Configuration",
-    "set_save": "Save Settings",
+  "MSG_info": "Message Configuration",
+  "set_save": "Save Settings",
 
-    "log_info": "Log Details",
-    "search_log": "Account/Operation Content/IP Address",
-    "operator_name": "Account",
-    "operate_detail": "Operation Description",
-    "request_method": "Request Method",
-    "request_parameters": "Request Parameters",
-    "operate_time": "Operation Time",
-    "operate_ip": "IP Address",
-    "operate_level": "Log Level",
-    "operate_import": "Important",
-    "operate_same": "General",
+  "log_info": "Log Details",
+  "search_log": "Account/Operation Content/IP Address",
+  "operator_name": "Account",
+  "operate_detail": "Operation Description",
+  "request_method": "Request Method",
+  "request_parameters": "Request Parameters",
+  "operate_time": "Operation Time",
+  "operate_ip": "IP Address",
+  "operate_level": "Log Level",
+  "operate_import": "Important",
+  "operate_same": "General",
+  "legal_person": "Legal Person",
 
-    "order_num": "Order Quantity",
-    "return_num": "Return Quantity",
+  "order_num": "Order Quantity",
+  "return_num": "Return Quantity",
 
-    "inOut": "Outbound",
-    "notOut": "Not Outbound",
-    "outTime": "Outbound Time",
+  "inOut": "Outbound",
+  "notOut": "Not Outbound",
+  "outTime": "Outbound Time",
 
-    "loss_goods": "Damaged Goods",
-    "loss_date": "Damage Date",
-    "loss_people": "Damage Person",
-    "loss_sn": "Damage Number",
-    "loss_desc": "Damage Description",
-    "loss_time": "Damage Time",
-    "loss_type": "Damage Type",
-    "loss_num": "Damage Quantity",
+  "loss_goods": "Loss Goods",
+  "loss_date": "Loss Date",
+  "loss_people": "Loss Person",
+  "loss_sn": "Loss Order Number",
+  "loss_desc": "Loss Description",
+  "loss_time": "Loss Time",
+  "loss_type": "Loss Type",
+  "loss_num": "Loss Quantity",
 
-    "search_goods": "Search Goods",
-    "transfer_goods": "Transfer Goods",
-    "out_warehouse": "Outgoing Warehouse",
-    "to_warehouse": "Incoming Warehouse",
-    "transfer_time": "Transfer Time",
-    "transfer_sn": "Transfer Number",
-    "transfer_num": "Transfer Quantity",
-    "delivery_method": "Delivery Method",
-    "transfer_order": "Transfer Order",
+  "search_goods": "Search Product",
+  "transfer_goods": "Transfer Product",
+  "out_warehouse": "Outbound Warehouse",
+  "to_warehouse": "Inbound Warehouse",
+  "transfer_time": "Transfer Time",
+  "transfer_sn": "Transfer Order Number",
+  "transfer_num": "Transfer Quantity",
+  "delivery_method": "Delivery Method",
+  "transfer_order": "Transfer Order",
 
-    "express": "Logistics Company",
-    "companyDetails": "Company Information",
-    "currentPack": "Current Package",
-    "end_use_time": "Package Expiration Time",
-    "user_num": "Number of Bindable Accounts",
-    "companyName": "Company Name",
-    "credit_code": "Unified Social Credit Code",
-    "industry": "Industry",
-    "company_user_name": "Contact Person",
-    "companyPhone": "Contact Phone",
-    "companyEmail": "Email",
-    "postalCode": "Postal Code",
-    "website": "Official Website",
-    "companyAddress": "Address",
-    "companyLicense": "Business License",
-    "nickname": "Account Name",
-    "loginName": "Login Account",
-    "profile": "Profile Picture",
-    "bindWeChat": "Bind WeChat",
-    "bindWeChatError": "Failed to Get WeChat Binding Information",
-    "uploadPro": "Please Upload Profile Picture",
-    "uploadNewPro": "Please Upload a New Profile Picture",
-    "pay_success": "Payment Successful",
-    "pay_info": "Payment Canceled",
-    "pay_error": "Payment Failed",
+  "express": "Logistics Company",
+  "express_title": "Logistics Company Name",
+  "express_code": "Express Query Code",
+  "express_kdcode": "Cainiao Logistics Code",
+  "express_company_info": "Are you sure you want to delete this logistics company?",
+  "operate_info": "Are you sure you want to perform this operation?",
+  "operate_success": "Operation Successful!",
 
-    "brand": "Brand",
-    "weight": "Weight",
-    "consistent": "Cannot Be Consistent",
-    "setPayment": "Set Payment Information",
-    "payinfo": "This payment method is a partner collection model. Merchants need to register their own WeChat mchid and bind with the partner. During the binding period, the partner and the merchant can negotiate service fees, or choose not to use a commission. Please communicate carefully with customer service personnel before filling out.",
-    "payment_type": "Payment Method",
-    "ali_private_key": "Ali Private Key",
-    "ali_public_key": "Ali Public Key",
-    "wx_sub_mch_id": "WeChat Store ID",
-    "logout_commit": "Are you sure you want to log out?",
-    "payment_success": "Setup Successful",
+  "companyDetails": "Company Information",
+  "currentPack": "Current Package",
+  "end_use_time": "Package Expiration Time",
+  "user_num": "Number of Bindable Accounts",
+  "companyName": "Company Name",
+  "credit_code": "Unified Social Credit Code",
+  "industry": "Industry",
+  "company_user_name": "Contact Person",
+  "companyPhone": "Contact Phone",
+  "companyEmail": "Email",
+  "postalCode": "Postal Code",
+  "website": "Official Website",
+  "companyAddress": "Address",
+  "companyLicense": "Business License",
 
-    "goods_tips":"The item is out of stock!",
-    "calendar": "Calendar",
-    "tabs": "Tabs",
-    "error": "Error",
+  "nickname": "Account Name",
+  "loginName": "Login Account",
+  "profile": "Profile Picture",
+  "bindWeChat": "Bind WeChat",
+  "bindWeChatError": "Failed to get WeChat binding information",
+  "uploadPro": "Please upload a profile picture",
+  "uploadNewPro": "Please upload a new profile picture",
 
-    "info": "Personal Information",
-    "edit_password": "Change Password",
-    "logout": "Log Out",
-    "login": "Login",
-    "lockscreen": "Lockscreen",
-    "password_recovery": "Password Recovery",
-    "register": "Register",
-    "404": "404",
-    "500": "500",
-    "503": "503",
-    "user_interface": "User Interface",
-    "tables_and_forms": "Tables And Forms",
-    "columns_filter": "Columns Filter",
-    "column_chooser": "Column Chooser",
-    "advanced": "Advanced",
-    "checkbox": "Checkbox",
-    "skin": "Skin",
-    "sticky_header": "Sticky Header",
-    "clone_header": "Clone Header",
-    "coming_soon_boxed": "Coming Soon Boxed",
-    "coming_soon_cover": "Coming Soon Cover",
-    "contact_us_boxed": "Contact Us Boxed",
-    "contact_us_cover": "Contact Us Cover"
-}
+  "pay_success": "Payment Successful",
+  "pay_info": "Payment has been canceled",
+  "pay_error": "Payment Failed",
+
+  "brand": "Brand",
+  "weight": "Weight",
+  "consistent": "Cannot be the same",
+  "setPayment": "Set Payment Information",
+  "payinfo": "This payment method is for partner collection mode. Merchants need to register their own WeChat mchid and bind with partners. During the binding period, partners and merchants can negotiate service fees, or no commission can be charged. Merchants should communicate with customer service personnel carefully before filling in.",
+  "payment_type": "Payment Method",
+  "ali_private_key": "Ali Private Key",
+  "ali_public_key": "Ali Public Key",
+  "wx_sub_mch_id": "WeChat Store ID",
+  "logout_commit": "Are you sure you want to log out?",
+  "payment_success": "Set Successfully",
+
+  "company_package": "Package",
+  "package_name": "Package Name",
+  "package_money": "Package Amount",
+  "package_day": "Days",
+  "package_user_num": "Number of Users that can be Created",
+  "package_remark": "Package Description",
+  "package_role": "Permissions",
+
+  "function_name": "Function Name",
+  "function_describe": "Function Description",
+  "function_permission": "Function Permissions",
+
+  "template_name": "Template Name",
+  "template_code": "Template Code",
+  "template_remark": "Template Description",
+  "audit_status": "Audit Status",
+  "superior_template": "Superior Template",
+  "custom_template_code": "Custom Template Code",
+  "enable_status": "Is Enabled",
+  "template_content": "Template Content",
+  "template_tips": "Only English, numbers, and underscores are allowed, no spaces",
+  "template_add": "Add Template",
+  "template_view": "View Template",
+  "template_edit": "Edit Template",
+  "template_type_success": "Status Modified Successfully",
+  "front_id_card": "Front of ID Card",
+  "opposite_id_card": "Back of ID Card",
+  "corporate_phone": "Legal Person Phone",
+  "upload_id_card": "Please upload the legal person's ID card",
+  "valid_phone": "Please enter a valid phone number",
+  "valid_email": "Please enter a valid email address",
+  "valid_postal_code": "Please enter a valid postal code",
+  "dic_class_list": "Dictionary Category List",
+  "dic_data_list": "Dictionary Data List",
+  "dic_sn": "Dictionary Number",
+  "dic_id": "Dictionary Code",
+  "dic_name": "Dictionary Name",
+  "dic_type": "Dictionary Type",
+  "dic_label": "Dictionary Label",
+  "dic_value": "Dictionary Key Value",
+  "dic_sort": "Dictionary Sort",
+  "default_flag": "Is Default Selected",
+  "dic_class_info": "Are you sure you want to delete this dictionary category?",
+  "dic_data_info": "Are you sure you want to delete this dictionary?",
+  "add_top_menu": "Add Top-Level Menu",
+  "edit_menu": "Edit Menu",
+  "add_menu": "Add Menu",
+  "menu_title": "Menu Title",
+  "menu_identifier": "Menu Identifier",
+  "menu_auth_regular": "Menu Permissions",
+  "menu_icon": "Menu Icon",
+  "menu_show_home": "Show on Home Page",
+  "menu_delet_info": "Are you sure you want to delete this menu? If there are submenus, they will also be deleted!"
+}

+ 17 - 0
src/locales/zh.json

@@ -51,6 +51,8 @@
     "submit":"确 定",
     "cancel":"取 消",
     "return":"返回",
+    "disable":"禁用",
+    "open":"开启",
     "save":"保存",
     "place":"请输入",
     "content":"内容",
@@ -230,6 +232,12 @@
     "transfer_order":"调拨单",
 
     "express":"物流公司",
+    "express_title":"物流公司名称",
+    "express_code":"快递查询代码",
+    "express_kdcode":"菜鸟物流代码",
+    "express_company_info":"确定要删除此物流公司吗?",
+    "operate_info":"确定要执行此操作吗?",
+    "operate_success":"操作成功!",
 
     "companyDetails":"公司信息",
     "currentPack":"当前套餐",
@@ -314,6 +322,15 @@
     "default_flag":"是否默认选中",
     "dic_class_info":"确定要删除这个字典分类吗?",
     "dic_data_info":"确定要删除这个字典吗?",
+    "add_top_menu":"添加顶级菜单",
+    "edit_menu":"编辑菜单",
+    "add_menu":"添加菜单",
+    "menu_title":"菜单标题",
+    "menu_identifier":"菜单标识",
+    "menu_auth_regular":"菜单权限",
+    "menu_icon":"菜单图标",
+    "menu_show_home":"首页显示",
+    "menu_delet_info":"确定要删除这个菜单吗?如果有子菜单,子菜单也会被一并删除!",
     
 
     "tabs": "标签",

+ 1 - 1
src/stores/index.ts

@@ -48,7 +48,7 @@ const store = createStore<State>({
         isDarkMode: false,
         mainLayout: 'app',
         theme: 'light',
-        menu: 'vertical',
+        menu: 'horizontal',
         layout: 'full',
         rtlClass: 'ltr',
         animation: '',

+ 1 - 1
src/views/companyMent/administratorManage.vue

@@ -38,7 +38,7 @@
           </template>
         </el-table-column>
         <el-table-column prop="role_name" :label="$t('role_name')"/>
-        <el-table-column :label="$t('operate')" width="200px">
+        <el-table-column :label="$t('operate')" fixed="right" width="300">
           <template #default="scope">
             <el-button size="small" type="primary" v-if="store.state.user.user.founder !== 1" @click="handleEditAdmin(scope.$index, scope.row)">{{$t('edit')}}</el-button>
             <!-- v-if="checkPermission(['administratorManage:edit'])" -->

+ 1 - 1
src/views/goods/SKUList.vue

@@ -25,7 +25,7 @@
           </template>
         </el-table-column>
 
-        <el-table-column :label="$t('operate')">
+        <el-table-column :label="$t('operate')" fixed="right" width="450">
           <template #default="scope">
             <el-button size="small" v-if="checkPermission(['warehouse:update'])" @click="handleView(scope.row)">{{$t('view')}}</el-button>
             <el-button size="small" v-if="checkPermission(['warehouse:update'])&& store.state.user.user.founder!==1" @click="handleEditWarehouse(scope.$index, scope.row)">{{$t('edit')}}</el-button>

+ 1 - 1
src/views/package/packageList.vue

@@ -45,7 +45,7 @@
           </template>
         </el-table-column>
         <el-table-column prop="remark" :label="$t('package_remark')" />
-        <el-table-column :label="$t('operate')">
+        <el-table-column :label="$t('operate')" fixed="right" width="300">
           <template #default="scope">
             <el-button size="default" v-if="checkPermission(['warehouse:update'])" @click="handleEditWarehouse(scope.$index, scope.row)">{{$t('edit')}}</el-button>
           </template>

+ 28 - 26
src/views/setting/express.vue

@@ -4,7 +4,7 @@
       <template #toolbar>
         <div class="inner-toolbar w-11/12 flex justify-between">
           <div class="toolbar-btns">
-            <el-button size="small" type="primary" @click="handleAddExpress">添加</el-button>
+            <el-button size="small" type="primary" @click="handleAddExpress">{{$t('add')}}</el-button>
           </div>
           <div class="toolbar-search">
             <!--  <en-table-search @search="searchEvent" placeholder="请输入关键字" /> -->
@@ -12,31 +12,31 @@
         </div>
       </template>
       <template #table-columns>
-        <el-table-column prop="name" label="公司名称" />
-        <el-table-column prop="code" label="快递查询代码" />
-        <el-table-column prop="kdcode" label="菜鸟代码" />
-        <el-table-column label="状态" :formatter="disabledStatus" />
-        <el-table-column label="操作" min-width="200">
+        <el-table-column prop="name" :label="$t('companyName')" />
+        <el-table-column prop="code" :label="$t('express_code')" />
+        <el-table-column prop="kdcode" :label="$t('express_kdcode')" />
+        <el-table-column :label="$t('user_state')" :formatter="disabledStatus" />
+        <el-table-column :label="$t('operate')" min-width="200">
           <template #default="scope">
             <el-button size="small" type="primary" v-if="checkPermission(['logisticsCompany:edit'])" @click="handleEditExpress(scope.$index, scope.row)"
-              >编辑</el-button
+              >{{$t('edit')}}</el-button
             >
             <el-button
               v-if="scope.row.disabled === 'OPEN' && checkPermission(['logisticsCompany:editStatus'])"
               size="small"
               type="danger"
               @click="handleDisabledExpress(scope.$index, scope.row)"
-              >禁用</el-button
+              >{{$t('disable')}}</el-button
             >
             <el-button
               v-if="scope.row.disabled === 'CLOSE' && checkPermission(['logisticsCompany:editStatus'])"
               size="small"
               type="success"
               @click="handleDisabledExpress(scope.$index, scope.row)"
-              >开启</el-button
+              >{{$t('open')}}</el-button
             >
             <el-button size="small" v-if="checkPermission(['logisticsCompany:delete'])" type="danger" @click="handleDeleteExpress(scope.$index, scope.row)"
-              >删除</el-button
+              >{{$t('delete')}}</el-button
             >
           </template>
         </el-table-column>
@@ -54,22 +54,22 @@
       @current-change="handlePageCurrentChange"
     />
 
-    <el-dialog v-model="dialogExpressVisible" title="物流公司" :close-on-click-modal="false" :close-on-press-escape="false">
+    <el-dialog v-model="dialogExpressVisible" :title="$t('express')" :close-on-click-modal="false" :close-on-press-escape="false">
       <el-form :model="expressForm" :rules="expressRules" ref="expressFormRef" label-width="120px">
-        <el-form-item label="物流公司名称" prop="name">
+        <el-form-item :label="$t('express_title')" prop="name">
           <el-input v-model="expressForm.name"></el-input>
         </el-form-item>
-        <el-form-item label="快递查询代码" prop="code">
+        <el-form-item :label="$t('express_code')" prop="code">
           <el-input v-model="expressForm.code"></el-input>
         </el-form-item>
-        <el-form-item label="菜鸟物流代码" prop="kdcode" v-if="expressForm.is_waybill">
+        <el-form-item :label="$t('express_kdcode')" prop="kdcode" v-if="expressForm.is_waybill">
           <el-input v-model="expressForm.kdcode"></el-input>
         </el-form-item>
       </el-form>
       <template #footer>
         <span class="dialog-footer">
-          <el-button @click="dialogExpressVisible = false">取 消</el-button>
-          <el-button type="primary" @click="submitExpressForm">确 定</el-button>
+          <el-button @click="dialogExpressVisible = false">{{$t('cancel')}}</el-button>
+          <el-button type="primary" @click="submitExpressForm">{{$t('submit')}}</el-button>
         </span>
       </template>
     </el-dialog>
@@ -80,6 +80,8 @@
 import { ref, reactive, computed, onMounted } from 'vue';
 import { ElMessage, ElMessageBox } from 'element-plus';
 import * as API_Express from '@/api/express';
+import { useI18n } from 'vue-i18n';
+const { t } = useI18n();
 
 // 定义响应式数据
 const loading = ref(false);
@@ -95,9 +97,9 @@ const expressFormRef = ref();
 // 计算属性:表单验证规则
 const expressRules = computed(() => {
   return {
-    name: [{ required: true, message: '请输入物流公司名称!', trigger: 'blur' }],
-    code: [{ required: true, message: '请输入快递查询代码!', trigger: 'blur' }],
-    kdcode: [{ required: expressForm.value.is_waybill, message: '请输入菜鸟物流代码!', trigger: 'blur' }],
+    name: [{ required: true, message: t('place')+t('express_title')+'!', trigger: 'blur' }],
+    code: [{ required: true, message: t('place')+t('express_code')+'!', trigger: 'blur' }],
+    kdcode: [{ required: expressForm.value.is_waybill, message:t('place')+t('express_kdcode')+'!', trigger: 'blur' }],
   };
 });
 
@@ -155,14 +157,14 @@ const submitExpressForm = () => {
       if (!id) {
         API_Express.addExpress(form).then(() => {
           dialogExpressVisible.value = false;
-          ElMessage.success('添加成功!');
+          ElMessage.success(t('add_success')+'!');
           getExpressList();
         });
       } else {
         form.formItems = [];
         API_Express.editExpress(id, form).then((response) => {
           dialogExpressVisible.value = false;
-          ElMessage.success('保存成功!');
+          ElMessage.success(t('sub_success')+'!');
           // 更新表格数据
           const index = tableData.value.data.findIndex((item: any) => item.id === id);
           if (index !== -1) {
@@ -171,16 +173,16 @@ const submitExpressForm = () => {
         });
       }
     } else {
-      ElMessage.error('表单填写有误,请检查!');
+      ElMessage.error(t('form_erroe'));
     }
   });
 };
 
 const handleDeleteExpress = (index: number, row: any) => {
-  ElMessageBox.confirm('确定要删除此物流公司吗?', '提示', { type: 'warning' })
+  ElMessageBox.confirm(t('express_company_info'), t('prompt'), { type: 'warning' })
     .then(() => {
       API_Express.deleteExpress(row.id).then(() => {
-        ElMessage.success('删除成功!');
+        ElMessage.success(t('del_success'));
         getExpressList();
       });
     })
@@ -188,10 +190,10 @@ const handleDeleteExpress = (index: number, row: any) => {
 };
 
 const handleDisabledExpress = (index: number, row: any) => {
-  ElMessageBox.confirm('确定要执行此操作吗?', '提示', { type: 'warning' })
+  ElMessageBox.confirm(t('operate_info'), t('prompt'), { type: 'warning' })
     .then(() => {
       API_Express.openDisableExpress(row.id, row.disabled === 'OPEN' ? 'CLOSE' : 'OPEN').then(() => {
-        ElMessage.success('操作成功!');
+        ElMessage.success(t('operate_success'));
         getExpressList();
       });
     })

+ 21 - 19
src/views/setting/menuManage.vue

@@ -8,43 +8,43 @@
               <el-button type="primary" text :disabled="node.level === 4" :icon="Plus"
                 :title="node.level === 4 ? '菜单最多添加三级' : '增加'" v-if="checkPermission(['menuManage:add'])"
                 @click.stop="handleAddMenu(data)" />
-              <el-button type="danger" text :icon="Minus" title="删除" v-if="checkPermission(['menuManage:del'])"
+              <el-button type="danger" text :icon="Minus" :title="$t('delete')" v-if="checkPermission(['menuManage:del'])"
                 @click.stop="handleDeleteMenu(node, data)" />
-              <el-button type="primary" text :icon="Edit" title="编辑" v-if="checkPermission(['menuManage:edit'])"
+              <el-button type="primary" text :icon="Edit" :title="$t('edit')" v-if="checkPermission(['menuManage:edit'])"
                 @click.stop="handleEditMenu(data)" />
             </span>
           </span>
         </template>
       </el-tree>
       <el-button v-if="menus" text style="margin-top: 10px; margin-left: 20px"
-        @click="handleAddMenu('')">添加顶级菜单</el-button>
-      <el-dialog :title="menuForm.menu_name ? '编辑菜单' : '添加菜单'" v-model="dialogMenuVisible" width="500px"
+        @click="handleAddMenu('')">{{$t('add_top_menu')}}</el-button>
+      <el-dialog :title="menuForm.menu_name ? $t('edit_menu') : $t('add_menu')" v-model="dialogMenuVisible" width="500px"
         :close-on-click-modal="false" :close-on-press-escape="false" @close="closeMenuForm">
         <el-form :model="menuForm" :rules="menuRules" ref="menuFormRef" label-width="100px">
-          <el-form-item label="菜单标题" prop="title">
+          <el-form-item :label="$t('menu_title')" prop="title">
             <el-input v-model="menuForm.title"></el-input>
           </el-form-item>
-          <el-form-item label="菜单标识" prop="identifier">
+          <el-form-item :label="$t('menu_identifier')" prop="identifier">
             <el-input v-model="menuForm.identifier"></el-input>
           </el-form-item>
-          <el-form-item label="菜单权限" prop="auth_regular">
+          <el-form-item :label="$t('menu_auth_regular')" prop="auth_regular">
             <el-input v-model="menuForm.auth_regular" type="textarea"></el-input>
           </el-form-item>
-          <el-form-item label="菜单图标" prop="icon" v-if="iconShow!=='0'">
+          <el-form-item :label="$t('menu_icon')" prop="icon" v-if="iconShow!=='0'">
             <el-upload class="site-logo" :action="MixinUploadApi" :show-file-list="false"
               :on-success="(res) => { menuForm.icon = res.url }" :multiple="false">
               <img v-if="menuForm.icon" :src="menuForm.icon" class="site-logo-img">
               <el-icon v-else><Plus /></el-icon>
             </el-upload>
           </el-form-item>
-          <el-form-item label="首页显示" prop="show_home" v-if="iconShow !== '0' && checkPermission(['UserMenu:get'])">
+          <el-form-item :label="$t('menu_show_home')" prop="show_home" v-if="iconShow !== '0' && checkPermission(['UserMenu:get'])">
             <el-switch v-model="menuForm.show_home" :active-value="1" :inactive-value="2" @change="switchVal"></el-switch>
           </el-form-item>
         </el-form>
         <template #footer>
           <span class="dialog-footer">
-            <el-button @click="closeMenuForm">取 消</el-button>
-            <el-button type="primary" @click="submitMenuForm('menuFormRef')">确 定</el-button>
+            <el-button @click="closeMenuForm">{{$t('cancel')}}</el-button>
+            <el-button type="primary" @click="submitMenuForm('menuFormRef')">{{$t('submit')}}</el-button>
           </span>
         </template>
       </el-dialog>
@@ -56,7 +56,9 @@
   import { ElMessage, ElMessageBox } from 'element-plus'
   import { Plus, Minus, Edit } from '@element-plus/icons-vue'
   import * as API_Menus from '@/api/menus'
-  
+  import { useI18n } from 'vue-i18n';
+const { t } = useI18n();
+
   const MixinUploadApi=ref(import.meta.env.VITE_API_URL + '/uploaders')
   const menus = ref<any[]>([]);
   const menuForm = ref<any>({
@@ -65,13 +67,13 @@
   })
   const menuRules = reactive({
     title: [
-      { required: true, message: '请输入菜单标题!', trigger: 'blur' }
+      { required: true, message:t('place')+t('menu_title')+'!', trigger: 'blur' }
     ],
     identifier: [
-      { required: true, message: '请输入菜单标识!', trigger: 'blur' }
+      { required: true, message:t('place')+t('menu_identifier')+'!', trigger: 'blur' }
     ],
     auth_regular: [
-      { required: true, message: '请输入菜单权限!', trigger: 'blur' }
+      { required: true, message:t('place')+t('menu_auth_regular')+'!', trigger: 'blur' }
     ],
   })
   
@@ -108,7 +110,7 @@
   }
   
   const handleDeleteMenu = (node, menu) => {
-    ElMessageBox.confirm('确定要删除这个菜单吗?如果有子菜单,子菜单也会被一并删除!', '提示', { type: 'warning' })
+    ElMessageBox.confirm(t('menu_delet_info'),t('prompt'), { type: 'warning' })
       .then(() => {
         API_Menus.deleteMenu(menu.id).then(() => {
           const parent = node.parent
@@ -136,7 +138,7 @@
         if (id) {
           API_Menus.editMenu(id, menuForm.value).then(response => {
             dialogMenuVisible.value = false
-            ElMessage.success('保存成功!')
+            ElMessage.success(t('sub_success'))
             GET_Memus()
           })
         } else {
@@ -149,11 +151,11 @@
               data.children.push(response)
             }
             dialogMenuVisible.value = false
-            ElMessage.success('保存成功!')
+            ElMessage.success(t('sub_success'))
           })
         }
       } else {
-        ElMessage.error('表单填写有误,请检查!')
+        ElMessage.error(t('form_erroe'))
         return false
       }
     })

+ 1 - 1
src/views/stock/goodsInventory.vue

@@ -67,7 +67,7 @@
         <el-table-column prop="status" :label="$t('warehousing_state')">
           <template #default="scope">{{ statusFilter(scope.row.status) }}</template>
         </el-table-column>
-        <el-table-column :label="$t('operate')" width="450">
+        <el-table-column :label="$t('operate')" fixed="right" width="450">
           <template #default="scope">
             <!-- v-if="checkPermission(['goodsInventoryCheck'])" -->
             <el-button size="small" @click="handleCheckGoodsInventory(scope.row)">{{$t('view')}}</el-button>

+ 1 - 1
src/views/stock/goodsInventoryLoss.vue

@@ -64,7 +64,7 @@
           <template #default="scope">{{ statusFilter(scope.row.status) }}</template>
         </el-table-column>
         <el-table-column prop="report_desc" :label="$t('loss_desc')" />
-        <el-table-column :label="$t('operate')" width="450">
+        <el-table-column :label="$t('operate')" fixed="right" width="450">
           <template #default="scope">
             <!-- v-if="checkPermission(['goodsInventoryLossDetail'])" -->
             <el-button type="mini" size="small" @click="handleDetailGoodsInventoryLoss(scope.row)">{{ $t('view') }}</el-button>

+ 1 - 1
src/views/stock/goodsLend.vue

@@ -30,7 +30,7 @@
           <template #default="scope">{{ statusFilter(scope.row.type) }}</template>
         </el-table-column>
         <el-table-column prop="bind_num" :label="$t('warechouse_sku')" />
-        <el-table-column :label="$t('operate')" width="250">
+        <el-table-column :label="$t('operate')" fixed="right" width="300">
           <template #default="scope">
             <!-- <el-button size="small" v-if="checkPermission(['inventoryItem'])" @click="introGoodsLend(scope.row)">查看</el-button>
             <el-button size="small" v-if="checkPermission(['bindAreaStock:update'])" @click="AddGoodsLend(scope.row)">绑定商品</el-button> -->

+ 1 - 1
src/views/stock/goodsTransfer.vue

@@ -63,7 +63,7 @@
         <el-table-column prop="transit_stock" :label="$t('transit_stock')" />
         <el-table-column prop="locked_stock" :label="$t('locked_stock')" />
         <el-table-column prop="warning_stock" :label="$t('warning_stock')" />
-        <!--   <el-table-column label="操作" width="250">
+        <!--   <el-table-column label="操作" fixed="right" width="300">
           <template #default="scope">
             <el-button type="success1" size="small" v-if="checkPermission(['goodsTransfer:add']) && scope.row.transit_stock>0"
               @click="lookTransit(scope.row)">查看在途</el-button>

+ 1 - 1
src/views/stock/outbound.vue

@@ -111,7 +111,7 @@
             <span>{{ scope.row.notes }}</span>
           </template>
         </el-table-column>
-        <el-table-column :label="$t('operate')" width="300">
+        <el-table-column :label="$t('operate')" fixed="right"  width="300">
           <template #default="scope">
             <!-- v-if="checkPermission(['checkInventory'])" -->
             <el-button size="small"  @click="handleAuditGoodsExchange(scope.row)">{{$t('view')}}</el-button>

+ 1 - 1
src/views/stock/warehouseList.vue

@@ -29,7 +29,7 @@
           </template>
         </el-table-column>
         <el-table-column prop="description" :label="$t('warechouse_remark')" min-width="150" />
-        <el-table-column :label="$t('operate')" fixed="right" width="100">
+        <el-table-column :label="$t('operate')" fixed="right" width="300">
           <template #default="scope">
             <el-button
               size="small"

+ 1 - 1
src/views/stock/warehouseLocation.vue

@@ -16,7 +16,7 @@
         <el-table-column prop="code" :label="$t('location_code')"/>
         <el-table-column prop="name" :label="$t('location_name')"/>
         <el-table-column prop="remark" :label="$t('notes')"/>
-        <el-table-column :label="$t('operate')">
+        <el-table-column :label="$t('operate')" fixed="right" width="300">
           <template #default="scope"
             ><!-- checkPermission(['updateAreaType:update'])&& -->
             <el-button size="small" v-if="store.state.user.user.founder !== 1" @click="handleEditGoodsLend(scope.row)">{{ $t('edit') }}</el-button

+ 1 - 1
src/views/stock/warehousing.vue

@@ -107,7 +107,7 @@
             <span>{{ scope.row.memo }}</span>
           </template>
         </el-table-column>
-        <el-table-column :label="$t('operate')">
+        <el-table-column :label="$t('operate')" fixed="right" width="300">
           <template #default="scope">
             <!-- v-if="checkPermission(['checkInventory'])" -->
             <el-button class="mr-1 mt-1" size="small" @click="handleAuditGoodsExchange(scope.row)">{{ $t('view') }}</el-button>

+ 1 - 1
src/views/templateManage/accountTemplate.vue

@@ -48,7 +48,7 @@
           <el-switch v-model="scope.row.enable_status" inline-prompt active-text="启用" inactive-text="禁用" @change="switchEnableStatus($event, scope.row)" />
         </template>
       </el-table-column>
-      <el-table-column :label="$t('operate')">
+      <el-table-column :label="$t('operate')" fixed="right" width="300">
         <template #default="scope">
           <el-button size="small" @click="handleView(scope.row)" v-if="checkPermission([''])">{{$t('view')}}</el-button>
           <el-button size="small" type="primary" @click="handleEditRole(scope.row)" v-if="checkPermission([''])">{{$t('edit')}}</el-button>

+ 1 - 1
src/views/templateManage/emailtemplate.vue

@@ -48,7 +48,7 @@
           <el-switch v-model="scope.row.enable_status" inline-prompt active-text="启用" inactive-text="禁用" @change="switchEnableStatus($event, scope.row)" />
         </template>
       </el-table-column>
-      <el-table-column :label="$t('operate')">
+      <el-table-column :label="$t('operate')" fixed="right" width="300">
         <template #default="scope">
           <el-button size="small" @click="handleView(scope.row)" v-if="checkPermission([''])">{{$t('view')}}</el-button>
           <el-button size="small" type="primary" @click="handleEditRole(scope.row)" v-if="checkPermission([''])">{{$t('edit')}}</el-button>

+ 1 - 1
src/views/templateManage/smsTemplate.vue

@@ -48,7 +48,7 @@
           <el-switch v-model="scope.row.enable_status" inline-prompt active-text="启用" inactive-text="禁用" @change="switchEnableStatus($event, scope.row)" />
         </template>
       </el-table-column>
-      <el-table-column :label="$t('operate')">
+      <el-table-column :label="$t('operate')" fixed="right" width="300">
         <template #default="scope">
           <el-button size="small" @click="handleView(scope.row)" v-if="checkPermission([''])">{{$t('view')}}</el-button>
           <el-button size="small" type="primary" @click="handleEditRole(scope.row)" v-if="checkPermission([''])">{{$t('edit')}}</el-button>

+ 1 - 1
src/views/templateManage/systemMessage.vue

@@ -48,7 +48,7 @@
           <el-switch v-model="scope.row.enable_status" inline-prompt active-text="启用" inactive-text="禁用" @change="switchEnableStatus($event, scope.row)" />
         </template>
       </el-table-column>
-      <el-table-column :label="$t('operate')">
+      <el-table-column :label="$t('operate')" fixed="right" width="300">
         <template #default="scope">
           <el-button size="small" @click="handleView(scope.row)" v-if="checkPermission([''])">{{$t('view')}}</el-button>
           <el-button size="small" type="primary" @click="handleEditRole(scope.row)" v-if="checkPermission([''])">{{$t('edit')}}</el-button>

+ 1 - 1
theme.config.ts

@@ -2,7 +2,7 @@
 export const $themeConfig = {
     locale: 'zh', // en, da, de, el, es, fr, hu, it, ja, pl, pt, ru, sv, tr, zh
     theme: 'light', // light, dark, system
-    menu: 'vertical', // vertical, collapsible-vertical, horizontal
+    menu: 'horizontal', // vertical, collapsible-vertical, horizontal
     layout: 'full', // full, boxed-layout
     rtlClass: 'ltr', // rtl, ltr
     animation: '', // animate__fadeIn, animate__fadeInDown, animate__fadeInUp, animate__fadeInLeft, animate__fadeInRight, animate__slideInDown, animate__slideInLeft, animate__slideInRight, animate__zoomIn