yys 6 dienas atpakaļ
vecāks
revīzija
8840640c25
100 mainītis faili ar 3728 papildinājumiem un 924 dzēšanām
  1. 160 0
      src/assets/styles/element-ui.scss
  2. 39 6
      src/assets/styles/index.scss
  3. 12 7
      src/assets/styles/sidebar.scss
  4. 25 26
      src/assets/styles/variables.scss
  5. 61 21
      src/components/TopNav/index.vue
  6. 7 7
      src/layout/components/AppMain.vue
  7. 168 69
      src/layout/components/Navbar.vue
  8. 1 3
      src/layout/components/Sidebar/Item.vue
  9. 65 38
      src/layout/components/Sidebar/index.vue
  10. 2 2
      src/layout/components/TagsView/index.vue
  11. 101 43
      src/layout/index.vue
  12. 101 0
      src/router/index.js
  13. 1 1
      src/store/modules/settings.js
  14. 6 2
      src/utils/request.js
  15. 4 0
      src/views/FastGptExtUserTag/index.vue
  16. 98 19
      src/views/FastGptExtUserTag/index/index.vue
  17. 5 0
      src/views/ad/adDyApi/index.vue
  18. 98 19
      src/views/ad/adDyApi/index/index.vue
  19. 5 0
      src/views/ad/clickLog/index.vue
  20. 98 19
      src/views/ad/clickLog/index/index.vue
  21. 14 7
      src/views/admin/ad/index.vue
  22. 4 1
      src/views/admin/aiChatQuality/index.vue
  23. 8 16
      src/views/admin/aiProvider/index.vue
  24. 11 2
      src/views/admin/article/index.vue
  25. 4 1
      src/views/admin/callRecord/index.vue
  26. 11 2
      src/views/admin/course/index.vue
  27. 14 7
      src/views/admin/crm/index.vue
  28. 11 2
      src/views/admin/live/index.vue
  29. 72 60
      src/views/admin/menu.js
  30. 64 34
      src/views/admin/moduleUsage/index.vue
  31. 11 2
      src/views/admin/product/index.vue
  32. 20 3
      src/views/admin/proxy/index.vue
  33. 4 1
      src/views/admin/qwExternalContact/index.vue
  34. 14 7
      src/views/admin/sop/index.vue
  35. 4 1
      src/views/admin/statistics/index.vue
  36. 14 7
      src/views/admin/storeOrder/index.vue
  37. 36 0
      src/views/admin/sysCompany/index.vue
  38. 4 1
      src/views/bill/billLog/index.vue
  39. 101 22
      src/views/callRecord/index/index.vue
  40. 10 5
      src/views/chat/chatDataset/index.vue
  41. 11 5
      src/views/chat/chatRole/index.vue
  42. 11 6
      src/views/chat/chatSession/index.vue
  43. 12 6
      src/views/company/company/index.vue
  44. 4 1
      src/views/company/companyBindUser/index.vue
  45. 11 5
      src/views/company/companyDept/index.vue
  46. 9 3
      src/views/company/companyDomain/index.vue
  47. 10 4
      src/views/company/companyDomainBind/index.vue
  48. 11 5
      src/views/company/companyMenu/index.vue
  49. 11 5
      src/views/company/companyMoneyLogs/index.vue
  50. 11 5
      src/views/company/companyPost/index.vue
  51. 8 3
      src/views/company/companyProfit/index.vue
  52. 9 3
      src/views/company/companyRecharge/index.vue
  53. 4 1
      src/views/company/companyRedPacketBalanceLogs/index.vue
  54. 11 5
      src/views/company/companyRole/index.vue
  55. 11 5
      src/views/company/companySms/index.vue
  56. 4 1
      src/views/company/companyTraffic/index.vue
  57. 4 1
      src/views/company/companyTrafficLog/index.vue
  58. 9 3
      src/views/company/companyUser/index.vue
  59. 4 1
      src/views/company/companyWorkflow/index.vue
  60. 4 1
      src/views/company/workflowExternalApi/index.vue
  61. 11 5
      src/views/company/wxAccount/index.vue
  62. 6 2
      src/views/company/wxUser/index.vue
  63. 5 0
      src/views/course/courseAnswerLog/index.vue
  64. 98 19
      src/views/course/courseAnswerLog/index/index.vue
  65. 5 0
      src/views/course/courseQuestionCategory/index.vue
  66. 98 19
      src/views/course/courseQuestionCategory/index/index.vue
  67. 98 19
      src/views/course/index/index.vue
  68. 5 0
      src/views/course/period/index.vue
  69. 98 19
      src/views/course/period/index/index.vue
  70. 5 0
      src/views/course/playSourceConfig/index.vue
  71. 98 19
      src/views/course/playSourceConfig/index/index.vue
  72. 5 0
      src/views/course/sopLogs/index.vue
  73. 98 19
      src/views/course/sopLogs/index/index.vue
  74. 5 0
      src/views/course/trainingCamp/index.vue
  75. 98 19
      src/views/course/trainingCamp/index/index.vue
  76. 5 0
      src/views/course/userCourseCommentLike/index.vue
  77. 98 19
      src/views/course/userCourseCommentLike/index/index.vue
  78. 5 0
      src/views/course/userCourseFavorite/index.vue
  79. 98 19
      src/views/course/userCourseFavorite/index/index.vue
  80. 5 0
      src/views/course/userCourseNoteLike/index.vue
  81. 98 19
      src/views/course/userCourseNoteLike/index/index.vue
  82. 5 0
      src/views/course/userCourseVideo/index.vue
  83. 98 19
      src/views/course/userCourseVideo/index/index.vue
  84. 5 0
      src/views/course/userTalentFollow/index.vue
  85. 98 19
      src/views/course/userTalentFollow/index/index.vue
  86. 5 0
      src/views/course/userVideoCommentLike/index.vue
  87. 98 19
      src/views/course/userVideoCommentLike/index/index.vue
  88. 5 0
      src/views/course/userVideoFavorite/index.vue
  89. 98 19
      src/views/course/userVideoFavorite/index/index.vue
  90. 5 0
      src/views/course/userVideoLike/index.vue
  91. 98 19
      src/views/course/userVideoLike/index/index.vue
  92. 5 0
      src/views/course/userVideoView/index.vue
  93. 98 19
      src/views/course/userVideoView/index/index.vue
  94. 5 0
      src/views/course/videoTags/index.vue
  95. 98 19
      src/views/course/videoTags/index/index.vue
  96. 4 0
      src/views/courseFinishTemp/course/index.vue
  97. 98 19
      src/views/courseFinishTemp/course/index/index.vue
  98. 10 5
      src/views/crm/customer/index.vue
  99. 98 19
      src/views/crm/customerAssign/index/index.vue
  100. 98 19
      src/views/crm/customerLevel/index/index.vue

+ 160 - 0
src/assets/styles/element-ui.scss

@@ -52,6 +52,8 @@
   left: 0;
   position: relative;
   margin: 0 auto;
+  border-radius: 8px;
+  overflow: hidden;
 }
 
 // refine element ui upload
@@ -90,3 +92,161 @@
 .el-submenu__icon-arrow {
   display: none;
 }
+
+// ============================
+// 全局主题覆盖 — Indigo 配色
+// ============================
+
+// 主要按钮
+.el-button--primary {
+  background-color: #4F46E5;
+  border-color: #4F46E5;
+
+  &:hover, &:focus {
+    background-color: #6366F1;
+    border-color: #6366F1;
+  }
+
+  &:active {
+    background-color: #4338CA;
+    border-color: #4338CA;
+  }
+
+  &.is-plain {
+    color: #4F46E5;
+    background-color: #EDE9FE;
+    border-color: #C4B5FD;
+
+    &:hover, &:focus {
+      background-color: #4F46E5;
+      border-color: #4F46E5;
+      color: #fff;
+    }
+  }
+}
+
+// 成功按钮
+.el-button--success {
+  background-color: #10B981;
+  border-color: #10B981;
+
+  &:hover, &:focus {
+    background-color: #34D399;
+    border-color: #34D399;
+  }
+}
+
+// 危险按钮
+.el-button--danger {
+  background-color: #EF4444;
+  border-color: #EF4444;
+
+  &:hover, &:focus {
+    background-color: #F87171;
+    border-color: #F87171;
+  }
+}
+
+// 警告按钮
+.el-button--warning {
+  background-color: #F59E0B;
+  border-color: #F59E0B;
+
+  &:hover, &:focus {
+    background-color: #FBBF24;
+    border-color: #FBBF24;
+  }
+}
+
+// 输入框聚焦
+.el-input__inner:focus,
+.el-textarea__inner:focus {
+  border-color: #4F46E5;
+}
+
+// 分页组件激活色
+.el-pagination.is-background .el-pager li:not(.disabled).active {
+  background-color: #4F46E5;
+}
+
+// Switch 组件激活色
+.el-switch.is-checked .el-switch__core {
+  border-color: #4F46E5;
+  background-color: #4F46E5;
+}
+
+// Radio 激活色
+.el-radio__input.is-checked .el-radio__inner {
+  border-color: #4F46E5;
+  background: #4F46E5;
+}
+
+.el-radio__input.is-checked + .el-radio__label {
+  color: #4F46E5;
+}
+
+// Checkbox 激活色
+.el-checkbox__input.is-checked .el-checkbox__inner {
+  background-color: #4F46E5;
+  border-color: #4F46E5;
+}
+
+.el-checkbox__input.is-checked + .el-checkbox__label {
+  color: #4F46E5;
+}
+
+// Select 选中色
+.el-select .el-input.is-focus .el-input__inner {
+  border-color: #4F46E5;
+}
+
+// Tabs 激活下划线
+.el-tabs__item.is-active {
+  color: #4F46E5;
+}
+
+.el-tabs__active-bar {
+  background-color: #4F46E5;
+}
+
+// Tag 组件
+.el-tag--primary {
+  background-color: #EDE9FE;
+  border-color: #C4B5FD;
+  color: #4F46E5;
+}
+
+// Steps 激活色
+.el-step__head.is-finish {
+  color: #4F46E5;
+  border-color: #4F46E5;
+}
+
+.el-step__title.is-finish {
+  color: #4F46E5;
+}
+
+// Table 排序图标激活
+.el-table__sort-caret.ascending {
+  border-bottom-color: #4F46E5;
+}
+
+.el-table__sort-caret.descending {
+  border-top-color: #4F46E5;
+}
+
+// 链接文字色
+.el-link--primary {
+  color: #4F46E5;
+
+  &:hover {
+    color: #6366F1;
+  }
+}
+
+// 日期选择器选中日期
+.el-date-table td.current:not(.disabled) span,
+.el-date-table td.end-date span,
+.el-date-table td.start-date span {
+  background-color: #4F46E5;
+}

+ 39 - 6
src/assets/styles/index.scss

@@ -10,7 +10,8 @@ body {
   -moz-osx-font-smoothing: grayscale;
   -webkit-font-smoothing: antialiased;
   text-rendering: optimizeLegibility;
-  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
+  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", 微软雅黑, Arial, sans-serif;
+  background-color: $page-bg;
 }
 
 label {
@@ -119,12 +120,13 @@ aside {
   }
 }
 
-//main-container全局样式
+//main-container全局样式 — 参考 Token 管理端卡片样式
 .app-container {
   background-color: #fff;
-  margin: 10px;
-
+  margin: 16px 24px;
   padding: 20px;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
 }
 
 .components-container {
@@ -133,7 +135,8 @@ aside {
 }
 
 .pagination-container {
-  margin-top: 30px;
+  margin-top: 20px;
+  text-align: right;
 }
 
 .text-center {
@@ -195,4 +198,34 @@ aside {
 .el-dialog__footer{
   border-top: 1px solid #DCDFE6;
 }
- 
+
+// 全局表格样式增强 — 参考 Token 管理端
+.el-table {
+  th {
+    background-color: #fafafa !important;
+    color: #303133;
+    font-weight: 500;
+  }
+
+  td {
+    color: #555;
+  }
+
+  .el-button--text {
+    font-size: 13px;
+  }
+}
+
+// 全局页面标题
+.page-title {
+  font-size: 24px;
+  font-weight: 700;
+  color: #1E293B;
+  margin: 0 0 4px;
+}
+
+.page-subtitle {
+  font-size: 14px;
+  color: #94A3B8;
+  margin: 0;
+}

+ 12 - 7
src/assets/styles/sidebar.scss

@@ -72,11 +72,11 @@
       white-space: nowrap !important;
     }
 
-    // menu hover
+    // menu hover — 白色主题
     .submenu-title-noDropdown,
     .el-submenu__title {
       &:hover {
-        background-color: rgba(0, 0, 0, 0.06) !important;
+        background-color: rgba(79, 70, 229, 0.04) !important;
       }
     }
 
@@ -89,7 +89,7 @@
       min-width: $base-sidebar-width !important;
 
       &:hover {
-        background-color: rgba(0, 0, 0, 0.06) !important;
+        background-color: rgba(79, 70, 229, 0.04) !important;
       }
     }
 
@@ -101,6 +101,12 @@
         background-color: $base-sub-menu-hover !important;
       }
     }
+
+    // 白色主题下的激活样式
+    .el-menu-item.is-active {
+      color: #4F46E5 !important;
+      background-color: #EDE9FE !important;
+    }
   }
 
   .hideSidebar {
@@ -197,13 +203,12 @@
   .nest-menu .el-submenu>.el-submenu__title,
   .el-menu-item {
     &:hover {
-      // you can use $subMenuHover
-      background-color: rgba(0, 0, 0, 0.06) !important;
+      background-color: rgba(79, 70, 229, 0.04) !important;
     }
   }
 
-  // the scroll bar appears when the subMenu is too long
-  >.el-menu--popup {
+  // 激活菜单项弹出子菜单
+  .el-menu--popup {
     max-height: 100vh;
     overflow-y: auto;
 

+ 25 - 26
src/assets/styles/variables.scss

@@ -1,41 +1,40 @@
-// base color
-$blue:#324157;
-$light-blue: #3a71a8;
-$red:#C03639;
+// base color — 参考 Token 管理端配色
+$blue:#3B82F6;
+$light-blue: #4F46E5;
+$red:#EF4444;
 $pink: #E65D6E;
-$green: #30B08F;
+$green: #10B981;
 $tiffany: #4AB7BD;
-$yellow:#FEC171;
-$panGreen: #30B08F;
-
-// 默认菜单主题风格
+$yellow:#F59E0B;
+$panGreen: #10B981;
+
+// 主题色(Indigo-600)
+$primary: #4F46E5;
+$primary-light: #EDE9FE;
+$primary-dark: #4338CA;
+
+// 页面背景色
+$page-bg: #F5F6FA;
+$border-color: #F0F0F0;
+$text-primary: #303133;
+$text-regular: #555555;
+$text-secondary: #94A3B8;
+$heading-color: #1E293B;
+
+// 默认菜单主题风格(深色 — 经典模式用)
 $base-menu-color:#bfcbd9;
 $base-menu-color-active:#f4f4f5;
 $base-menu-background: #304156;
 $base-logo-title-color: #ffffff;
 
-$base-menu-light-color:rgba(0,0,0,.70);
+// 浅色菜单主题风格(topNav 模式左侧栏用)
+$base-menu-light-color:#555555;
 $base-menu-light-background:#ffffff;
-$base-logo-light-title-color: #001529;
+$base-logo-light-title-color: #1E293B;
 
 $base-sub-menu-background:#1f2d3d;
 $base-sub-menu-hover:#001528;
 
-// 自定义暗色菜单风格
-/**
-$base-menu-color:hsla(0,0%,100%,.65);
-$base-menu-color-active:#fff;
-$base-menu-background:#001529;
-$base-logo-title-color: #ffffff;
-
-$base-menu-light-color:rgba(0,0,0,.70);
-$base-menu-light-background:#ffffff;
-$base-logo-light-title-color: #001529;
-
-$base-sub-menu-background:#000c17;
-$base-sub-menu-hover:#001528;
-*/
-
 $base-sidebar-width: 200px;
 
 // the :export directive is the magic sauce for webpack

+ 61 - 21
src/components/TopNav/index.vue

@@ -3,6 +3,7 @@
     :default-active="activeMenu"
     mode="horizontal"
     @select="handleSelect"
+    class="topmenu-container"
   >
     <template v-for="(item, index) in topMenus">
       <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber"
@@ -34,7 +35,7 @@ export default {
   data() {
     return {
       // 顶部栏初始数
-      visibleNumber: 8,
+      visibleNumber: 12,
       // 是否为首次加载
       isFrist: false,
       // 当前激活菜单的 index
@@ -169,27 +170,66 @@ export default {
 </script>
 
 <style lang="scss">
-.topmenu-container.el-menu--horizontal > .el-menu-item {
-  float: left;
-  height: 50px !important;
-  line-height: 50px !important;
-  color: #999093 !important;
-  padding: 0 5px !important;
-  margin: 0 10px !important;
-}
+/* 顶部菜单样式 — 参考 Token 管理端 */
+.topmenu-container.el-menu--horizontal {
+  border-bottom: none !important;
 
-.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
-  border-bottom: 2px solid #{'var(--theme)'} !important;
-  color: #303133;
-}
+  & > .el-menu-item {
+    float: left;
+    height: 56px !important;
+    line-height: 56px !important;
+    color: #555 !important;
+    font-size: 14px;
+    font-weight: 500;
+    padding: 0 16px !important;
+    margin: 0 4px !important;
+    border-bottom: 2px solid transparent !important;
+    background: transparent !important;
+
+    &:hover {
+      color: #303133 !important;
+      background: transparent !important;
+    }
+
+    &.is-active {
+      color: #4F46E5 !important;
+      border-bottom: 2px solid #4F46E5 !important;
+      background: transparent !important;
+    }
+
+    .svg-icon {
+      margin-right: 6px;
+      font-size: 16px;
+    }
+  }
 
-/* submenu item */
-.topmenu-container.el-menu--horizontal > .el-submenu .el-submenu__title {
-  float: left;
-  height: 50px !important;
-  line-height: 50px !important;
-  color: #999093 !important;
-  padding: 0 5px !important;
-  margin: 0 10px !important;
+  & > .el-submenu {
+    .el-submenu__title {
+      height: 56px !important;
+      line-height: 56px !important;
+      color: #555 !important;
+      font-size: 14px;
+      font-weight: 500;
+      padding: 0 16px !important;
+      margin: 0 4px !important;
+      border-bottom: 2px solid transparent !important;
+      background: transparent !important;
+
+      &:hover {
+        color: #303133 !important;
+        background: transparent !important;
+      }
+
+      .svg-icon {
+        margin-right: 6px;
+        font-size: 16px;
+      }
+    }
+
+    &.is-active .el-submenu__title {
+      color: #4F46E5 !important;
+      border-bottom: 2px solid #4F46E5 !important;
+    }
+  }
 }
 </style>

+ 7 - 7
src/layout/components/AppMain.vue

@@ -24,26 +24,26 @@ export default {
 
 <style lang="scss" scoped>
 .app-main {
-  background-color: #f0f2f5;
-  /* 50= navbar  50  */
-  min-height: calc(100vh - 50px);
+  background-color: #f5f6fa;
+  /* 56= navbar 56px */
+  min-height: calc(100vh - 56px);
   width: 100%;
   position: relative;
   overflow: hidden;
 }
 
 .fixed-header+.app-main {
-  padding-top: 50px;
+  padding-top: 56px;
 }
 
 .hasTagsView {
   .app-main {
-    /* 84 = navbar + tags-view = 50 + 34 */
-    min-height: calc(100vh - 84px);
+    /* 90 = navbar + tags-view = 56 + 34 */
+    min-height: calc(100vh - 90px);
   }
 
   .fixed-header+.app-main {
-    padding-top: 84px;
+    padding-top: 90px;
   }
 }
 </style>

+ 168 - 69
src/layout/components/Navbar.vue

@@ -1,35 +1,40 @@
 <template>
-  <div class="navbar">
-    <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
+  <div class="navbar" :class="{'topnav-mode': topNav}">
+    <!-- Logo 区域 -->
+    <div class="navbar-left">
+      <router-link to="/" class="logo-link">
+        <img v-if="logImg" :src="logImg" class="logo-img" />
+        <span class="logo-title">{{ title }}</span>
+      </router-link>
+    </div>
+
+    <!-- 顶部一级菜单 (topNav模式) -->
+    <top-nav v-if="topNav" class="topmenu-container" />
 
-    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
-    <top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/>
+    <!-- 面包屑 (经典模式) -->
+    <template v-else>
+      <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
+      <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
+    </template>
 
+    <!-- 右侧用户区域 -->
     <div class="right-menu">
       <template v-if="device!=='mobile'">
-        <tenant-selector v-if="showTenantSelector" class="right-menu-item" />
-        <search id="header-search" class="right-menu-item" />
-
         <screenfull id="screenfull" class="right-menu-item hover-effect" />
-
-        <el-tooltip content="布局大小" effect="dark" placement="bottom">
-          <size-select id="size-select" class="right-menu-item hover-effect" />
-        </el-tooltip>
-
       </template>
 
       <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
         <div class="avatar-wrapper">
-          <img :src="logImg" class="user-avatar">
+          <div class="avatar-icon">
+            <span>{{ userNameFirst }}</span>
+          </div>
+          <span class="avatar-name">{{ nickName }}</span>
           <i class="el-icon-caret-bottom" />
         </div>
         <el-dropdown-menu slot="dropdown">
           <router-link to="/user/profile">
             <el-dropdown-item>个人中心</el-dropdown-item>
           </router-link>
-          <el-dropdown-item @click.native="setting = true">
-            <span>布局设置</span>
-          </el-dropdown-item>
           <el-dropdown-item divided @click.native="logout">
             <span>退出登录</span>
           </el-dropdown-item>
@@ -45,47 +50,36 @@ import Breadcrumb from '@/components/Breadcrumb'
 import TopNav from '@/components/TopNav'
 import Hamburger from '@/components/Hamburger'
 import Screenfull from '@/components/Screenfull'
-import SizeSelect from '@/components/SizeSelect'
-import Search from '@/components/HeaderSearch'
-import TenantSelector from '@/components/TenantSelector'
-
 
 export default {
   components: {
     Breadcrumb,
     TopNav,
     Hamburger,
-    Screenfull,
-    SizeSelect,
-    Search,
-    TenantSelector
+    Screenfull
   },
   computed: {
     ...mapGetters([
       'sidebar',
       'avatar',
       'device',
-      'selectedCompanyId'
+      'name'
     ]),
-    showTenantSelector() {
-      // 平台管理员始终显示租户选择器
-      return true
+    topNav() {
+      return this.$store.state.settings.topNav
     },
-    setting: {
-      get() {
-        return this.$store.state.settings.showSettings
-      },
-      set(val) {
-        this.$store.dispatch('settings/changeSetting', {
-          key: 'showSettings',
-          value: val
-        })
-      }
+    title() {
+      return process.env.VUE_APP_TITLE_INDEX || '云联融智'
     },
-    topNav: {
-      get() {
-        return this.$store.state.settings.topNav
-      }
+    nickName() {
+      return this.$store.getters && this.$store.getters.nickName || '管理员'
+    },
+    userNameFirst() {
+      const name = this.nickName
+      return name ? name.charAt(0) : '管'
+    },
+    logImg() {
+      return require(process.env.VUE_APP_LOG_URL)
     }
   },
   methods: {
@@ -109,11 +103,41 @@ export default {
 
 <style lang="scss" scoped>
 .navbar {
-  height: 50px;
+  height: 56px;
   overflow: hidden;
   position: relative;
   background: #fff;
-  box-shadow: 0 1px 4px rgba(0,21,41,.08);
+  border-bottom: 1px solid #f0f0f0;
+  box-shadow: 0 1px 4px rgba(0,21,41,.04);
+  display: flex;
+  align-items: center;
+  padding: 0 20px;
+
+  .navbar-left {
+    flex-shrink: 0;
+    display: flex;
+    align-items: center;
+
+    .logo-link {
+      display: flex;
+      align-items: center;
+      text-decoration: none;
+      outline: none;
+
+      .logo-img {
+        width: 30px;
+        height: 30px;
+        margin-right: 10px;
+      }
+
+      .logo-title {
+        font-size: 15px;
+        font-weight: 600;
+        color: #303133;
+        white-space: nowrap;
+      }
+    }
+  }
 
   .hamburger-container {
     line-height: 46px;
@@ -121,7 +145,6 @@ export default {
     float: left;
     cursor: pointer;
     transition: background .3s;
-    -webkit-tap-highlight-color:transparent;
 
     &:hover {
       background: rgba(0, 0, 0, .025)
@@ -133,31 +156,27 @@ export default {
   }
 
   .topmenu-container {
-    position: absolute;
-    left: 50px;
-  }
-
-  .errLog-container {
-    display: inline-block;
-    vertical-align: top;
+    flex: 1;
+    min-width: 0;
   }
 
   .right-menu {
-    float: right;
+    flex-shrink: 0;
     height: 100%;
-    line-height: 50px;
+    display: flex;
+    align-items: center;
 
     &:focus {
       outline: none;
     }
 
     .right-menu-item {
-      display: inline-block;
+      display: inline-flex;
+      align-items: center;
       padding: 0 8px;
       height: 100%;
       font-size: 18px;
       color: #5a5e66;
-      vertical-align: text-bottom;
 
       &.hover-effect {
         cursor: pointer;
@@ -170,27 +189,107 @@ export default {
     }
 
     .avatar-container {
-      margin-right: 30px;
+      margin-left: 10px;
 
       .avatar-wrapper {
-        margin-top: 5px;
-        position: relative;
-
-        .user-avatar {
-          cursor: pointer;
-          width: 40px;
-          height: 40px;
-          border-radius: 10px;
+        display: flex;
+        align-items: center;
+        cursor: pointer;
+
+        .avatar-icon {
+          width: 30px;
+          height: 30px;
+          border-radius: 8px;
+          background: linear-gradient(135deg, #4F46E5, #7C3AED);
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          color: #fff;
+          font-size: 13px;
+          font-weight: 600;
+        }
+
+        .avatar-name {
+          margin-left: 8px;
+          font-size: 14px;
+          color: #303133;
+          max-width: 100px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
         }
 
         .el-icon-caret-bottom {
-          cursor: pointer;
-          position: absolute;
-          right: -20px;
-          top: 25px;
+          margin-left: 4px;
           font-size: 12px;
+          color: #999;
+        }
+      }
+    }
+  }
+}
+
+/* topNav 模式下的菜单样式覆盖 */
+.navbar.topnav-mode {
+  ::v-deep .topmenu-container.el-menu--horizontal {
+    border-bottom: none !important;
+    height: 56px;
+    display: flex;
+    align-items: center;
+
+    & > .el-menu-item {
+      height: 56px !important;
+      line-height: 56px !important;
+      color: #555 !important;
+      font-size: 14px;
+      font-weight: 500;
+      padding: 0 16px !important;
+      margin: 0 4px !important;
+      border-bottom: 2px solid transparent !important;
+
+      &:hover {
+        color: #303133 !important;
+        background: transparent !important;
+      }
+
+      &.is-active {
+        color: #4F46E5 !important;
+        border-bottom: 2px solid #4F46E5 !important;
+        background: transparent !important;
+      }
+
+      .svg-icon {
+        margin-right: 6px;
+        font-size: 16px;
+      }
+    }
+
+    & > .el-submenu {
+      .el-submenu__title {
+        height: 56px !important;
+        line-height: 56px !important;
+        color: #555 !important;
+        font-size: 14px;
+        font-weight: 500;
+        padding: 0 16px !important;
+        margin: 0 4px !important;
+        border-bottom: 2px solid transparent !important;
+
+        &:hover {
+          color: #303133 !important;
+          background: transparent !important;
+        }
+
+        .svg-icon {
+          margin-right: 6px;
+          font-size: 16px;
         }
       }
+
+      &.is-active .el-submenu__title {
+        color: #4F46E5 !important;
+        border-bottom: 2px solid #4F46E5 !important;
+      }
     }
   }
 }

+ 1 - 3
src/layout/components/Sidebar/Item.vue

@@ -16,9 +16,7 @@ export default {
     const { icon, title } = context.props
     const vnodes = []
 
-    if (icon) {
-      vnodes.push(<svg-icon icon-class={icon}/>)
-    }
+    vnodes.push(<svg-icon icon-class={icon || 'tree-table'}/>)
 
     if (title) {
       vnodes.push(<span slot='title'>{(title)}</span>)

+ 65 - 38
src/layout/components/Sidebar/index.vue

@@ -1,17 +1,16 @@
 <template>
-  <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
-    <logo v-if="showLogo" :collapse="isCollapse" />
-    <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
+  <div class="sidebar-wrapper" :style="{ backgroundColor: '#fff' }">
+    <el-scrollbar wrap-class="scrollbar-wrapper">
       <el-menu
         :default-active="activeMenu"
         :collapse="isCollapse"
-        :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
-        :text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
+        :background-color="'#fff'"
+        :text-color="'#555'"
         :unique-opened="true"
-        :active-text-color="settings.theme"
+        :active-text-color="'#4F46E5'"
         :collapse-transition="false"
         mode="vertical"
-        class="custom-menu"
+        class="sidebar-menu"
       >
         <sidebar-item
           v-for="(route, index) in sidebarRouters"
@@ -26,59 +25,87 @@
 
 <script>
 import { mapGetters, mapState } from "vuex";
-import Logo from "./Logo";
 import SidebarItem from "./SidebarItem";
-import variables from "@/assets/styles/variables.scss";
 
 export default {
-  components: { SidebarItem, Logo },
+  components: { SidebarItem },
   computed: {
     ...mapState(["settings"]),
     ...mapGetters(["sidebarRouters", "sidebar"]),
     activeMenu() {
       const route = this.$route;
       const { meta, path } = route;
-      // if set path, the sidebar will highlight the path you set
       if (meta.activeMenu) {
         return meta.activeMenu;
       }
       return path;
     },
-    showLogo() {
-      return this.$store.state.settings.sidebarLogo;
-    },
-    variables() {
-      return variables;
-    },
     isCollapse() {
       return !this.sidebar.opened;
     }
   }
 };
 </script>
+
 <style lang="scss" scoped>
+.sidebar-wrapper {
+  width: 200px;
+  height: 100%;
+  background: #fff;
+  border-right: 1px solid #f0f0f0;
 
+  .sidebar-menu {
+    border: none;
+    height: 100%;
+    width: 100% !important;
 
-.custom-menu ::v-deep .el-menu-item{
-  width: 90%;
-  margin: auto;
-}
-//.custom-menu ::v-deep .el-menu-item:hover{
-//  background: linear-gradient(270deg, rgba(29, 141, 245, 0.2) 0%, rgba(29, 141, 245, 0.2) 100%)!important;
-//  width: 90%;
-//  margin: auto;
-//  border-radius: 6px;
-//}
-.custom-menu ::v-deep .el-menu-item.is-active {
-  //background-color: #006CFF!important;
-  color: #F2B680 !important;
-  width: 90%;
-  margin: auto;
-  border-radius: 6px;
-}
-//.custom-menu ::v-deep .el-menu-item.is-active{
-//  background: linear-gradient(270deg, #006CFF 0%, #006CFF 100%)!important;
-//
-//}
+    ::v-deep .el-menu-item {
+      height: 44px;
+      line-height: 44px;
+      font-size: 14px;
+      color: #555;
+      padding-left: 20px !important;
+
+      &:hover {
+        background-color: rgba(79, 70, 229, 0.04) !important;
+      }
+
+      &.is-active {
+        color: #4F46E5 !important;
+        background-color: #EDE9FE !important;
+        border-radius: 0;
+        font-weight: 500;
+      }
+    }
+
+    ::v-deep .el-submenu__title {
+      height: 44px;
+      line-height: 44px;
+      font-size: 14px;
+      color: #555;
+      padding-left: 20px !important;
+      font-weight: 500;
 
+      &:hover {
+        background-color: rgba(79, 70, 229, 0.04) !important;
+      }
+
+      .svg-icon {
+        margin-right: 10px;
+        font-size: 16px;
+      }
+    }
+
+    ::v-deep .el-submenu .el-menu-item {
+      padding-left: 44px !important;
+      font-size: 14px;
+      font-weight: 400;
+      min-width: auto !important;
+    }
+
+    ::v-deep .el-submenu .el-submenu .el-menu-item {
+      padding-left: 60px !important;
+    }
+  }
+}
 </style>

+ 2 - 2
src/layout/components/TagsView/index.vue

@@ -266,9 +266,9 @@ export default {
         margin-right: 15px;
       }
       &.active {
-        background-color: #42b983;
+        background-color: #4F46E5;
         color: #fff;
-        border-color: #42b983;
+        border-color: #4F46E5;
         &::before {
           content: '';
           background: #fff;

+ 101 - 43
src/layout/index.vue

@@ -1,17 +1,33 @@
 <template>
   <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
-    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
-    <sidebar class="sidebar-container"/>
-    <div :class="{hasTagsView:needTagsView}" class="main-container">
-      <div :class="{'fixed-header':fixedHeader}">
-        <navbar />
-        <tags-view v-if="needTagsView" />
+    <!-- topNav 模式:全宽顶部栏 + 左侧子菜单 -->
+    <template v-if="topNav">
+      <div class="topnav-layout">
+        <navbar class="full-navbar" />
+        <div class="topnav-body">
+          <sidebar v-if="hasSidebarRoutes" class="sidebar-container" />
+          <div :class="{hasTagsView:needTagsView}" class="main-container">
+            <tags-view v-if="needTagsView" />
+            <app-main />
+          </div>
+        </div>
       </div>
-      <app-main />
-      <right-panel>
-        <settings />
-      </right-panel>
-    </div>
+    </template>
+    <!-- 经典模式:左侧全高侧栏 -->
+    <template v-else>
+      <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
+      <sidebar class="sidebar-container"/>
+      <div :class="{hasTagsView:needTagsView}" class="main-container">
+        <div :class="{'fixed-header':fixedHeader}">
+          <navbar />
+          <tags-view v-if="needTagsView" />
+        </div>
+        <app-main />
+        <right-panel>
+          <settings />
+        </right-panel>
+      </div>
+    </template>
   </div>
 </template>
 
@@ -42,6 +58,13 @@ export default {
       needTagsView: state => state.settings.tagsView,
       fixedHeader: state => state.settings.fixedHeader
     }),
+    topNav() {
+      return this.$store.state.settings.topNav
+    },
+    hasSidebarRoutes() {
+      const routes = this.$store.getters.sidebarRouters
+      return routes && routes.length > 0
+    },
     classObj() {
       return {
         hideSidebar: !this.sidebar.opened,
@@ -63,45 +86,80 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-  @import "~@/assets/styles/mixin.scss";
-  @import "~@/assets/styles/variables.scss";
-
-  .app-wrapper {
-    @include clearfix;
-    position: relative;
-    height: 100%;
-    width: 100%;
-
-    &.mobile.openSidebar {
-      position: fixed;
-      top: 0;
-    }
-  }
+@import "~@/assets/styles/mixin.scss";
+@import "~@/assets/styles/variables.scss";
 
-  .drawer-bg {
-    background: #000;
-    opacity: 0.3;
-    width: 100%;
-    top: 0;
-    height: 100%;
-    position: absolute;
-    z-index: 999;
-  }
+.app-wrapper {
+  @include clearfix;
+  position: relative;
+  height: 100%;
+  width: 100%;
 
-  .fixed-header {
+  &.mobile.openSidebar {
     position: fixed;
     top: 0;
-    right: 0;
-    z-index: 9;
-    width: calc(100% - #{$base-sidebar-width});
-    transition: width 0.28s;
   }
+}
+
+.drawer-bg {
+  background: #000;
+  opacity: 0.3;
+  width: 100%;
+  top: 0;
+  height: 100%;
+  position: absolute;
+  z-index: 999;
+}
 
-  .hideSidebar .fixed-header {
-    width: calc(100% - 54px)
+.fixed-header {
+  position: fixed;
+  top: 0;
+  right: 0;
+  z-index: 9;
+  width: calc(100% - #{$base-sidebar-width});
+  transition: width 0.28s;
+}
+
+.hideSidebar .fixed-header {
+  width: calc(100% - 54px)
+}
+
+.mobile .fixed-header {
+  width: 100%;
+}
+
+/* topNav 全宽布局 */
+.topnav-layout {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+
+  .full-navbar {
+    flex-shrink: 0;
+    z-index: 1002;
   }
 
-  .mobile .fixed-header {
-    width: 100%;
+  .topnav-body {
+    display: flex;
+    flex: 1;
+    overflow: hidden;
+    background: #f5f6fa;
+
+    .sidebar-container {
+      flex-shrink: 0;
+      position: relative !important;
+      top: auto !important;
+      height: 100% !important;
+      box-shadow: none !important;
+      border-right: 1px solid #f0f0f0;
+    }
+
+    .main-container {
+      flex: 1;
+      overflow: auto;
+      margin-left: 0 !important;
+      min-height: 0;
+    }
   }
+}
 </style>

+ 101 - 0
src/router/index.js

@@ -5,6 +5,7 @@ Vue.use(Router)
 
 /* Layout */
 import Layout from '@/layout'
+import ParentView from '@/components/ParentView';
 import LiveConsole from "@/views/live/liveConsole/index.vue";
 
 
@@ -244,6 +245,106 @@ export const constantRoutes = [
     }
   ]
   },
+  // ======== 龙虾引擎 (Lobster Workflow Engine) ========
+  {
+    path: '/lobster',
+    component: Layout,
+    redirect: '/lobster/production-workflow',
+    name: 'Lobster',
+    meta: { title: '龙虾引擎', icon: 'system' },
+    children: [
+      {
+        path: 'production-workflow',
+        component: ParentView,
+        redirect: '/lobster/production-workflow/canvas',
+        name: 'ProductionWorkflow',
+        hidden: true,
+        meta: { title: 'AI生产工作流', icon: 'component' },
+        children: [
+          {
+            path: 'canvas',
+            component: () => import('@/views/lobster/workflow-canvas/index'),
+            name: 'LobsterCanvas',
+            hidden: true,
+            meta: { title: '工作流画布', icon: 'chart' }
+          },
+          {
+            path: 'template',
+            component: () => import('@/views/lobster/template/index'),
+            name: 'LobsterTemplate',
+            hidden: true,
+            meta: { title: '工作流模板库', icon: 'documentation' }
+          }
+        ]
+      },
+      {
+        path: 'workflow-generate',
+        component: () => import('@/views/lobster/workflow-generate/index'),
+        name: 'LobsterGenerate',
+        meta: { title: 'AI生成工作流', icon: 'build' }
+      },
+      {
+        path: 'instance',
+        component: () => import('@/views/lobster/instance/index'),
+        name: 'LobsterInstance',
+        meta: { title: '实例监控', icon: 'monitor' }
+      },
+      {
+        path: 'optimization',
+        component: () => import('@/views/lobster/optimization/index'),
+        name: 'LobsterOptimization',
+        meta: { title: 'AI优化建议', icon: 'eye-open' }
+      },
+      {
+        path: 'prompt',
+        component: () => import('@/views/lobster/prompt/index'),
+        name: 'LobsterPrompt',
+        meta: { title: '提示词管理', icon: 'edit' }
+      },
+      {
+        path: 'sales-corpus',
+        component: () => import('@/views/lobster/sales-corpus/index'),
+        name: 'SalesCorpus',
+        meta: { title: '销冠语料学习', icon: 'star' }
+      },
+      {
+        path: 'api-registry',
+        component: () => import('@/views/lobster/api-registry/index'),
+        name: 'LobsterApiRegistry',
+        meta: { title: '接口注册中心', icon: 'nested' }
+      },
+      {
+        path: 'dead-letter',
+        component: () => import('@/views/lobster/dead-letter/index'),
+        name: 'LobsterDeadLetter',
+        meta: { title: '死信队列', icon: 'bug' }
+      },
+      {
+        path: 'event-audit',
+        component: () => import('@/views/lobster/event-audit/index'),
+        name: 'LobsterEventAudit',
+        meta: { title: '节点审核', icon: 'checkbox' }
+      },
+      {
+        path: 'chat-aggregate',
+        component: () => import('@/views/lobster/chat-aggregate/index'),
+        name: 'ChatAggregate',
+        meta: { title: '聚合聊天', icon: 'message' }
+      },
+      {
+        path: 'model-config',
+        component: () => import('@/views/lobster/model-config/index'),
+        name: 'LobsterModelConfig',
+        meta: { title: '模型配置', icon: 'server' }
+      },
+      {
+        path: 'billing',
+        component: () => import('@/views/lobster/billing/index'),
+        name: 'LobsterBilling',
+        meta: { title: 'Token系数管理', icon: 'money' }
+      }
+    ]
+  },
 ]
 
 const originalPush = Router.prototype.push

+ 1 - 1
src/store/modules/settings.js

@@ -5,7 +5,7 @@ const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dyn
 const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
 const state = {
   title: '',
-  theme: storageSetting.theme || '#006CFF',
+  theme: storageSetting.theme || '#4F46E5',
   sideTheme: storageSetting.sideTheme || sideTheme,
   showSettings: showSettings,
   topNav:  storageSetting.topNav === undefined ? topNav : storageSetting.topNav,

+ 6 - 2
src/utils/request.js

@@ -23,10 +23,14 @@ service.interceptors.request.use(config => {
 
   // 是否需要设置 token
   const isToken = (config.headers || {}).isToken === false
+  // 始终发送 X-Frontend-Type 和 tenant-code(登录时也需要)
+  config.headers['X-Frontend-Type'] = 'admin'
+  const tenantCode = getTenantCode()
+  if (tenantCode) {
+    config.headers['tenant-code'] = tenantCode
+  }
   if (getToken() && !isToken) {
     config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
-    config.headers['X-Frontend-Type'] = 'admin'
-    config.headers['tenant-code'] = getTenantCode()
   }
   // get请求映射params参数
   if (config.method === 'get' && config.params) {

+ 4 - 0
src/views/FastGptExtUserTag/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,6 +62,7 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "",

+ 98 - 19
src/views/FastGptExtUserTag/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['FastGptExtUserTag:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['FastGptExtUserTag:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['FastGptExtUserTag:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "Fastgptextusertag",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/FastGptExtUserTag/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/FastGptExtUserTag/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/FastGptExtUserTag", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/FastGptExtUserTag", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/FastGptExtUserTag/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/ad/adDyApi/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Addyapi",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/ad/adDyApi/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['ad:adDyApi:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['ad:adDyApi:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['ad:adDyApi:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "AdAddyapi",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/ad/adDyApi/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/ad/adDyApi/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/ad/adDyApi", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/ad/adDyApi", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/ad/adDyApi/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/ad/clickLog/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Clicklog",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/ad/clickLog/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['ad:clickLog:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['ad:clickLog:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['ad:clickLog:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "AdClicklog",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/ad/clickLog/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/ad/clickLog/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/ad/clickLog", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/ad/clickLog", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/ad/clickLog/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 14 - 7
src/views/admin/ad/index.vue

@@ -1,13 +1,14 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="租户名称" prop="companyName">
+        <el-input v-model="queryParams.companyName" placeholder="请输入租户名称" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
       <el-form-item label="账户名称" prop="accountName">
         <el-input v-model="queryParams.accountName" placeholder="请输入账户名称" clearable size="small" @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="租户编号" prop="tenantCode">
-        <el-input v-model="queryParams.tenantCode" placeholder="请输入租户编号" clearable size="small" @keyup.enter.native="handleQuery" />
-      </el-form-item>
       <el-form-item>
+        <inline-tenant-selector @change="onTenantChange" />
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
@@ -21,7 +22,7 @@
     </el-row>
 
     <el-table border v-loading="loading" :data="list">
-      <el-table-column label="租户" align="center" prop="tenantLabel" min-width="150" />
+      <el-table-column label="租户名称" align="center" prop="companyName" min-width="150" />
       <el-table-column label="账户名称" align="center" prop="accountName" />
       <el-table-column label="平台" align="center" prop="platform" width="100" />
       <el-table-column label="状态" align="center" prop="status" width="100" />
@@ -35,14 +36,16 @@
 
 <script>
 import { listAdAccount } from '@/api/admin/ad'
+import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
   name: 'AdminAd',
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: false, exportLoading: false, showSearch: true,
       list: [], total: 0,
-      queryParams: { pageNum: 1, pageSize: 10, accountName: null, tenantCode: null }
+      queryParams: { pageNum: 1, pageSize: 10, accountName: null, companyName: null, companyId: null }
     }
   },
   created() { this.getList() },
@@ -50,13 +53,17 @@ export default {
     getList() {
       this.loading = true
       listAdAccount(this.queryParams).then(res => {
-        this.list = (res.rows || []).map(r => ({ ...r, tenantLabel: r.tenant_label || (r.tenant_code + ' | ' + r.tenant_name) }))
+        this.list = res.rows || []
         this.total = res.total || 0
         this.loading = false
       }).catch(() => { this.loading = false })
     },
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
-    resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
+    resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
     handleExport() { this.$message.info('导出功能开发中') }
   }
 }

+ 4 - 1
src/views/admin/aiChatQuality/index.vue

@@ -30,7 +30,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -137,6 +138,8 @@
 <script>
 import { listChatSessions, getSessionMessages, addQualityRecord } from '@/api/admin/aiChatQuality'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'AiChatQualityAdmin',
   data() {

+ 8 - 16
src/views/admin/aiProvider/index.vue

@@ -10,7 +10,7 @@
 
       <el-alert
         title="大模型管理说明"
-        description="统一管理大模型配置,支持豆包(Doubao)、通义千问(Qwen)、元宝/混元(Yuanbao)、DeepSeek 四种国产模型。所有模型均使用OpenAI兼容协议,配置后全局生效。"
+        description="统一管理大模型配置,固定支持豆包(Doubao)、通义千问(Qwen)、DeepSeek、智谱(Zhipu) 四种国产模型。所有模型均使用OpenAI兼容协议,配置后全局生效。"
         type="info"
         show-icon
         :closable="false"
@@ -59,8 +59,8 @@
           <el-select v-model="form.providerCode" placeholder="请选择" style="width: 100%" @change="handleProviderChange">
             <el-option label="豆包(Doubao)" value="doubao" />
             <el-option label="通义千问(Qwen)" value="qwen" />
-            <el-option label="元宝/混元(Yuanbao)" value="yuanbao" />
             <el-option label="DeepSeek" value="deepseek" />
+            <el-option label="智谱(Zhipu)" value="zhipu" />
           </el-select>
         </el-form-item>
         <el-form-item label="模型名称" prop="modelName">
@@ -72,12 +72,6 @@
         <el-form-item label="API Key" prop="apiKey">
           <el-input v-model="form.apiKey" placeholder="API Key" show-password />
         </el-form-item>
-        <el-form-item label="最大Token">
-          <el-input-number v-model="form.maxTokens" :min="256" :max="128000" :step="256" />
-        </el-form-item>
-        <el-form-item label="温度">
-          <el-slider v-model="form.temperature" :min="0" :max="2" :step="0.1" show-input />
-        </el-form-item>
         <el-form-item label="启用">
           <el-switch v-model="form.enabled" :active-value="1" :inactive-value="0" />
         </el-form-item>
@@ -103,7 +97,7 @@ export default {
       dialogTitle: '',
       form: {
         id: null, providerName: '', providerCode: '', modelName: '',
-        apiEndpoint: '', apiKey: '', maxTokens: 4096, temperature: 0.7, isDefault: 0, enabled: 1
+        apiEndpoint: '', apiKey: '', isDefault: 0, enabled: 1
       },
       rules: {
         providerName: [{ required: true, message: '请输入供应商名称', trigger: 'blur' }],
@@ -131,7 +125,7 @@ export default {
     },
     handleAdd() {
       this.dialogTitle = '新增模型'
-      this.form = { id: null, providerName: '', providerCode: '', modelName: '', apiEndpoint: '', apiKey: '', maxTokens: 4096, temperature: 0.7, isDefault: 0, enabled: 1 }
+      this.form = { id: null, providerName: '', providerCode: '', modelName: '', apiEndpoint: '', apiKey: '', isDefault: 0, enabled: 1 }
       this.dialogVisible = true
       this.$nextTick(() => { this.$refs.formRef && this.$refs.formRef.resetFields() })
     },
@@ -142,16 +136,14 @@ export default {
     },
     handleProviderChange(code) {
       const defaults = {
-        doubao: { apiEndpoint: 'https://ark.cn-beijing.volces.com/api/v3/chat/completions', modelName: 'doubao-pro-4k', maxTokens: 4096, temperature: 0.7 },
-        qwen:   { apiEndpoint: 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions', modelName: 'qwen-plus', maxTokens: 8192, temperature: 0.7 },
-        yuanbao:{ apiEndpoint: 'https://api.hunyuan.cloud.tencent.com/v1/chat/completions', modelName: 'hunyuan-lite', maxTokens: 4096, temperature: 0.7 },
-        deepseek:{ apiEndpoint: 'https://api.deepseek.com/v1/chat/completions', modelName: 'deepseek-chat', maxTokens: 8192, temperature: 0.7 }
+        doubao: { apiEndpoint: 'https://ark.cn-beijing.volces.com/api/v3/chat/completions', modelName: 'doubao-pro-4k' },
+        qwen:   { apiEndpoint: 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions', modelName: 'qwen-plus' },
+        deepseek:{ apiEndpoint: 'https://api.deepseek.com/v1/chat/completions', modelName: 'deepseek-chat' },
+        zhipu:  { apiEndpoint: 'https://open.bigmodel.cn/api/paas/v4/chat/completions', modelName: 'glm-4-flash' }
       }
       if (defaults[code]) {
         this.form.apiEndpoint = defaults[code].apiEndpoint
         this.form.modelName = defaults[code].modelName
-        this.form.maxTokens = defaults[code].maxTokens
-        this.form.temperature = defaults[code].temperature
       }
     },
     async handleSubmit() {

+ 11 - 2
src/views/admin/article/index.vue

@@ -30,7 +30,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="onTenantChange" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -207,6 +208,8 @@
 <script>
 import { listAllArticles, listPendingArticles, getArticleInfo, auditArticle, deleteArticle, getArticleStatistics } from '@/api/admin/article'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'ArticleAdmin',
   data() {
@@ -240,7 +243,8 @@ export default {
         pageSize: 10,
         companyName: null,
         articleTitle: null,
-        status: null
+        status: null,
+        companyId: null
       },
       // 详情弹窗
       viewOpen: false,
@@ -284,6 +288,11 @@ export default {
       this.queryParams.pageNum = 1
       this.getList()
     },
+    /** 租户选择变化 */
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm('queryForm')

+ 4 - 1
src/views/admin/callRecord/index.vue

@@ -29,7 +29,8 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -265,6 +266,8 @@
 <script>
 import { listAllCallRecords, getCallRecordInfo, addQualityRecord, listQualityRecords, updateQualityRecord, deleteQualityRecord, reportQuality, getCallStatistics } from '@/api/admin/callRecord'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'CallRecordAdmin',
   data() {

+ 11 - 2
src/views/admin/course/index.vue

@@ -30,7 +30,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="onTenantChange" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -170,6 +171,8 @@
 <script>
 import { listAllCourses, getCourseInfo, getCourseStatistics } from '@/api/admin/course'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'CourseAdmin',
   data() {
@@ -202,7 +205,8 @@ export default {
         pageSize: 10,
         companyName: null,
         courseName: null,
-        status: null
+        status: null,
+        companyId: null
       },
       // 详情弹窗
       viewOpen: false,
@@ -229,6 +233,11 @@ export default {
       this.queryParams.pageNum = 1
       this.getList()
     },
+    /** 租户选择变化 */
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm('queryForm')

+ 14 - 7
src/views/admin/crm/index.vue

@@ -1,13 +1,14 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="租户名称" prop="companyName">
+        <el-input v-model="queryParams.companyName" placeholder="请输入租户名称" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
       <el-form-item label="客户名称" prop="customerName">
         <el-input v-model="queryParams.customerName" placeholder="请输入客户名称" clearable size="small" @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="租户编号" prop="tenantCode">
-        <el-input v-model="queryParams.tenantCode" placeholder="请输入租户编号" clearable size="small" @keyup.enter.native="handleQuery" />
-      </el-form-item>
       <el-form-item>
+        <inline-tenant-selector @change="onTenantChange" />
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
@@ -21,7 +22,7 @@
     </el-row>
 
     <el-table border v-loading="loading" :data="list">
-      <el-table-column label="租户" align="center" prop="tenantLabel" min-width="150" />
+      <el-table-column label="租户名称" align="center" prop="companyName" min-width="150" />
       <el-table-column label="客户名称" align="center" prop="customerName" />
       <el-table-column label="手机号" align="center" prop="customerPhone" width="130" />
       <el-table-column label="客户阶段" align="center" prop="stage" width="100" />
@@ -35,14 +36,16 @@
 
 <script>
 import { listCrmCustomer } from '@/api/admin/crm'
+import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
   name: 'AdminCrm',
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: false, exportLoading: false, showSearch: true,
       list: [], total: 0,
-      queryParams: { pageNum: 1, pageSize: 10, customerName: null, tenantCode: null }
+      queryParams: { pageNum: 1, pageSize: 10, customerName: null, companyName: null, companyId: null }
     }
   },
   created() { this.getList() },
@@ -50,13 +53,17 @@ export default {
     getList() {
       this.loading = true
       listCrmCustomer(this.queryParams).then(res => {
-        this.list = (res.rows || []).map(r => ({ ...r, tenantLabel: r.tenant_code + ' | ' + r.tenant_name }))
+        this.list = res.rows || []
         this.total = res.total || 0
         this.loading = false
       }).catch(() => { this.loading = false })
     },
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
-    resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
+    resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
     handleExport() { this.$message.info('导出功能开发中') }
   }
 }

+ 11 - 2
src/views/admin/live/index.vue

@@ -30,7 +30,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="onTenantChange" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -173,6 +174,8 @@
 <script>
 import { listAllLives, getLiveInfo, getLiveStatistics } from '@/api/admin/live'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'LiveAdmin',
   data() {
@@ -206,7 +209,8 @@ export default {
         pageSize: 10,
         companyName: null,
         liveTitle: null,
-        status: null
+        status: null,
+        companyId: null
       },
       // 详情弹窗
       viewOpen: false,
@@ -233,6 +237,11 @@ export default {
       this.queryParams.pageNum = 1
       this.getList()
     },
+    /** 租户选择变化 */
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm('queryForm')

+ 72 - 60
src/views/admin/menu.js

@@ -1,7 +1,9 @@
 /**
  * 总后台菜单配置
+ * 精简后保留13个管理+审计菜单,新增6个功能/审计页面
  */
 export default [
+  // ==================== 核心管理 ====================
   {
     path: '/admin/proxy',
     component: () => import('@/views/admin/proxy/index'),
@@ -9,105 +11,115 @@ export default [
     meta: { title: '代理管理', icon: 'el-icon-s-home', permission: ['admin:proxy:list'] }
   },
   {
-    path: '/admin/qwExternalContact',
-    component: () => import('@/views/admin/qwExternalContact/index'),
-    name: 'QwExternalContactAdmin',
-    meta: { title: '企微用户管理', icon: 'el-icon-user', permission: ['admin:qwExternalContact:list'] }
-  },
-  {
-    path: '/admin/aiChatQuality',
-    component: () => import('@/views/admin/aiChatQuality/index'),
-    name: 'AiChatQualityAdmin',
-    meta: { title: 'AI聊天质检', icon: 'el-icon-chat-line-round', permission: ['admin:aiChatQuality:list'] }
+    path: '/admin/company',
+    component: () => import('@/views/admin/sysCompany/index'),
+    name: 'SysCompanyAdmin',
+    meta: { title: '租户管理', icon: 'el-icon-building', permission: ['admin:company:list'] }
   },
   {
     path: '/admin/user',
     component: () => import('@/views/admin/sysUser/index'),
     name: 'SysUserAdmin',
-    meta: { title: '员工账户管理', icon: 'el-icon-user-solid', permission: ['admin:user:list'] }
+    meta: { title: '员工管理', icon: 'el-icon-user-solid', permission: ['admin:user:list'] }
   },
   {
-    path: '/admin/company',
-    component: () => import('@/views/admin/sysCompany/index'),
-    name: 'SysCompanyAdmin',
-    meta: { title: '租户管理', icon: 'el-icon-building', permission: ['admin:company:list'] }
+    path: '/admin/aiProvider',
+    component: () => import('@/views/admin/aiProvider/index'),
+    name: 'AiProviderAdmin',
+    meta: { title: '文本模型配置', icon: 'el-icon-cpu', permission: ['admin:aiProvider:list'] }
   },
   {
-    path: '/admin/course',
-    component: () => import('@/views/admin/course/index'),
-    name: 'CourseAdmin',
-    meta: { title: '课程管理', icon: 'el-icon-video-play', permission: ['admin:course:list'] }
+    path: '/admin/moduleUsage',
+    component: () => import('@/views/admin/moduleUsage/index'),
+    name: 'AdminModuleUsage',
+    meta: { title: '模块用量统计', icon: 'el-icon-data-line', permission: ['admin:moduleUsage:list'] }
   },
+
+  // ==================== 消费/返佣/充值/提现 ====================
   {
-    path: '/admin/live',
-    component: () => import('@/views/admin/live/index'),
-    name: 'LiveAdmin',
-    meta: { title: '直播管理', icon: 'el-icon-live', permission: ['admin:live:list'] }
+    path: '/admin/consumeRecord',
+    component: () => import('@/views/admin/consumeRecord/index'),
+    name: 'AdminConsumeRecord',
+    meta: { title: '消费扣款记录', icon: 'el-icon-money', permission: ['admin:consumeRecord:list'] }
   },
   {
-    path: '/admin/product',
-    component: () => import('@/views/admin/product/index'),
-    name: 'ProductAdmin',
-    meta: { title: '商品审核', icon: 'el-icon-shopping-cart-full', permission: ['admin:product:list'] }
+    path: '/admin/rechargeRecord',
+    component: () => import('@/views/admin/rechargeRecord/index'),
+    name: 'AdminRechargeRecord',
+    meta: { title: '充值记录', icon: 'el-icon-bank-card', permission: ['admin:rechargeRecord:list'] }
   },
   {
-    path: '/admin/article',
-    component: () => import('@/views/admin/article/index'),
-    name: 'ArticleAdmin',
-    meta: { title: '文章审计', icon: 'el-icon-file-text', permission: ['admin:article:list'] }
+    path: '/admin/commissionRecord',
+    component: () => import('@/views/admin/commissionRecord/index'),
+    name: 'AdminCommissionRecord',
+    meta: { title: '返佣记录', icon: 'el-icon-s-finance', permission: ['admin:commissionRecord:list'] }
+  },
+  {
+    path: '/admin/withdrawal',
+    component: () => import('@/views/admin/withdrawalManage/index'),
+    name: 'AdminWithdrawal',
+    meta: { title: '提现管理', icon: 'el-icon-wallet', permission: ['admin:withdrawal:list'] }
+  },
+
+  // ==================== 内容审计 ====================
+  {
+    path: '/admin/qwExternalContact',
+    component: () => import('@/views/admin/qwExternalContact/index'),
+    name: 'QwExternalContactAdmin',
+    meta: { title: '企微用户管理(审计)', icon: 'el-icon-user', permission: ['admin:qwExternalContact:list'] }
   },
   {
     path: '/admin/callRecord',
     component: () => import('@/views/admin/callRecord/index'),
     name: 'CallRecordAdmin',
-    meta: { title: '外呼记录质检', icon: 'el-icon-phone', permission: ['admin:callRecord:list'] }
+    meta: { title: '通话记录(审计)', icon: 'el-icon-phone', permission: ['admin:callRecord:list'] }
   },
   {
-    path: '/admin/statistics',
-    component: () => import('@/views/admin/statistics/index'),
-    name: 'AdminStatistics',
-    meta: { title: '统计中心', icon: 'el-icon-data-analysis', permission: ['admin:statistics:overview'] }
+    path: '/admin/course',
+    component: () => import('@/views/admin/course/index'),
+    name: 'CourseAdmin',
+    meta: { title: '公域课程管理(审计)', icon: 'el-icon-video-play', permission: ['admin:course:list'] }
   },
   {
-    path: '/admin/aiProvider',
-    component: () => import('@/views/admin/aiProvider/index'),
-    name: 'AiProviderAdmin',
-    meta: { title: '大模型供应商管理', icon: 'el-icon-cpu', permission: ['admin:aiProvider:list'] }
+    path: '/admin/live',
+    component: () => import('@/views/admin/live/index'),
+    name: 'LiveAdmin',
+    meta: { title: '直播间(审计)', icon: 'el-icon-live', permission: ['admin:live:list'] }
   },
   {
-    path: '/admin/moduleUsage',
-    component: () => import('@/views/admin/moduleUsage/index'),
-    name: 'AdminModuleUsage',
-    meta: { title: '模块用量统计', icon: 'el-icon-data-line', permission: ['admin:moduleUsage:list'] }
+    path: '/admin/liveVideo',
+    component: () => import('@/views/admin/liveVideo/index'),
+    name: 'AdminLiveVideo',
+    meta: { title: '直播视频(审计)', icon: 'el-icon-video-camera-solid', permission: ['admin:liveVideo:list'] }
   },
   {
-    path: '/admin/crm',
-    component: () => import('@/views/admin/crm/index'),
-    name: 'AdminCrm',
-    meta: { title: 'CRM客户审计', icon: 'el-icon-s-custom', permission: ['admin:crm:list'] }
+    path: '/admin/videoResource',
+    component: () => import('@/views/admin/videoResource/index'),
+    name: 'AdminVideoResource',
+    meta: { title: '视频资源(审计)', icon: 'el-icon-video-camera', permission: ['admin:videoResource:list'] }
+  },
+  {
+    path: '/admin/product',
+    component: () => import('@/views/admin/product/index'),
+    name: 'ProductAdmin',
+    meta: { title: '商品管理(审计)', icon: 'el-icon-shopping-cart-full', permission: ['admin:product:list'] }
   },
   {
     path: '/admin/storeOrder',
     component: () => import('@/views/admin/storeOrder/index'),
     name: 'AdminStoreOrder',
-    meta: { title: '商城订单审计', icon: 'el-icon-s-order', permission: ['admin:storeOrder:list'] }
-  },
-  {
-    path: '/admin/sop',
-    component: () => import('@/views/admin/sop/index'),
-    name: 'AdminSop',
-    meta: { title: 'SOP审计', icon: 'el-icon-document-copy', permission: ['admin:sop:list'] }
+    meta: { title: '销售订单(审计)', icon: 'el-icon-s-order', permission: ['admin:storeOrder:list'] }
   },
   {
-    path: '/admin/ad',
-    component: () => import('@/views/admin/ad/index'),
-    name: 'AdminAd',
-    meta: { title: '广告投放审计', icon: 'el-icon-present', permission: ['admin:ad:list'] }
+    path: '/admin/article',
+    component: () => import('@/views/admin/article/index'),
+    name: 'ArticleAdmin',
+    meta: { title: '文章管理(审计)', icon: 'el-icon-file-text', permission: ['admin:article:list'] }
   },
   {
     path: '/admin/lobster',
     component: () => import('@/views/lobster/workflow-generate/index'),
     name: 'LobsterInstanceMonitor',
-    meta: { title: '龙虾引擎监控', icon: 'el-icon-cpu', permission: ['admin:lobster:list'] }
+    meta: { title: 'AI生成工作流(审计)', icon: 'el-icon-cpu', permission: ['admin:lobster:list'] }
   }
 ]

+ 64 - 34
src/views/admin/moduleUsage/index.vue

@@ -4,8 +4,8 @@
       <el-form-item label="租户名称" prop="tenantName">
         <el-input v-model="queryParams.tenantName" placeholder="请输入租户名称" clearable size="small" @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="代理ID" prop="proxyId">
-        <el-input v-model="queryParams.proxyId" placeholder="请输入代理ID" clearable size="small" @keyup.enter.native="handleQuery" />
+      <el-form-item label="统计日期" prop="statDate">
+        <el-date-picker v-model="queryParams.statDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择统计日期" clearable size="small" style="width:180px" />
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -23,25 +23,44 @@
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="租户名称" align="center" prop="tenantName" />
-      <el-table-column label="代理ID" align="center" prop="proxyId" />
-      <el-table-column label="AI模型用量" align="center" prop="aiModelUsed" />
-      <el-table-column label="AI模型配额" align="center" prop="aiModelQuota" />
-      <el-table-column label="AI Token用量" align="center" prop="aiTokenUsed" />
-      <el-table-column label="AI Token配额" align="center" prop="aiTokenQuota" />
-      <el-table-column label="短信用量" align="center" prop="smsUsed" />
-      <el-table-column label="课程流量用量" align="center" prop="courseTrafficUsed" />
-      <el-table-column label="直播流量用量" align="center" prop="liveTrafficUsed" />
-      <el-table-column label="AI外呼用量" align="center" prop="aiCallUsed" />
-      <el-table-column label="企微助手用量" align="center" prop="wechatHelperUsed" />
-      <el-table-column label="统计日期" align="center" prop="statDate" width="120">
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange" style="width:100%">
+      <el-table-column type="selection" width="50" align="center" fixed="left" />
+      <el-table-column label="租户名称" align="center" prop="tenantName" width="140" fixed="left" />
+      <el-table-column label="归属代理" align="center" prop="proxyName" width="120" />
+      <el-table-column label="统计日期" align="center" prop="statDate" width="110" />
+      <!-- 组织管理 -->
+      <el-table-column label="部门数" align="center" prop="deptCount" width="75" />
+      <el-table-column label="员工数" align="center" prop="employeeCount" width="75" />
+      <!-- CRM/外呼/短信 -->
+      <el-table-column label="外呼次数" align="center" prop="outboundCallCount" width="85" />
+      <el-table-column label="短信发送量" align="center" prop="smsSentCount" width="95" />
+      <!-- 个微 -->
+      <el-table-column label="个微用户数" align="center" prop="wxUserCount" width="100" />
+      <el-table-column label="个微绑定数" align="center" prop="wxAccountCount" width="100" />
+      <el-table-column label="个微客户数" align="center" prop="wxCustomerCount" width="100" />
+      <!-- 企微 -->
+      <el-table-column label="企微用户数" align="center" prop="qwUserCount" width="100" />
+      <el-table-column label="企微绑定数" align="center" prop="qwAccountCount" width="100" />
+      <!-- 业务模块 -->
+      <el-table-column label="SOP数" align="center" prop="sopCount" width="70" />
+      <el-table-column label="课程数" align="center" prop="courseCount" width="75" />
+      <el-table-column label="直播次数" align="center" prop="liveCount" width="85" />
+      <el-table-column label="商品数" align="center" prop="productCount" width="75" />
+      <el-table-column label="订单数" align="center" prop="orderCount" width="75" />
+      <!-- AI/龙虾引擎 -->
+      <el-table-column label="工作流数" align="center" prop="workflowCount" width="85" />
+      <el-table-column label="龙虾模板数" align="center" prop="lobsterTemplateCount" width="105" />
+      <el-table-column label="龙虾任务数" align="center" prop="lobsterTaskCount" width="105" />
+      <!-- 汇总 -->
+      <el-table-column label="活跃模块数" align="center" prop="activeModuleCount" width="100">
         <template slot-scope="scope">
-          <span>{{ scope.row.statDate }}</span>
+          <el-tag type="success" size="small">{{ scope.row.activeModuleCount || 0 }}</el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="当月消费总额" align="center" prop="totalConsumeAmount" width="120" fixed="right">
+        <template slot-scope="scope">¥{{ scope.row.totalConsumeAmount || '0.00' }}</template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="80" fixed="right">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">详情</el-button>
         </template>
@@ -50,22 +69,33 @@
 
     <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
 
-    <el-dialog title="租户用量详情" :visible.sync="detailVisible" width="600px">
-      <el-descriptions :column="2" border>
+    <!-- 详情弹窗 -->
+    <el-dialog title="租户用量详情" :visible.sync="detailVisible" width="700px">
+      <el-descriptions :column="3" border>
         <el-descriptions-item label="租户名称">{{ detail.tenantName }}</el-descriptions-item>
-        <el-descriptions-item label="代理ID">{{ detail.proxyId }}</el-descriptions-item>
-        <el-descriptions-item label="AI模型用量">{{ detail.aiModelUsed }}</el-descriptions-item>
-        <el-descriptions-item label="AI模型配额">{{ detail.aiModelQuota }}</el-descriptions-item>
-        <el-descriptions-item label="AI Token用量">{{ detail.aiTokenUsed }}</el-descriptions-item>
-        <el-descriptions-item label="AI Token配额">{{ detail.aiTokenQuota }}</el-descriptions-item>
-        <el-descriptions-item label="短信用量">{{ detail.smsUsed }}</el-descriptions-item>
-        <el-descriptions-item label="短信配额">{{ detail.smsQuota }}</el-descriptions-item>
-        <el-descriptions-item label="课程流量用量">{{ detail.courseTrafficUsed }}</el-descriptions-item>
-        <el-descriptions-item label="直播流量用量">{{ detail.liveTrafficUsed }}</el-descriptions-item>
-        <el-descriptions-item label="人工外呼用量">{{ detail.manualCallUsed }}</el-descriptions-item>
-        <el-descriptions-item label="AI外呼用量">{{ detail.aiCallUsed }}</el-descriptions-item>
-        <el-descriptions-item label="企微助手用量">{{ detail.wechatHelperUsed }}</el-descriptions-item>
+        <el-descriptions-item label="归属代理">{{ detail.proxyName || '-' }}</el-descriptions-item>
         <el-descriptions-item label="统计日期">{{ detail.statDate }}</el-descriptions-item>
+        <el-descriptions-item label="部门数量">{{ detail.deptCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="员工数量">{{ detail.employeeCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="外呼拨打次数">{{ detail.outboundCallCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="短信发送量">{{ detail.smsSentCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="个微用户数">{{ detail.wxUserCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="绑定个微账号数">{{ detail.wxAccountCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="个微客户数">{{ detail.wxCustomerCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="企微用户数">{{ detail.qwUserCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="绑定企微号数">{{ detail.qwAccountCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="SOP数量">{{ detail.sopCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="课程数量">{{ detail.courseCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="直播次数">{{ detail.liveCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="商品数量">{{ detail.productCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="订单数量">{{ detail.orderCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="工作流数量">{{ detail.workflowCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="龙虾引擎模版数">{{ detail.lobsterTemplateCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="龙虾引擎任务数">{{ detail.lobsterTaskCount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="活跃模块数">
+          <el-tag type="success" size="small">{{ detail.activeModuleCount || 0 }}</el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="当月消费总额">¥{{ detail.totalConsumeAmount || '0.00' }}</el-descriptions-item>
       </el-descriptions>
     </el-dialog>
   </div>
@@ -90,7 +120,7 @@ export default {
         pageNum: 1,
         pageSize: 10,
         tenantName: null,
-        proxyId: null
+        statDate: null
       }
     }
   },
@@ -115,7 +145,7 @@ export default {
       this.handleQuery()
     },
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.tenantId)
+      this.ids = selection.map(item => item.usageId)
     },
     handleDetail(row) {
       getTenantDetail(row.tenantId).then(res => {

+ 11 - 2
src/views/admin/product/index.vue

@@ -30,7 +30,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="onTenantChange" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -215,6 +216,8 @@
 <script>
 import { listAllProducts, listPendingProducts, getProductInfo, auditProduct, getProductStatistics } from '@/api/admin/product'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'ProductAdmin',
   data() {
@@ -248,7 +251,8 @@ export default {
         pageSize: 10,
         companyName: null,
         productName: null,
-        status: null
+        status: null,
+        companyId: null
       },
       // 详情弹窗
       viewOpen: false,
@@ -292,6 +296,11 @@ export default {
       this.queryParams.pageNum = 1
       this.getList()
     },
+    /** 租户选择变化 */
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm('queryForm')

+ 20 - 3
src/views/admin/proxy/index.vue

@@ -15,7 +15,8 @@
             </el-select>
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="loadProxyList">搜索</el-button>
+            <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="loadProxyList">搜索</el-button>
             <el-button icon="el-icon-refresh" size="mini" @click="resetProxyQuery">重置</el-button>
           </el-form-item>
         </el-form>
@@ -31,8 +32,8 @@
           <el-table-column type="selection" width="50" align="center" />
           <el-table-column label="ID" prop="proxyId" width="60" align="center" />
           <el-table-column label="代理名称" prop="proxyName" />
-          <el-table-column label="联系人" prop="contactName" />
-          <el-table-column label="联系电话" prop="contactMobile" />
+          <el-table-column label="代理姓名" prop="contactName" />
+          <el-table-column label="代理联系方式" prop="contactMobile" />
           <el-table-column label="余额" align="center">
             <template slot-scope="s">¥{{ s.row.balance || 0 }}</template>
           </el-table-column>
@@ -40,6 +41,13 @@
             <template slot-scope="s">{{ s.row.profitShareRatio || 0 }}%</template>
           </el-table-column>
           <el-table-column label="到期时间" align="center" prop="expireTime" />
+          <el-table-column label="发展客户数" align="center" prop="tenantCount" />
+          <el-table-column label="累计分成总额" align="center" prop="totalCommission">
+            <template slot-scope="s">¥{{ s.row.totalCommission || 0 }}</template>
+          </el-table-column>
+          <el-table-column label="剩余未提现" align="center" prop="unwithdrawnAmount">
+            <template slot-scope="s">¥{{ s.row.unwithdrawnAmount || 0 }}</template>
+          </el-table-column>
           <el-table-column label="状态" align="center" prop="status">
             <template slot-scope="s">
               <el-switch v-model="s.row.status" :active-value="1" :inactive-value="0"
@@ -206,8 +214,11 @@ import {
   getTenantsByProxy, bindTenant, unbindTenant
 } from '@/api/admin/proxy'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'AdminProxy',
+  components: { InlineTenantSelector },
   data() {
     return {
       activeTab: 'proxyList',
@@ -256,6 +267,12 @@ export default {
       if (this.activeTab === 'tenantRel') this.loadEnabledProxies()
     },
 
+    /** 租户选择器变更 / 搜索查询 */
+    handleQuery() {
+      this.proxyQuery.pageNum = 1
+      this.loadProxyList()
+    },
+
     // ======== 代理 CRUD ========
     loadProxyList() {
       this.proxyLoading = true

+ 4 - 1
src/views/admin/qwExternalContact/index.vue

@@ -39,7 +39,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -123,6 +124,8 @@
 <script>
 import { listAllExternalContact, getExternalContact } from '@/api/admin/qwExternalContact'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'QwExternalContactAdmin',
   data() {

+ 14 - 7
src/views/admin/sop/index.vue

@@ -6,13 +6,14 @@
     </el-tabs>
 
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="租户名称" prop="companyName">
+        <el-input v-model="queryParams.companyName" placeholder="请输入租户名称" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
       <el-form-item :label="activeTab==='sop'?'SOP名称':'模板名称'" prop="sopName">
         <el-input v-model="queryParams.sopName" placeholder="请输入名称" clearable size="small" @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="租户编号" prop="tenantCode">
-        <el-input v-model="queryParams.tenantCode" placeholder="请输入租户编号" clearable size="small" @keyup.enter.native="handleQuery" />
-      </el-form-item>
       <el-form-item>
+        <inline-tenant-selector @change="onTenantChange" />
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
@@ -26,7 +27,7 @@
     </el-row>
 
     <el-table border v-loading="loading" :data="list">
-      <el-table-column label="租户" align="center" prop="tenantLabel" min-width="150" />
+      <el-table-column label="租户名称" align="center" prop="companyName" min-width="150" />
       <el-table-column label="名称" align="center" prop="name" />
       <el-table-column label="状态" align="center" prop="status" width="100" />
       <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
@@ -38,14 +39,16 @@
 
 <script>
 import { listSop, listSopTemp } from '@/api/admin/sop'
+import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
   name: 'AdminSop',
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: false, exportLoading: false, showSearch: true, activeTab: 'sop',
       list: [], total: 0,
-      queryParams: { pageNum: 1, pageSize: 10, sopName: null, tenantCode: null }
+      queryParams: { pageNum: 1, pageSize: 10, sopName: null, companyName: null, companyId: null }
     }
   },
   created() { this.getList() },
@@ -54,14 +57,18 @@ export default {
       this.loading = true
       const api = this.activeTab === 'temp' ? listSopTemp : listSop
       api(this.queryParams).then(res => {
-        this.list = (res.rows || []).map(r => ({ ...r, tenantLabel: r.tenant_label || (r.tenant_code + ' | ' + r.tenant_name) }))
+        this.list = res.rows || []
         this.total = res.total || 0
         this.loading = false
       }).catch(() => { this.loading = false })
     },
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     handleTabClick() { this.queryParams.pageNum = 1; this.getList() },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
-    resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
+    resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
     handleExport() { this.$message.info('导出功能开发中') }
   }
 }

+ 4 - 1
src/views/admin/statistics/index.vue

@@ -31,7 +31,8 @@
           />
         </el-form-item>
         <el-form-item>
-          <el-button type="primary" icon="el-icon-search" @click="refreshAll">查询</el-button>
+          <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" @click="refreshAll">查询</el-button>
           <el-button icon="el-icon-refresh" @click="resetFilter">重置</el-button>
         </el-form-item>
       </el-form>
@@ -207,6 +208,8 @@ const TYPE_NAMES = {
   'MICRO_ASSISTANT': '微助手', 'ACCOUNT_FEE': '账户费'
 }
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'AdminStatistics',
   data() {

+ 14 - 7
src/views/admin/storeOrder/index.vue

@@ -1,13 +1,14 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="租户名称" prop="companyName">
+        <el-input v-model="queryParams.companyName" placeholder="请输入租户名称" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
       <el-form-item label="订单编号" prop="orderNo">
         <el-input v-model="queryParams.orderNo" placeholder="请输入订单编号" clearable size="small" @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="租户编号" prop="tenantCode">
-        <el-input v-model="queryParams.tenantCode" placeholder="请输入租户编号" clearable size="small" @keyup.enter.native="handleQuery" />
-      </el-form-item>
       <el-form-item>
+        <inline-tenant-selector @change="onTenantChange" />
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
@@ -21,7 +22,7 @@
     </el-row>
 
     <el-table border v-loading="loading" :data="list">
-      <el-table-column label="租户" align="center" prop="tenantLabel" min-width="150" />
+      <el-table-column label="租户名称" align="center" prop="companyName" min-width="150" />
       <el-table-column label="订单编号" align="center" prop="orderNo" width="180" />
       <el-table-column label="订单金额" align="center" prop="orderAmount" width="120" />
       <el-table-column label="支付方式" align="center" prop="payType" width="100" />
@@ -35,14 +36,16 @@
 
 <script>
 import { listStoreOrder } from '@/api/admin/storeOrder'
+import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
   name: 'AdminStoreOrder',
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: false, exportLoading: false, showSearch: true,
       list: [], total: 0,
-      queryParams: { pageNum: 1, pageSize: 10, orderNo: null, tenantCode: null }
+      queryParams: { pageNum: 1, pageSize: 10, orderNo: null, companyName: null, companyId: null }
     }
   },
   created() { this.getList() },
@@ -50,13 +53,17 @@ export default {
     getList() {
       this.loading = true
       listStoreOrder(this.queryParams).then(res => {
-        this.list = (res.rows || []).map(r => ({ ...r, tenantLabel: r.tenant_label || (r.tenant_code + ' | ' + r.tenant_name) }))
+        this.list = res.rows || []
         this.total = res.total || 0
         this.loading = false
       }).catch(() => { this.loading = false })
     },
+    onTenantChange(companyId) {
+      this.queryParams.companyId = companyId
+      this.handleQuery()
+    },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
-    resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
+    resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
     handleExport() { this.$message.info('导出功能开发中') }
   }
 }

+ 36 - 0
src/views/admin/sysCompany/index.vue

@@ -51,6 +51,18 @@
       <el-table-column label="邮箱" align="center" prop="email" />
       <el-table-column label="地址" align="center" prop="address" />
       <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="租户余额" align="center" prop="balance">
+        <template slot-scope="scope">¥{{ scope.row.balance || '0.00' }}</template>
+      </el-table-column>
+      <el-table-column label="已消费总额" align="center" prop="totalCost">
+        <template slot-scope="scope">¥{{ scope.row.totalCost || '0.00' }}</template>
+      </el-table-column>
+      <el-table-column label="开通账户数" align="center" prop="accountCount" />
+      <el-table-column label="绑定企微账号数" align="center" prop="qwAccountCount" />
+      <el-table-column label="绑定个微账号数" align="center" prop="wxAccountCount" />
+      <el-table-column label="客户数" align="center" prop="customerCount" />
+      <el-table-column label="企微用户数" align="center" prop="qwUserCount" />
+      <el-table-column label="归属代理" align="center" prop="proxyName" />
       <el-table-column label="租户状态" align="center" prop="status">
         <template slot-scope="scope">
           <el-tag v-if="scope.row.status == 0" type="success">正常</el-tag>
@@ -123,6 +135,30 @@
         <el-form-item label="创建时间">
           <span>{{ viewForm.createTime }}</span>
         </el-form-item>
+        <el-form-item label="租户余额">
+          <span>¥{{ viewForm.balance || '0.00' }}</span>
+        </el-form-item>
+        <el-form-item label="已消费总额">
+          <span>¥{{ viewForm.totalCost || '0.00' }}</span>
+        </el-form-item>
+        <el-form-item label="开通账户数">
+          <span>{{ viewForm.accountCount || 0 }}</span>
+        </el-form-item>
+        <el-form-item label="绑定企微账号数">
+          <span>{{ viewForm.qwAccountCount || 0 }}</span>
+        </el-form-item>
+        <el-form-item label="绑定个微账号数">
+          <span>{{ viewForm.wxAccountCount || 0 }}</span>
+        </el-form-item>
+        <el-form-item label="客户数">
+          <span>{{ viewForm.customerCount || 0 }}</span>
+        </el-form-item>
+        <el-form-item label="企微用户数">
+          <span>{{ viewForm.qwUserCount || 0 }}</span>
+        </el-form-item>
+        <el-form-item label="归属代理">
+          <span>{{ viewForm.proxyName || '-' }}</span>
+        </el-form-item>
         <el-form-item label="租户状态">
           <el-tag v-if="viewForm.status == 0" type="success">正常</el-tag>
           <el-tag v-else type="error">禁用</el-tag>

+ 4 - 1
src/views/bill/billLog/index.vue

@@ -34,7 +34,8 @@
         <el-date-picker v-model="billTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="changeTime"></el-date-picker>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -144,6 +145,8 @@
 <script>
 import { listBillLog, getBillLog, delBillLog, addBillLog, updateBillLog, exportBillLog, reopen } from "@/api/bill/billLog";
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: "BillLog",
   data() {

+ 101 - 22
src/views/callRecord/index/index.vue

@@ -6,51 +6,83 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
-          v-hasPermi="['platform:callRecord:add']">新增</el-button>
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
+          v-hasPermi="['callRecord:add']">新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['callRecord:remove']">删除</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
-            v-hasPermi="['platform:callRecord:edit']">修改</el-button>
+            v-hasPermi="['callRecord:edit']">修改</el-button>
           <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
-            v-hasPermi="['platform:callRecord:remove']">删除</el-button>
+            v-hasPermi="['callRecord:remove']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "Callrecord",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/callRecord/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/callRecord/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/callRecord", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/callRecord", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/callRecord/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 10 - 5
src/views/chat/chatDataset/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="所属角色" prop="roleId">
         <el-select v-model="queryParams.roleId" placeholder="请选择所属角色" clearable size="small">
           <el-option
@@ -138,9 +141,10 @@ import { listChatDataset, getChatDataset, delChatDataset, addChatDataset, update
 import { getAllRoleList } from "@/api/chat/chatRole";
 import chatDatasetFile from "@/views/chat/components/chatDatasetFile.vue";
 import {allList}from "@/api/company/company";
+import TenantSelect from '@/components/TenantSelect/index'
 export default {
   name: "ChatDataset",
-  components:{chatDatasetFile},
+  components:{ chatDatasetFile, TenantSelect },
   data() {
     return {
       companyList:[],
@@ -175,6 +179,7 @@ export default {
         roleId: null,
         datasetName: null,
         extId: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -213,7 +218,7 @@ export default {
     /** 查询知识库列表 */
     getList() {
       this.loading = true;
-      listChatDataset(this.queryParams).then(response => {
+      listChatDataset(this.$withTenant(this.queryParams)).then(response => {
         this.chatDatasetList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -272,13 +277,13 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.datasetId != null) {
-            updateChatDataset(this.form).then(response => {
+            updateChatDataset(this.$withTenant(this.form)).then(response => {
               this.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addChatDataset(this.form).then(response => {
+            addChatDataset(this.$withTenant(this.form)).then(response => {
               this.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -303,7 +308,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有知识库数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 11 - 5
src/views/chat/chatRole/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="客服角色" prop="roleName">
         <el-input
           v-model="queryParams.roleName"
@@ -172,8 +175,10 @@ import { listChatRole, getChatRole, delChatRole, addChatRole, updateChatRole, ex
 import { getUrl } from "@/api/chat/chatUpload";
 import QRCode from 'qrcodejs2'
 import {allList}from "@/api/company/company";
+import TenantSelect from '@/components/TenantSelect/index'
 export default {
   name: "ChatRole",
+  components: { TenantSelect },
   data() {
     return {
       companyList:[],
@@ -210,7 +215,8 @@ export default {
         companyId: null,
         roleType: null,
         configJson: null,
-        mode: null
+        mode: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -302,7 +308,7 @@ export default {
     /** 查询聊天角色列表 */
     getList() {
       this.loading = true;
-      listChatRole(this.queryParams).then(response => {
+      listChatRole(this.$withTenant(this.queryParams)).then(response => {
         this.chatRoleList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -376,13 +382,13 @@ export default {
         if (valid) {
           this.form.modeConfigJson=JSON.stringify(this.form.modeConfigJson)
           if (this.form.roleId != null) {
-            updateChatRole(this.form).then(response => {
+            updateChatRole(this.$withTenant(this.form)).then(response => {
               this.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addChatRole(this.form).then(response => {
+            addChatRole(this.$withTenant(this.form)).then(response => {
               this.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -407,7 +413,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有客服数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 11 - 6
src/views/chat/chatSession/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="公司名称" prop="companyId" >
         <el-select v-model="queryParams.companyId" placeholder="请选择所属公司" filterable size="small">
           <el-option v-for="(option, index) in companyList" :key="index" :value="option.dictValue" :label="option.dictLabel"></el-option>
@@ -203,9 +206,10 @@ import { listChatSession, getChatSession, delChatSession, addChatSession, update
 import chatMsgDetails from '../components/chatMsgDetails.vue';
 import { getAllRoleList } from "@/api/chat/chatRole";
 import {allList}from "@/api/company/company";
+import TenantSelect from '@/components/TenantSelect/index'
 export default {
   name: "ChatSession",
-  components:{chatMsgDetails},
+  components:{ chatMsgDetails, TenantSelect },
   data() {
     return {
       roles:[],
@@ -245,7 +249,8 @@ export default {
         userId: null,
         kfId: null,
         status: null,
-        isLook:null
+        isLook:null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -287,7 +292,7 @@ export default {
     /** 查询会话列表 */
     getList() {
       this.loading = true;
-      listChatSession(this.queryParams).then(response => {
+      listChatSession(this.$withTenant(this.queryParams)).then(response => {
         this.chatSessionList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -360,13 +365,13 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.sessionId != null) {
-            updateChatSession(this.form).then(response => {
+            updateChatSession(this.$withTenant(this.form)).then(response => {
               this.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addChatSession(this.form).then(response => {
+            addChatSession(this.$withTenant(this.form)).then(response => {
               this.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -391,7 +396,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有会话数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 12 - 6
src/views/company/company/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="公司名称" prop="companyName">
         <el-input
         style="width: 220px"
@@ -286,9 +289,11 @@ import {recharge,deduct, resetPwd,listCompany, getCompany, delCompany, addCompan
 import {getFollowDoctorList} from "@/api/his/doctor";
 
 import {getVoiceApiList } from "@/api/company/companyVoiceApi";
+import TenantSelect from '@/components/TenantSelect/index'
 
 export default {
   name: "Company",
+  components: { TenantSelect },
   data() {
     return {
       // 表单参数
@@ -347,6 +352,7 @@ export default {
       queryParams: {
         pageNum: 1,
         pageSize: 10,
+        tenantId: null,
         companyName: null,
         companyMobile: null,
         companyAddress: null,
@@ -418,7 +424,7 @@ export default {
     submitDeductForm() {
       this.$refs["deductForm"].validate(valid => {
         if (valid) {
-          deduct(this.deductForm).then(response => {
+          deduct(this.$withTenant(this.deductForm)).then(response => {
             if (response.code === 200) {
               this.msgSuccess(response.msg);
               this.deduct.open = false;
@@ -439,7 +445,7 @@ export default {
     submitRechargeForm() {
       this.$refs["rechargeForm"].validate(valid => {
         if (valid) {
-          recharge(this.rechargeForm).then(response => {
+          recharge(this.$withTenant(this.rechargeForm)).then(response => {
             if (response.code === 200) {
               this.msgSuccess(response.msg);
               this.recharge.open = false;
@@ -452,7 +458,7 @@ export default {
     /** 查询企业列表 */
     getList() {
       this.loading = true;
-      listCompany(this.queryParams).then(response => {
+      listCompany(this.$withTenant(this.queryParams)).then(response => {
         this.companyList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -546,7 +552,7 @@ export default {
           }
 
           if (this.form.companyId != null) {
-            updateCompany(this.form).then(response => {
+            updateCompany(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -554,7 +560,7 @@ export default {
               }
             });
           } else {
-            addCompany(this.form).then(response => {
+            addCompany(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -596,7 +602,7 @@ export default {
 
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有公司数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 4 - 1
src/views/company/companyBindUser/index.vue

@@ -29,7 +29,8 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -141,6 +142,8 @@
 <script>
 import { listCompanyBindUser, getCompanyBindUser, delCompanyBindUser, addCompanyBindUser, updateCompanyBindUser, exportCompanyBindUser } from "@/api/company/companyBindUser";
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: "CompanyBindUser",
   data() {

+ 11 - 5
src/views/company/companyDept/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="父部门id" prop="parentId">
         <el-input
           v-model="queryParams.parentId"
@@ -209,9 +212,11 @@
 
 <script>
 import { listCompanyDept, getCompanyDept, delCompanyDept, addCompanyDept, updateCompanyDept, exportCompanyDept } from "@/api/company/companyDept";
+import TenantSelect from '@/components/TenantSelect/index'
 
 export default {
   name: "CompanyDept",
+  components: { TenantSelect },
   data() {
     return {
       // 遮罩层
@@ -244,7 +249,8 @@ export default {
         phone: null,
         email: null,
         status: null,
-        companyId: null
+        companyId: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -260,7 +266,7 @@ export default {
     /** 查询部门列表 */
     getList() {
       this.loading = true;
-      listCompanyDept(this.queryParams).then(response => {
+      listCompanyDept(this.$withTenant(this.queryParams)).then(response => {
         this.companyDeptList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -329,7 +335,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.deptId != null) {
-            updateCompanyDept(this.form).then(response => {
+            updateCompanyDept(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -337,7 +343,7 @@ export default {
               }
             });
           } else {
-            addCompanyDept(this.form).then(response => {
+            addCompanyDept(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -364,7 +370,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有部门数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 9 - 3
src/views/company/companyDomain/index.vue

@@ -22,7 +22,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -199,7 +200,8 @@
             />
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleDialogQuery">搜索</el-button>
+            <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleDialogQuery">搜索</el-button>
             <el-button icon="el-icon-refresh" size="mini" @click="resetDialogQuery">重置</el-button>
           </el-form-item>
         </el-form>
@@ -245,7 +247,8 @@
             />
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="companyHandleDialogQuery">搜索
+            <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="companyHandleDialogQuery">搜索
             </el-button>
             <el-button icon="el-icon-refresh" size="mini" @click="companyResetQuery">重置</el-button>
           </el-form-item>
@@ -349,6 +352,8 @@ import { listCompany } from '@/api/company/company'
 import { getToken } from '@/utils/auth'
 import domainBind from '@/views/company/companyDomainBind/index.vue'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'CompanyDomain',
   data() {
@@ -466,6 +471,7 @@ export default {
     }
   },
   components: {
+    InlineTenantSelector,
     'childDomainBind': domainBind
   },
   created() {

+ 10 - 4
src/views/company/companyDomainBind/index.vue

@@ -20,7 +20,8 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -198,7 +199,8 @@
 <!--            />-->
 <!--          </el-form-item>-->
 <!--          <el-form-item>-->
-<!--            <el-button type="primary" icon="el-icon-search" size="mini" @click="companyHandleDialogQuery">搜索-->
+<!--            <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="companyHandleDialogQuery">搜索-->
 <!--            </el-button>-->
 <!--            <el-button icon="el-icon-refresh" size="mini" @click="companyResetQuery">重置</el-button>-->
 <!--          </el-form-item>-->
@@ -232,7 +234,8 @@
             />
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleDialogQuery">搜索</el-button>
+            <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleDialogQuery">搜索</el-button>
             <el-button icon="el-icon-refresh" size="mini" @click="resetDialogQuery">重置</el-button>
           </el-form-item>
         </el-form>
@@ -294,9 +297,12 @@ import {
 import { getCompanyUserListPage } from '@/api/company/companyUser'
 import companyBindUser from '@/views/company/companyBindUser/index.vue'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'CompanyDomainBind',
-  components: { 'childCompanyBindUser': companyBindUser },
+  components: {
+    InlineTenantSelector, 'childCompanyBindUser': companyBindUser },
   props: {
     isPageCall: {
       type: Boolean,

+ 11 - 5
src/views/company/companyMenu/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="菜单名称" prop="menuName">
         <el-input
         style="width: 220px"
@@ -273,9 +276,11 @@
 
 <script>
 import { listCompanyMenu, getCompanyMenu, delCompanyMenu, addCompanyMenu, updateCompanyMenu, exportCompanyMenu } from "@/api/company/companyMenu";
+import TenantSelect from '@/components/TenantSelect/index'
 
 export default {
   name: "CompanyMenu",
+  components: { TenantSelect },
   data() {
     return {
       // 遮罩层
@@ -312,7 +317,8 @@ export default {
         status: null,
         perms: null,
         icon: null,
-        companyId: null
+        companyId: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -331,7 +337,7 @@ export default {
     /** 查询菜单权限列表 */
     getList() {
       this.loading = true;
-      listCompanyMenu(this.queryParams).then(response => {
+      listCompanyMenu(this.$withTenant(this.queryParams)).then(response => {
         this.companyMenuList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -404,7 +410,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.menuId != null) {
-            updateCompanyMenu(this.form).then(response => {
+            updateCompanyMenu(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -412,7 +418,7 @@ export default {
               }
             });
           } else {
-            addCompanyMenu(this.form).then(response => {
+            addCompanyMenu(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -439,7 +445,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有菜单权限数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 11 - 5
src/views/company/companyMoneyLogs/index.vue

@@ -2,6 +2,10 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
 
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
+
       <el-form-item label="公司名" prop="companyId">
           <el-select filterable  style="width: 220px" v-model="queryParams.companyId" placeholder="请选择公司名" clearable size="small">
               <el-option
@@ -193,11 +197,12 @@
 import { listCompanyMoneyLogs, getCompanyMoneyLogs, delCompanyMoneyLogs, addCompanyMoneyLogs, updateCompanyMoneyLogs, exportCompanyMoneyLogs } from "@/api/company/companyMoneyLogs";
 import { getCompanyList } from "@/api/company/company";
 import { getTask } from "@/api/common";
+import TenantSelect from '@/components/TenantSelect/index'
 import storeOrderDetails  from '../../components/his/storeOrderDetails.vue';
 import liveOrderDetails from '../../live/liveOrder/liveOrderDetails.vue';
 import inquiryOrderDetails from '../../components/his/inquiryOrderDetails.vue';
 export default {
-  components: { storeOrderDetails, liveOrderDetails, inquiryOrderDetails},
+  components: { TenantSelect, storeOrderDetails, liveOrderDetails, inquiryOrderDetails},
   name: "CompanyMoneyLogs",
   data() {
     return {
@@ -249,6 +254,7 @@ export default {
         tradeCode:null,
         beginTime:null,
         endTime:null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -304,7 +310,7 @@ export default {
       else{
         this.queryParams.createTimeRange=null;
       }
-      listCompanyMoneyLogs(this.queryParams).then(response => {
+      listCompanyMoneyLogs(this.$withTenant(this.queryParams)).then(response => {
         this.companyMoneyLogsList = response.rows;
         console.log(this.queryParams)
         this.total = response.total;
@@ -371,7 +377,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.logsId != null) {
-            updateCompanyMoneyLogs(this.form).then(response => {
+            updateCompanyMoneyLogs(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -379,7 +385,7 @@ export default {
               }
             });
           } else {
-            addCompanyMoneyLogs(this.form).then(response => {
+            addCompanyMoneyLogs(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -413,7 +419,7 @@ export default {
       else{
         this.queryParams.createTimeRange=null;
       }
-      const queryParams=this.addDateRange(this.queryParams, this.dateRange)
+      const queryParams=this.$withTenant(this.addDateRange(this.queryParams, this.dateRange))
       queryParams.type=type;
       if(orderType !== undefined){
         queryParams.orderType=orderType;

+ 11 - 5
src/views/company/companyPost/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="岗位编码" prop="postCode">
         <el-input
           v-model="queryParams.postCode"
@@ -161,9 +164,11 @@
 
 <script>
 import { listCompanyPost, getCompanyPost, delCompanyPost, addCompanyPost, updateCompanyPost, exportCompanyPost } from "@/api/company/companyPost";
+import TenantSelect from '@/components/TenantSelect/index'
 
 export default {
   name: "CompanyPost",
+  components: { TenantSelect },
   data() {
     return {
       // 遮罩层
@@ -192,7 +197,8 @@ export default {
         postName: null,
         postSort: null,
         status: null,
-        companyId: null
+        companyId: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -220,7 +226,7 @@ export default {
     /** 查询岗位信息列表 */
     getList() {
       this.loading = true;
-      listCompanyPost(this.queryParams).then(response => {
+      listCompanyPost(this.$withTenant(this.queryParams)).then(response => {
         this.companyPostList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -285,7 +291,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.postId != null) {
-            updateCompanyPost(this.form).then(response => {
+            updateCompanyPost(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -293,7 +299,7 @@ export default {
               }
             });
           } else {
-            addCompanyPost(this.form).then(response => {
+            addCompanyPost(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -320,7 +326,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有岗位信息数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 8 - 3
src/views/company/companyProfit/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="公司名" prop="companyId">
           <el-select filterable style="width: 220px" v-model="queryParams.companyId" placeholder="请选择公司名" clearable size="small">
               <el-option
@@ -103,9 +106,10 @@
 <script>
 import { audit,listCompanyProfit, getCompanyProfit, delCompanyProfit, addCompanyProfit, updateCompanyProfit, exportCompanyProfit } from "@/api/company/companyProfit";
 import { getCompanyList } from "@/api/company/company";
+import TenantSelect from '@/components/TenantSelect/index'
 import companyProfit from "../components/companyProfit";
 export default {
-  components: {companyProfit },
+  components: { TenantSelect, companyProfit },
   name: "CompanyProfit",
   data() {
     return {
@@ -149,6 +153,7 @@ export default {
         balances: null,
         profitStatus: null,
         profitType: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -186,7 +191,7 @@ export default {
     /** 查询提现列表 */
     getList() {
       this.loading = true;
-      listCompanyProfit(this.queryParams).then(response => {
+      listCompanyProfit(this.$withTenant(this.queryParams)).then(response => {
         this.companyProfitList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -244,7 +249,7 @@ export default {
     
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有提现数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 9 - 3
src/views/company/companyRecharge/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="公司名称" prop="companyId">
        <el-select style="width: 220px" v-model="queryParams.companyId" placeholder="请选择公司名" clearable size="small">
               <el-option
@@ -146,8 +149,10 @@
 <script>
 import { listCompanyRecharge, getCompanyRecharge, audit, exportCompanyRecharge } from "@/api/company/companyRecharge";
 import { getCompanyList } from "@/api/company/company";
+import TenantSelect from '@/components/TenantSelect/index'
 
 export default {
+  components: { TenantSelect },
   name: "CompanyRecharge",
   data() {
     return {
@@ -183,6 +188,7 @@ export default {
         payTime: null,
         status: null,
         isAudit:0,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -215,7 +221,7 @@ export default {
     /** 查询充值列表 */
     getList() {
       this.loading = true;
-      listCompanyRecharge(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+      listCompanyRecharge(this.$withTenant(this.addDateRange(this.queryParams, this.dateRange))).then(response => {
         this.companyRechargeList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -272,7 +278,7 @@ export default {
     submitForm() {
       this.$refs["form"].validate(valid => {
         if (valid) {
-          audit(this.form).then(response => {
+          audit(this.$withTenant(this.form)).then(response => {
             if (response.code === 200) {
               this.msgSuccess("审核成功");
               this.open = false;
@@ -284,7 +290,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有充值数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 4 - 1
src/views/company/companyRedPacketBalanceLogs/index.vue

@@ -43,7 +43,8 @@
         ></el-date-picker>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -141,6 +142,8 @@
 import { listCompanyRedPacketBalanceLogs, getCompanyRedPacketBalanceLogs, delCompanyRedPacketBalanceLogs, addCompanyRedPacketBalanceLogs, updateCompanyRedPacketBalanceLogs, exportCompanyRedPacketBalanceLogs } from "@/api/company/companyRedPacketBalanceLogs";
 import { getCompanyList } from '@/api/company/company'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: "CompanyRedPacketBalanceLogs",
   data() {

+ 11 - 5
src/views/company/companyRole/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="角色名称" prop="roleName">
         <el-input
           v-model="queryParams.roleName"
@@ -203,9 +206,11 @@
 
 <script>
 import { listCompanyRole, getCompanyRole, delCompanyRole, addCompanyRole, updateCompanyRole, exportCompanyRole } from "@/api/company/companyRole";
+import TenantSelect from '@/components/TenantSelect/index'
 
 export default {
   name: "CompanyRole",
+  components: { TenantSelect },
   data() {
     return {
       // 遮罩层
@@ -237,7 +242,8 @@ export default {
         menuCheckStrictly: null,
         deptCheckStrictly: null,
         status: null,
-        companyId: null
+        companyId: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -265,7 +271,7 @@ export default {
     /** 查询角色信息列表 */
     getList() {
       this.loading = true;
-      listCompanyRole(this.queryParams).then(response => {
+      listCompanyRole(this.$withTenant(this.queryParams)).then(response => {
         this.companyRoleList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -334,7 +340,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.roleId != null) {
-            updateCompanyRole(this.form).then(response => {
+            updateCompanyRole(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -342,7 +348,7 @@ export default {
               }
             });
           } else {
-            addCompanyRole(this.form).then(response => {
+            addCompanyRole(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -369,7 +375,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有角色信息数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 11 - 5
src/views/company/companySms/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="公司名" prop="companyId">
           <el-select filterable style="width: 220px" v-model="queryParams.companyId" placeholder="请选择公司名" clearable size="small">
               <el-option
@@ -71,7 +74,9 @@
 <script>
 import { listCompanySms, getCompanySms, delCompanySms, addCompanySms, updateCompanySms, exportCompanySms } from "@/api/company/companySms";
 import { getCompanyList } from "@/api/company/company";
+import TenantSelect from '@/components/TenantSelect/index'
 export default {
+  components: { TenantSelect },
   name: "CompanySms",
   data() {
     return {
@@ -100,7 +105,8 @@ export default {
         pageSize: 10,
         companyId: null,
         remainSmsCount: null,
-        totalSmsCount: null
+        totalSmsCount: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -120,7 +126,7 @@ export default {
     /** 查询公司短信列表 */
     getList() {
       this.loading = true;
-      listCompanySms(this.queryParams).then(response => {
+      listCompanySms(this.$withTenant(this.queryParams)).then(response => {
         this.companySmsList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -178,7 +184,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.smsId != null) {
-            updateCompanySms(this.form).then(response => {
+            updateCompanySms(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -186,7 +192,7 @@ export default {
               }
             });
           } else {
-            addCompanySms(this.form).then(response => {
+            addCompanySms(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -213,7 +219,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有公司短信数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 4 - 1
src/views/company/companyTraffic/index.vue

@@ -27,7 +27,8 @@
       </el-form-item>
 
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -156,6 +157,8 @@ import { allList } from '@/api/company/company'
 import { resetForm } from '@/utils/common'
 import { delAdIqiyiAccount } from '@/api/ad/AdIqiyiAccount'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: "CompanyTraffic",
   data() {

+ 4 - 1
src/views/company/companyTrafficLog/index.vue

@@ -51,7 +51,8 @@
       </el-form-item>
 
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -122,6 +123,8 @@
 import { listTrafficLog, listTrafficLogExport } from "@/api/company/trafficLog";
 import { allList } from '@/api/company/company'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: "CompanyTrafficLog",
   data() {

+ 9 - 3
src/views/company/companyUser/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="部门ID" prop="deptId">
         <el-input
           v-model="queryParams.deptId"
@@ -298,9 +301,11 @@
 
 <script>
 import { listCompanyUser, getCompanyUser, delCompanyUser, addCompanyUser, updateCompanyUser, exportCompanyUser } from "@/api/company/companyUser";
+import TenantSelect from '@/components/TenantSelect/index'
 
 export default {
   name: "CompanyUser",
+  components: { TenantSelect },
   data() {
     return {
       // 遮罩层
@@ -325,6 +330,7 @@ export default {
       queryParams: {
         pageNum: 1,
         pageSize: 10,
+        tenantId: null,
         deptId: null,
         userName: null,
         nickName: null,
@@ -361,7 +367,7 @@ export default {
     /** 查询企业员工信息列表 */
     getList() {
       this.loading = true;
-      listCompanyUser(this.queryParams).then(response => {
+      listCompanyUser(this.$withTenant(this.queryParams)).then(response => {
         this.companyUserList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -437,7 +443,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.userId != null) {
-            updateCompanyUser(this.form).then(response => {
+            updateCompanyUser(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -445,7 +451,7 @@ export default {
               }
             });
           } else {
-            addCompanyUser(this.form).then(response => {
+            addCompanyUser(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;

+ 4 - 1
src/views/company/companyWorkflow/index.vue

@@ -31,7 +31,8 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -260,6 +261,8 @@
 import { listWorkflow, delWorkflow, updateWorkflowStatus, copyWorkflow, exportWorkflow, getBindCompanyUserByWorkflowId,
          listCompanyUser, updateWorkflowBindCompanyUser, getWorkflowVersionList, getWorkflowVersionDetail, rollbackWorkflowVersion} from '@/api/company/companyWorkflow'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'CompanyWorkflow',
   data() {

+ 4 - 1
src/views/company/workflowExternalApi/index.vue

@@ -22,7 +22,8 @@
           </el-select>
         </el-form-item>
         <el-form-item>
-          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
+          <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
           <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
         </el-form-item>
       </el-form>
@@ -235,6 +236,8 @@ import {
   pageExternalApiLogs
 } from '@/api/company/externalApi'
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: 'CompanyWorkflowExternalApi',
   data() {

+ 11 - 5
src/views/company/wxAccount/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="微信昵称" prop="wxNickName">
         <el-input
           v-model="queryParams.wxNickName"
@@ -146,10 +149,12 @@
 <script>
 import { listCompanyAccount, getCompanyAccount, delCompanyAccount, addCompanyAccount, updateCompanyAccount, exportCompanyAccount, companyListAll } from "@/api/company/companyAccount";
 import {getAllUserlist} from "@/api/company/companyUser";
+import TenantSelect from '@/components/TenantSelect/index'
 
 
 export default {
   name: "CompanyAccount",
+  components: { TenantSelect },
   data() {
     return {
       // 遮罩层
@@ -178,7 +183,8 @@ export default {
         wxNickName: null,
         wxNo: null,
         companyUserId: null,
-        createUser: null
+        createUser: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -197,7 +203,7 @@ export default {
     /** 查询个微账号列表 */
     getList() {
       this.loading = true;
-      listCompanyAccount(this.queryParams).then(response => {
+      listCompanyAccount(this.$withTenant(this.queryParams)).then(response => {
         this.companyAccountList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -257,7 +263,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.id != null) {
-            updateCompanyAccount(this.form).then(response => {
+            updateCompanyAccount(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -265,7 +271,7 @@ export default {
               }
             });
           } else {
-            addCompanyAccount(this.form).then(response => {
+            addCompanyAccount(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -292,7 +298,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
+      const queryParams = this.$withTenant(this.queryParams);
       this.$confirm('是否确认导出所有个微账号数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 6 - 2
src/views/company/wxUser/index.vue

@@ -40,7 +40,8 @@
 
 
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <inline-tenant-selector @change="handleQuery" />
+      <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -215,9 +216,12 @@ import wxUserGroup from "@/views/company/wxUserGroup/wxUserGroup.vue";
 import {listWxUserGroup} from "@/api/wxUser/wxUserGroup";
 
 
+import InlineTenantSelector from "@/components/InlineTenantSelector"
+
 export default {
   name: "WxUser",
-  components: {wxUserGroup},
+  components: {
+    InlineTenantSelector,wxUserGroup},
   data() {
     return {
       // 遮罩层

+ 5 - 0
src/views/course/courseAnswerLog/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Courseanswerlog",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/courseAnswerLog/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:courseAnswerLog:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:courseAnswerLog:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:courseAnswerLog:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseCourseanswerlog",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/courseAnswerLog/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/courseAnswerLog/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/courseAnswerLog", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/courseAnswerLog", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/courseAnswerLog/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/courseQuestionCategory/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Coursequestioncategory",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/courseQuestionCategory/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:courseQuestionCategory:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:courseQuestionCategory:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:courseQuestionCategory:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseCoursequestioncategory",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/courseQuestionCategory/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/courseQuestionCategory/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/courseQuestionCategory", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/courseQuestionCategory", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/courseQuestionCategory/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 98 - 19
src/views/course/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "Course",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/period/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Period",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/period/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:period:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:period:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:period:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CoursePeriod",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/period/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/period/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/period", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/period", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/period/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/playSourceConfig/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Playsourceconfig",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/playSourceConfig/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:playSourceConfig:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:playSourceConfig:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:playSourceConfig:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CoursePlaysourceconfig",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/playSourceConfig/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/playSourceConfig/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/playSourceConfig", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/playSourceConfig", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/playSourceConfig/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/sopLogs/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Soplogs",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/sopLogs/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:sopLogs:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:sopLogs:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:sopLogs:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseSoplogs",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/sopLogs/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/sopLogs/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/sopLogs", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/sopLogs", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/sopLogs/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/trainingCamp/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Trainingcamp",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/trainingCamp/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:trainingCamp:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:trainingCamp:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:trainingCamp:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseTrainingcamp",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/trainingCamp/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/trainingCamp/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/trainingCamp", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/trainingCamp", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/trainingCamp/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userCourseCommentLike/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Usercoursecommentlike",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userCourseCommentLike/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userCourseCommentLike:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userCourseCommentLike:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userCourseCommentLike:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUsercoursecommentlike",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userCourseCommentLike/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userCourseCommentLike/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userCourseCommentLike", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userCourseCommentLike", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userCourseCommentLike/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userCourseFavorite/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Usercoursefavorite",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userCourseFavorite/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userCourseFavorite:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userCourseFavorite:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userCourseFavorite:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUsercoursefavorite",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userCourseFavorite/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userCourseFavorite/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userCourseFavorite", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userCourseFavorite", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userCourseFavorite/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userCourseNoteLike/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Usercoursenotelike",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userCourseNoteLike/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userCourseNoteLike:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userCourseNoteLike:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userCourseNoteLike:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUsercoursenotelike",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userCourseNoteLike/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userCourseNoteLike/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userCourseNoteLike", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userCourseNoteLike", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userCourseNoteLike/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userCourseVideo/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Usercoursevideo",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userCourseVideo/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userCourseVideo:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userCourseVideo:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userCourseVideo:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUsercoursevideo",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userCourseVideo/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userCourseVideo/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userCourseVideo", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userCourseVideo", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userCourseVideo/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userTalentFollow/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Usertalentfollow",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userTalentFollow/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userTalentFollow:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userTalentFollow:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userTalentFollow:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUsertalentfollow",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userTalentFollow/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userTalentFollow/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userTalentFollow", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userTalentFollow", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userTalentFollow/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userVideoCommentLike/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Uservideocommentlike",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userVideoCommentLike/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userVideoCommentLike:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userVideoCommentLike:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userVideoCommentLike:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUservideocommentlike",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userVideoCommentLike/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userVideoCommentLike/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userVideoCommentLike", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userVideoCommentLike", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userVideoCommentLike/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userVideoFavorite/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Uservideofavorite",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userVideoFavorite/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userVideoFavorite:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userVideoFavorite:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userVideoFavorite:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUservideofavorite",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userVideoFavorite/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userVideoFavorite/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userVideoFavorite", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userVideoFavorite", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userVideoFavorite/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userVideoLike/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Uservideolike",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userVideoLike/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userVideoLike:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userVideoLike:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userVideoLike:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUservideolike",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userVideoLike/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userVideoLike/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userVideoLike", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userVideoLike", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userVideoLike/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/userVideoView/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Uservideoview",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/userVideoView/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:userVideoView:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:userVideoView:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:userVideoView:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseUservideoview",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/userVideoView/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/userVideoView/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/userVideoView", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/userVideoView", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/userVideoView/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 5 - 0
src/views/course/videoTags/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,9 +62,11 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "Videotags",
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,

+ 98 - 19
src/views/course/videoTags/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['course:videoTags:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['course:videoTags:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['course:videoTags:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CourseVideotags",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/course/videoTags/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/course/videoTags/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/course/videoTags", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/course/videoTags", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/course/videoTags/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 4 - 0
src/views/courseFinishTemp/course/index.vue

@@ -5,6 +5,9 @@
         <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
           @keyup.enter.native="handleQuery" />
       </el-form-item>
+      <el-form-item label="租户">
+        <inline-tenant-selector @change="handleQuery" />
+      </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,6 +62,7 @@
 
 <script>
 import { getRequest, delRequest } from "@/api/common";
+import InlineTenantSelector from "@/components/InlineTenantSelector";
 
 export default {
   name: "",

+ 98 - 19
src/views/courseFinishTemp/course/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['courseFinishTemp:course:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['courseFinishTemp:course:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['courseFinishTemp:course:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CoursefinishtempCourse",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/courseFinishTemp/course/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/courseFinishTemp/course/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/courseFinishTemp/course", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/courseFinishTemp/course", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/courseFinishTemp/course/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 10 - 5
src/views/crm/customer/index.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户" prop="tenantId">
+        <tenant-select v-model="queryParams.tenantId" @change="handleQuery" />
+      </el-form-item>
       <el-form-item label="公司名" prop="companyId">
           <el-select filterable  v-model="queryParams.companyId" placeholder="请选择公司名" clearable size="small">
               <el-option
@@ -325,13 +328,14 @@
 <script>
 import { listCustomer,getCustomer,addCustomer,updateCustomer,delCustomer,exportCustomer  } from "@/api/crm/customer";
 import { getCompanyList } from "@/api/company/company";
+import TenantSelect from '@/components/TenantSelect/index'
 import customerDetails from '../components/customerDetails.vue';
 import editCustomerSource from '../components/editCustomerSource.vue';
 import {getCitys} from "@/api/store/city";
 import { throwStatement } from "@babel/types";
 export default {
   name: "Customer",
-  components: { customerDetails,editCustomerSource },
+  components: { TenantSelect, customerDetails,editCustomerSource },
   data() {
     return {
       source:{
@@ -408,6 +412,7 @@ export default {
         tags: null,
         beginTime: null,
         endTime: null,
+        tenantId: null
       },
       // 表单参数
       form: {},
@@ -539,7 +544,7 @@ export default {
         this.queryParams.tags=null
       }
 
-      listCustomer(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+      listCustomer(this.$withTenant(this.addDateRange(this.queryParams, this.dateRange))).then(response => {
         this.customerList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -652,7 +657,7 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.customerId != null) {
-            updateCustomer(this.form).then(response => {
+            updateCustomer(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
                 this.open = false;
@@ -660,7 +665,7 @@ export default {
               }
             });
           } else {
-            addCustomer(this.form).then(response => {
+            addCustomer(this.$withTenant(this.form)).then(response => {
               if (response.code === 200) {
                 this.msgSuccess("新增成功");
                 this.open = false;
@@ -688,7 +693,7 @@ export default {
     /** 导出按钮操作 */
     handleExport() {
       //const queryParams = this.queryParams;
-      const queryParams=this.addDateRange(this.queryParams, this.dateRange)
+      const queryParams=this.$withTenant(this.addDateRange(this.queryParams, this.dateRange))
       this.$confirm('是否确认导出客户数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",

+ 98 - 19
src/views/crm/customerAssign/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['crm:customerAssign:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['crm:customerAssign:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['crm:customerAssign:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CrmCustomerassign",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/crm/customerAssign/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/crm/customerAssign/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/crm/customerAssign", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/crm/customerAssign", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/crm/customerAssign/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

+ 98 - 19
src/views/crm/customerLevel/index/index.vue

@@ -6,21 +6,33 @@
           @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
-        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['crm:customerLevel:add']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
+          @click="handleDelete" v-hasPermi="['crm:customerLevel:remove']">删除</el-button>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="50" align="center" />
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+
+    <el-table border v-loading="loading" :data="list" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
             v-hasPermi="['crm:customerLevel:edit']">修改</el-button>
@@ -29,28 +41,48 @@
         </template>
       </el-table-column>
     </el-table>
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { getRequest, postRequest, putRequest, delRequest } from "@/api/common";
+
 export default {
   name: "CrmCustomerlevel",
   data() {
     return {
       loading: true,
       ids: [],
-      single: true,
       multiple: true,
       showSearch: true,
       total: 0,
       list: [],
+      title: "",
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         keyword: null
-      }
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
+      },
     };
   },
   created() {
@@ -59,10 +91,15 @@ export default {
   methods: {
     getList() {
       this.loading = true;
-      // TODO: 接入API
-      this.list = [];
-      this.total = 0;
-      this.loading = false;
+      getRequest("/crm/customerLevel/list", this.queryParams).then(response => {
+        this.list = response.rows || [];
+        this.total = response.total || 0;
+        this.loading = false;
+      }).catch(() => {
+        this.list = [];
+        this.total = 0;
+        this.loading = false;
+      });
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -72,22 +109,64 @@ export default {
       this.resetForm("queryForm");
       this.handleQuery();
     },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    reset() {
+      this.form = { id: null, name: null };
+      this.resetForm("form");
+    },
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id);
-      this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
     handleAdd() {
-      this.$message.info("新增功能开发中");
+      this.reset();
+      this.open = true;
+      this.title = "新增";
     },
     handleUpdate(row) {
-      this.$message.info("修改功能开发中");
+      this.reset();
+      const id = row.id || this.ids;
+      getRequest("/crm/customerLevel/" + id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改";
+      });
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            putRequest("/crm/customerLevel", this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            postRequest("/crm/customerLevel", this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
     },
     handleDelete(row) {
-      this.$modal.confirm("是否确认删除?").then(() => {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除选中的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return delRequest("/crm/customerLevel/" + ids);
+      }).then(() => {
+        this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
-    }
-  }
+    },
+  },
 };
 </script>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels