boss 4 napja
szülő
commit
78db50415a
46 módosított fájl, 656 hozzáadás és 113 törlés
  1. 4 0
      src/api/admin/ad.js
  2. 5 0
      src/api/admin/aiChatQuality.js
  3. 4 1
      src/api/admin/article.js
  4. 9 0
      src/api/admin/callRecord.js
  5. 9 0
      src/api/admin/commissionRecord.js
  6. 9 0
      src/api/admin/consumeRecord.js
  7. 5 0
      src/api/admin/course.js
  8. 4 0
      src/api/admin/crm.js
  9. 5 0
      src/api/admin/live.js
  10. 4 0
      src/api/admin/moduleUsage.js
  11. 5 0
      src/api/admin/product.js
  12. 15 0
      src/api/admin/proxyOperLog.js
  13. 5 0
      src/api/admin/qwExternalContact.js
  14. 10 1
      src/api/admin/rechargeRecord.js
  15. 5 0
      src/api/admin/serviceCost.js
  16. 4 0
      src/api/admin/sop.js
  17. 4 0
      src/api/admin/storeOrder.js
  18. 19 1
      src/api/admin/sysCompany.js
  19. 9 0
      src/api/admin/sysUser.js
  20. 9 0
      src/api/admin/withdrawalManage.js
  21. 8 2
      src/views/admin/ad/index.vue
  22. 26 2
      src/views/admin/agentPricing/index.vue
  23. 4 3
      src/views/admin/agentReport/index.vue
  24. 6 4
      src/views/admin/aiChatQuality/index.vue
  25. 6 4
      src/views/admin/article/index.vue
  26. 6 4
      src/views/admin/callRecord/index.vue
  27. 4 10
      src/views/admin/cidConfig/index.vue
  28. 5 3
      src/views/admin/commissionRecord/index.vue
  29. 5 3
      src/views/admin/consumeRecord/index.vue
  30. 6 4
      src/views/admin/course/index.vue
  31. 8 2
      src/views/admin/crm/index.vue
  32. 4 10
      src/views/admin/frontConfig/index.vue
  33. 30 1
      src/views/admin/ipadServer/index.vue
  34. 6 4
      src/views/admin/live/index.vue
  35. 6 2
      src/views/admin/moduleUsage/index.vue
  36. 4 10
      src/views/admin/ossConfig/index.vue
  37. 6 4
      src/views/admin/product/index.vue
  38. 213 5
      src/views/admin/proxyOperLog/index.vue
  39. 6 5
      src/views/admin/qwExternalContact/index.vue
  40. 5 3
      src/views/admin/rechargeRecord/index.vue
  41. 8 2
      src/views/admin/sop/index.vue
  42. 8 2
      src/views/admin/storeOrder/index.vue
  43. 118 4
      src/views/admin/sysCompany/index.vue
  44. 6 4
      src/views/admin/sysUser/index.vue
  45. 5 3
      src/views/admin/withdrawalManage/index.vue
  46. 4 10
      src/views/admin/wxConfig/index.vue

+ 4 - 0
src/api/admin/ad.js

@@ -3,3 +3,7 @@ import request from '@/utils/request'
 export function listAdAccount(query) {
   return request({ url: '/admin/ad/list', method: 'get', params: query })
 }
+
+export function exportAdAccount(query) {
+  return request({ url: '/admin/ad/export', method: 'get', params: query })
+}

+ 5 - 0
src/api/admin/aiChatQuality.js

@@ -1,5 +1,10 @@
 import request from '@/utils/request'
 
+// 导出AI对话会话
+export function exportChatSessions(query) {
+  return request({ url: '/admin/aiChatQuality/export', method: 'get', params: query })
+}
+
 // 查询AI聊天会话列表
 export function listChatSessions(query) {
   return request({

+ 4 - 1
src/api/admin/article.js

@@ -50,7 +50,10 @@ export function deleteArticle(articleId) {
   })
 }
 
-// 获取文章统计信息
+// 导出文章
+export function exportAllArticles(query) {
+  return request({ url: '/admin/article/export', method: 'get', params: query })
+}
 export function getArticleStatistics() {
   return request({
     url: '/admin/article/statistics',

+ 9 - 0
src/api/admin/callRecord.js

@@ -91,4 +91,13 @@ export function getCallStatistics() {
     url: '/admin/callRecord/statistics',
     method: 'get'
   })
+}
+
+// 导出通话记录
+export function exportCallRecord(query) {
+  return request({
+    url: '/admin/callRecord/export',
+    method: 'get',
+    params: query
+  })
 }

+ 9 - 0
src/api/admin/commissionRecord.js

@@ -16,3 +16,12 @@ export function getCommissionRecord(id) {
     method: 'get'
   })
 }
+
+// 导出返佣记录
+export function exportCommissionRecord(query) {
+  return request({
+    url: '/admin/commission-record/export',
+    method: 'get',
+    params: query
+  })
+}

+ 9 - 0
src/api/admin/consumeRecord.js

@@ -16,3 +16,12 @@ export function getConsumeRecord(id) {
     method: 'get'
   })
 }
+
+// 导出消费记录
+export function exportConsumeRecord(query) {
+  return request({
+    url: '/admin/consume-record/export',
+    method: 'get',
+    params: query
+  })
+}

+ 5 - 0
src/api/admin/course.js

@@ -25,6 +25,11 @@ export function getCourseInfo(courseId) {
   })
 }
 
+// 导出课程
+export function exportAllCourses(query) {
+  return request({ url: '/admin/course/export', method: 'get', params: query })
+}
+
 // 获取课程统计信息
 export function getCourseStatistics() {
   return request({

+ 4 - 0
src/api/admin/crm.js

@@ -3,3 +3,7 @@ import request from '@/utils/request'
 export function listCrmCustomer(query) {
   return request({ url: '/admin/crm/list', method: 'get', params: query })
 }
+
+export function exportCrmCustomer(query) {
+  return request({ url: '/admin/crm/export', method: 'get', params: query })
+}

+ 5 - 0
src/api/admin/live.js

@@ -25,6 +25,11 @@ export function getLiveInfo(liveId) {
   })
 }
 
+// 导出直播
+export function exportAllLives(query) {
+  return request({ url: '/admin/live/export', method: 'get', params: query })
+}
+
 // 获取直播统计信息
 export function getLiveStatistics() {
   return request({

+ 4 - 0
src/api/admin/moduleUsage.js

@@ -23,3 +23,7 @@ export function refreshStatistics() {
 export function refreshTenantStatistics(tenantId) {
   return request({ url: `/admin/module-usage/refresh/${tenantId}`, method: 'post' })
 }
+
+export function exportModuleUsage(query) {
+  return request({ url: '/admin/module-usage/export', method: 'get', params: query })
+}

+ 5 - 0
src/api/admin/product.js

@@ -42,6 +42,11 @@ export function auditProduct(productId, status, auditRemark) {
   })
 }
 
+// 导出商品
+export function exportAllProducts(query) {
+  return request({ url: '/admin/product/export', method: 'get', params: query })
+}
+
 // 获取商品统计信息
 export function getProductStatistics() {
   return request({

+ 15 - 0
src/api/admin/proxyOperLog.js

@@ -0,0 +1,15 @@
+import request from '@/utils/request'
+
+// 查询代理操作日志列表
+export function listProxyOperLog(params) {
+  return request({
+    url: '/admin/proxyOperLog/list',
+    method: 'get',
+    params: params
+  })
+}
+
+// 导出代理操作日志
+export function exportProxyOperLog(query) {
+  return request({ url: '/admin/proxyOperLog/export', method: 'get', params: query })
+}

+ 5 - 0
src/api/admin/qwExternalContact.js

@@ -25,6 +25,11 @@ export function getExternalContact(id) {
   })
 }
 
+// 导出企微外部联系人
+export function exportAllExternalContact(query) {
+  return request({ url: '/admin/qwContact/export', method: 'get', params: query })
+}
+
 // 获取统计信息
 export function getStatistics() {
   return request({

+ 10 - 1
src/api/admin/rechargeRecord.js

@@ -9,10 +9,19 @@ export function listRechargeRecords(query) {
   })
 }
 
-// 获取充记录详情
+// 获取充记录详情
 export function getRechargeRecord(id) {
   return request({
     url: '/admin/recharge-record/' + id,
     method: 'get'
   })
 }
+
+// 导出充値记录
+export function exportRechargeRecord(query) {
+  return request({
+    url: '/admin/recharge-record/export',
+    method: 'get',
+    params: query
+  })
+}

+ 5 - 0
src/api/admin/serviceCost.js

@@ -27,3 +27,8 @@ export function listServicePrice(query) {
 export function batchSaveServicePrice(data) {
   return request({ url: '/admin/servicePrice/batch', method: 'post', data })
 }
+
+// 代理定价批量保存(代理端接口)
+export function batchSaveProxyServicePrice(data) {
+  return request({ url: '/proxy/servicePrice/batch', method: 'put', data })
+}

+ 4 - 0
src/api/admin/sop.js

@@ -7,3 +7,7 @@ export function listSop(query) {
 export function listSopTemp(query) {
   return request({ url: '/admin/sop/temp/list', method: 'get', params: query })
 }
+
+export function exportSop(query) {
+  return request({ url: '/admin/sop/export', method: 'get', params: query })
+}

+ 4 - 0
src/api/admin/storeOrder.js

@@ -3,3 +3,7 @@ import request from '@/utils/request'
 export function listStoreOrder(query) {
   return request({ url: '/admin/storeOrder/list', method: 'get', params: query })
 }
+
+export function exportStoreOrder(query) {
+  return request({ url: '/admin/storeOrder/export', method: 'get', params: query })
+}

+ 19 - 1
src/api/admin/sysCompany.js

@@ -43,11 +43,29 @@ export function getStatistics() {
   })
 }
 
-// 租户充值/扣款
+// 新增租户
+export function addCompany(data) {
+  return request({
+    url: '/admin/company',
+    method: 'post',
+    data: data
+  })
+}
+
+// 租户充値/扣款
 export function rechargeCompany(companyId, data) {
   return request({
     url: '/admin/company/' + companyId + '/recharge',
     method: 'post',
     data: data
   })
+}
+
+// 导出租户列表
+export function exportCompany(query) {
+  return request({
+    url: '/admin/company/export',
+    method: 'get',
+    params: query
+  })
 }

+ 9 - 0
src/api/admin/sysUser.js

@@ -58,4 +58,13 @@ export function getStatistics() {
     url: '/admin/companyUser/statistics',
     method: 'get'
   })
+}
+
+// 导出员工列表
+export function exportSysUser(query) {
+  return request({
+    url: '/admin/companyUser/export',
+    method: 'get',
+    params: query
+  })
 }

+ 9 - 0
src/api/admin/withdrawalManage.js

@@ -41,3 +41,12 @@ export function confirmPaid(id) {
     method: 'put'
   })
 }
+
+// 导出提现申请
+export function exportWithdrawal(query) {
+  return request({
+    url: '/admin/withdrawal/export',
+    method: 'get',
+    params: query
+  })
+}

+ 8 - 2
src/views/admin/ad/index.vue

@@ -37,7 +37,7 @@
 </template>
 
 <script>
-import { listAdAccount } from '@/api/admin/ad'
+import { listAdAccount, exportAdAccount } from '@/api/admin/ad'
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
@@ -66,7 +66,13 @@ export default {
     },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
     resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
-    handleExport() { this.$message.info('导出功能开发中') }
+    handleExport() {
+      this.exportLoading = true
+      exportAdAccount(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
+    }
   }
 }
 </script>

+ 26 - 2
src/views/admin/agentPricing/index.vue

@@ -43,7 +43,7 @@
 
 <script>
 import { listProxy, allEnabledProxies } from '@/api/admin/proxy'
-import { listServicePrice } from '@/api/admin/serviceCost'
+import { listServicePrice, batchSaveProxyServicePrice } from '@/api/admin/serviceCost'
 
 export default {
   name: 'AdminAgentPricing',
@@ -64,6 +64,11 @@ export default {
     fetchProxies() {
       allEnabledProxies().then(res => {
         this.proxyList = res.data || []
+        // 自动选中第一个代理并加载定价
+        if (this.proxyList.length > 0) {
+          this.selectedProxyId = this.proxyList[0].proxyId
+          this.onProxyChange()
+        }
       }).catch(() => {})
     },
     onProxyChange() {
@@ -88,7 +93,26 @@ export default {
       }).catch(() => {}).finally(() => { this.loading = false })
     },
     batchSave() {
-      this.$message.success('定价保存成功')
+      if (!this.mergedList.length) {
+        this.$message.warning('没有可保存的定价数据')
+        return
+      }
+      this.saving = true
+      const data = this.mergedList.map(item => ({
+        proxyId: this.selectedProxyId,
+        modelCode: item.modelCode,
+        modelName: item.modelName,
+        upstreamInputPrice: item.upstreamInputPrice,
+        baseOutputPrice: item.baseOutputPrice,
+        agentInputPrice: item.agentInputPrice,
+        agentOutputPrice: item.agentOutputPrice
+      }))
+      batchSaveProxyServicePrice(data).then(() => {
+        this.$message.success('定价保存成功')
+        this.fetchPricing()
+      }).catch(() => {
+        this.$message.error('保存失败,请重试')
+      }).finally(() => { this.saving = false })
     }
   }
 }

+ 4 - 3
src/views/admin/agentReport/index.vue

@@ -8,7 +8,7 @@
     </div>
 
     <!-- 时间范围切换 -->
-    <el-card shadow="hover" class="filter-card">
+    <el-card shadow="never" class="mb16 filter-card">
       <el-radio-group v-model="daysRange" size="small" @change="fetchData">
         <el-radio-button :label="7">近7天</el-radio-button>
         <el-radio-button :label="30">近30天</el-radio-button>
@@ -26,7 +26,7 @@
           <span class="card-header-title">代理收入排名</span>
         </div>
       </div>
-      <el-table :data="agentReport" border v-loading="loading" size="small">
+      <el-table :data="agentReport" border v-loading="loading" size="small" style="width:100%">
         <el-table-column type="index" label="#" width="60" />
         <el-table-column prop="proxyName" label="代理名称" min-width="120" />
         <el-table-column prop="proxyCode" label="代理编码" min-width="120" />
@@ -88,7 +88,8 @@ export default {
 .page-header { margin-bottom: 16px; }
 .page-title { font-size: 22px; font-weight: 700; color: #1e293b; margin: 0 0 4px 0; }
 .page-desc { font-size: 14px; color: #94a3b8; margin: 0; }
-.filter-card { border-radius: 16px; border: none; }
+.mb16 { margin-bottom: 16px; }
+.filter-card { border-radius: 16px; border: none; padding-bottom: 0; }
 .card-header { display: flex; justify-content: space-between; align-items: center; }
 .card-header-left { display: flex; align-items: center; gap: 10px; }
 .card-header-icon { width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; }

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

@@ -138,7 +138,7 @@
 </template>
 
 <script>
-import { listChatSessions, getSessionMessages, addQualityRecord } from '@/api/admin/aiChatQuality'
+import { listChatSessions, getSessionMessages, addQualityRecord, exportChatSessions } from '@/api/admin/aiChatQuality'
 
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
@@ -240,11 +240,13 @@ export default {
         }
       })
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportChatSessions(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 6 - 4
src/views/admin/article/index.vue

@@ -208,7 +208,7 @@
 </template>
 
 <script>
-import { listAllArticles, listPendingArticles, getArticleInfo, auditArticle, deleteArticle, getArticleStatistics } from '@/api/admin/article'
+import { listAllArticles, listPendingArticles, getArticleInfo, auditArticle, deleteArticle, getArticleStatistics, exportAllArticles } from '@/api/admin/article'
 
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
@@ -345,11 +345,13 @@ export default {
         this.showStatistics = true
       })
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportAllArticles(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

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

@@ -266,7 +266,7 @@
 </template>
 
 <script>
-import { listAllCallRecords, getCallRecordInfo, addQualityRecord, listQualityRecords, updateQualityRecord, deleteQualityRecord, reportQuality, getCallStatistics } from '@/api/admin/callRecord'
+import { listAllCallRecords, getCallRecordInfo, addQualityRecord, listQualityRecords, updateQualityRecord, deleteQualityRecord, reportQuality, getCallStatistics, exportCallRecord } from '@/api/admin/callRecord'
 
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
@@ -455,11 +455,13 @@ export default {
         return `${secs}秒`
       }
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportCallRecord(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     },
     /** 选择变化 */
     handleSelectionChange(selection) {

+ 4 - 10
src/views/admin/cidConfig/index.vue

@@ -66,10 +66,10 @@
           </el-form-item>
         </el-card>
 
-        <div class="footer">
-          <el-button type="primary" :loading="submitLoading" @click="submitForm">提 交</el-button>
-        </div>
       </el-form>
+      <div style="text-align: center; margin-top: 20px; padding-bottom: 20px;">
+        <el-button type="primary" size="medium" @click="submitForm" :loading="submitLoading">保存配置</el-button>
+      </div>
     </el-card>
   </div>
 </template>
@@ -207,11 +207,5 @@ export default {
   font-size: 12px;
   margin-left: 8px;
 }
-.footer {
-  width: 100%;
-  display: flex;
-  margin-top: 30px;
-  align-items: flex-end;
-  justify-content: flex-end;
-}
+
 </style>

+ 5 - 3
src/views/admin/commissionRecord/index.vue

@@ -97,7 +97,7 @@
 </template>
 
 <script>
-import { listCommissionRecords, getCommissionRecord } from '@/api/admin/commissionRecord'
+import { listCommissionRecords, getCommissionRecord, exportCommissionRecord } from '@/api/admin/commissionRecord'
 
 export default {
   name: 'AdminCommissionRecord',
@@ -157,8 +157,10 @@ export default {
     },
     handleExport() {
       this.exportLoading = true
-      this.$message.info('导出功能开发中')
-      this.exportLoading = false
+      exportCommissionRecord(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 5 - 3
src/views/admin/consumeRecord/index.vue

@@ -128,7 +128,7 @@
 </template>
 
 <script>
-import { listConsumeRecords, getConsumeRecord } from '@/api/admin/consumeRecord'
+import { listConsumeRecords, getConsumeRecord, exportConsumeRecord } from '@/api/admin/consumeRecord'
 
 export default {
   name: 'AdminConsumeRecord',
@@ -212,8 +212,10 @@ export default {
     },
     handleExport() {
       this.exportLoading = true
-      this.$message.info('导出功能开发中')
-      this.exportLoading = false
+      exportConsumeRecord(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 6 - 4
src/views/admin/course/index.vue

@@ -171,7 +171,7 @@
 </template>
 
 <script>
-import { listAllCourses, getCourseInfo, getCourseStatistics } from '@/api/admin/course'
+import { listAllCourses, getCourseInfo, getCourseStatistics, exportAllCourses } from '@/api/admin/course'
 
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
@@ -259,11 +259,13 @@ export default {
         this.showStatistics = true
       })
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportAllCourses(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 8 - 2
src/views/admin/crm/index.vue

@@ -37,7 +37,7 @@
 </template>
 
 <script>
-import { listCrmCustomer } from '@/api/admin/crm'
+import { listCrmCustomer, exportCrmCustomer } from '@/api/admin/crm'
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
@@ -66,7 +66,13 @@ export default {
     },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
     resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
-    handleExport() { this.$message.info('导出功能开发中') }
+    handleExport() {
+      this.exportLoading = true
+      exportCrmCustomer(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
+    }
   }
 }
 </script>

+ 4 - 10
src/views/admin/frontConfig/index.vue

@@ -126,10 +126,10 @@
           </el-row>
         </el-card>
 
-        <div class="footer">
-          <el-button type="primary" :loading="submitLoading" @click="submitForm">提 交</el-button>
-        </div>
       </el-form>
+      <div style="text-align: center; margin-top: 20px; padding-bottom: 20px;">
+        <el-button type="primary" size="medium" @click="submitForm" :loading="submitLoading">保存配置</el-button>
+      </div>
     </el-card>
   </div>
 </template>
@@ -208,11 +208,5 @@ export default {
 .section-card {
   margin-bottom: 20px;
 }
-.footer {
-  width: 100%;
-  display: flex;
-  margin-top: 30px;
-  align-items: flex-end;
-  justify-content: flex-end;
-}
+
 </style>

+ 30 - 1
src/views/admin/ipadServer/index.vue

@@ -1,5 +1,24 @@
 <template>
   <div class="app-container">
+    <!-- ===== 搜索区 ===== -->
+    <el-card shadow="never" class="mb16 filter-card">
+      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
+        <el-form-item label="服务器地址" prop="serverIp">
+          <el-input v-model="queryParams.serverIp" placeholder="请输入服务器IP" clearable style="width:200px" @keyup.enter.native="handleQuery" />
+        </el-form-item>
+        <el-form-item label="状态" prop="status">
+          <el-select v-model="queryParams.status" placeholder="全部状态" clearable style="width:120px">
+            <el-option label="在线" :value="1" />
+            <el-option label="离线" :value="0" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <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-card>
+
     <!-- ===== 操作栏 ===== -->
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
@@ -67,7 +86,7 @@ export default {
       loading: false,
       dataList: [],
       total: 0,
-      queryParams: { pageNum: 1, pageSize: 10 },
+      queryParams: { pageNum: 1, pageSize: 10, serverIp: '', status: '' },
       dialogVisible: false,
       formTitle: '',
       submitting: false,
@@ -135,6 +154,15 @@ export default {
         URL.revokeObjectURL(link.href)
       })
     },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.loadList()
+    },
+    resetQuery() {
+      this.$refs['queryForm'].resetFields()
+      this.queryParams = { pageNum: 1, pageSize: 10, serverIp: '', status: '' }
+      this.loadList()
+    },
     reset() {
       this.form = { id: null, serverIp: '', port: 8080, remark: '' }
       if (this.$refs['form']) this.$refs['form'].resetFields()
@@ -147,4 +175,5 @@ export default {
 .mb8 { margin-bottom: 8px; }
 .mb16 { margin-bottom: 16px; }
 .filter-card { padding-bottom: 0; }
+
 </style>

+ 6 - 4
src/views/admin/live/index.vue

@@ -174,7 +174,7 @@
 </template>
 
 <script>
-import { listAllLives, getLiveInfo, getLiveStatistics } from '@/api/admin/live'
+import { listAllLives, getLiveInfo, getLiveStatistics, exportAllLives } from '@/api/admin/live'
 
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
@@ -263,11 +263,13 @@ export default {
         this.showStatistics = true
       })
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportAllLives(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 6 - 2
src/views/admin/moduleUsage/index.vue

@@ -144,7 +144,7 @@
 </template>
 
 <script>
-import { listModuleUsageSummary, getTenantDetail, refreshStatistics } from '@/api/admin/moduleUsage'
+import { listModuleUsageSummary, getTenantDetail, refreshStatistics, exportModuleUsage } from '@/api/admin/moduleUsage'
 
 export default {
   name: 'AdminModelUsage',
@@ -244,7 +244,11 @@ export default {
       })
     },
     handleExport() {
-      this.$message.info('导出功能开发中')
+      this.exportLoading = true
+      exportModuleUsage(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 4 - 10
src/views/admin/ossConfig/index.vue

@@ -108,10 +108,10 @@
           </el-card>
         </template>
 
-        <div class="footer">
-          <el-button type="primary" :loading="submitLoading" @click="submitForm">提 交</el-button>
-        </div>
       </el-form>
+      <div style="text-align: center; margin-top: 20px; padding-bottom: 20px;">
+        <el-button type="primary" size="medium" @click="submitForm" :loading="submitLoading">保存配置</el-button>
+      </div>
     </el-card>
   </div>
 </template>
@@ -212,11 +212,5 @@ export default {
 .section-card {
   margin-bottom: 20px;
 }
-.footer {
-  width: 100%;
-  display: flex;
-  margin-top: 30px;
-  align-items: flex-end;
-  justify-content: flex-end;
-}
+
 </style>

+ 6 - 4
src/views/admin/product/index.vue

@@ -216,7 +216,7 @@
 </template>
 
 <script>
-import { listAllProducts, listPendingProducts, getProductInfo, auditProduct, getProductStatistics } from '@/api/admin/product'
+import { listAllProducts, listPendingProducts, getProductInfo, auditProduct, getProductStatistics, exportAllProducts } from '@/api/admin/product'
 
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
@@ -340,11 +340,13 @@ export default {
         this.showStatistics = true
       })
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportAllProducts(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 213 - 5
src/views/admin/proxyOperLog/index.vue

@@ -1,19 +1,227 @@
 <template>
   <div class="app-container">
+    <!-- ===== 搜索栏 ===== -->
+    <el-card shadow="never" class="mb16 filter-card">
+      <el-form :model="queryParams" ref="queryForm" :inline="true" size="small">
+        <el-form-item label="操作人员" prop="operName">
+          <el-input
+            v-model="queryParams.operName"
+            placeholder="请输入操作人员"
+            clearable
+            style="width:160px"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="操作状态" prop="status">
+          <el-select v-model="queryParams.status" placeholder="全部" clearable style="width:120px">
+            <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="操作时间">
+          <el-date-picker
+            v-model="dateRange"
+            type="daterange"
+            range-separator="-"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            value-format="yyyy-MM-dd"
+            style="width:220px"
+            @change="handleDateChange"
+          />
+        </el-form-item>
+        <el-form-item>
+          <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-button type="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport">导出</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- ===== 日志列表 ===== -->
     <el-card shadow="never">
-      <div slot="header">
-        <span>代理操作日志</span>
-      </div>
-      <el-empty description="功能开发中,敬请期待" />
+      <el-table
+        border
+        v-loading="loading"
+        :data="logList"
+        size="small"
+        style="width:100%"
+      >
+        <el-table-column label="日志ID" prop="operId" width="80" align="center" />
+        <el-table-column label="模块标题" prop="title" min-width="120" show-overflow-tooltip />
+        <el-table-column label="业务类型" align="center" width="90">
+          <template slot-scope="scope">
+            <el-tag :type="businessTypeMap[scope.row.businessType] && businessTypeMap[scope.row.businessType].type" size="mini">
+              {{ businessTypeMap[scope.row.businessType] ? businessTypeMap[scope.row.businessType].label : '其它' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作人" prop="operName" width="100" align="center" />
+        <el-table-column label="请求方式" prop="requestMethod" width="90" align="center">
+          <template slot-scope="scope">
+            <el-tag :type="methodTypeMap[scope.row.requestMethod] || 'info'" size="mini" plain>
+              {{ scope.row.requestMethod || '-' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="主机地址" prop="operIp" width="130" align="center" />
+        <el-table-column label="请求URL" prop="operUrl" min-width="160" show-overflow-tooltip />
+        <el-table-column label="操作状态" align="center" width="90">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.status === 0 || scope.row.status === '0'" type="success" size="mini">正常</el-tag>
+            <el-tag v-else type="danger" size="mini">异常</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作时间" prop="operTime" width="160" align="center" />
+        <el-table-column label="操作" align="center" width="70" fixed="right">
+          <template slot-scope="scope">
+            <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getList"
+      />
     </el-card>
+
+    <!-- ===== 详情弹窗 ===== -->
+    <el-dialog title="操作日志详情" :visible.sync="detailOpen" width="640px" append-to-body>
+      <el-descriptions :column="2" border size="small">
+        <el-descriptions-item label="日志ID">{{ detail.operId }}</el-descriptions-item>
+        <el-descriptions-item label="模块标题">{{ detail.title }}</el-descriptions-item>
+        <el-descriptions-item label="业务类型">
+          <el-tag
+            :type="businessTypeMap[detail.businessType] && businessTypeMap[detail.businessType].type"
+            size="mini"
+          >
+            {{ businessTypeMap[detail.businessType] ? businessTypeMap[detail.businessType].label : '其它' }}
+          </el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="操作人员">{{ detail.operName || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="请求方式">{{ detail.requestMethod || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="主机地址">{{ detail.operIp || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="请求URL" :span="2">{{ detail.operUrl || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="请求参数" :span="2">
+          <div class="param-box">{{ detail.operParam || '-' }}</div>
+        </el-descriptions-item>
+        <el-descriptions-item label="操作状态">
+          <el-tag v-if="detail.status === 0 || detail.status === '0'" type="success" size="mini">正常</el-tag>
+          <el-tag v-else type="danger" size="mini">异常</el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="操作时间">{{ detail.operTime }}</el-descriptions-item>
+        <el-descriptions-item label="租户名称" v-if="detail.companyName">{{ detail.companyName }}</el-descriptions-item>
+      </el-descriptions>
+      <div slot="footer">
+        <el-button @click="detailOpen = false">关 闭</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import { listProxyOperLog, exportProxyOperLog } from '@/api/admin/proxyOperLog'
+
 export default {
   name: 'AdminProxyOperLog',
   data() {
-    return {}
+    return {
+      loading: false,
+      exportLoading: false,
+      total: 0,
+      logList: [],
+      dateRange: [],
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        operName: null,
+        status: null,
+        beginTime: null,
+        endTime: null
+      },
+      statusOptions: [
+        { value: 0, label: '正常' },
+        { value: 1, label: '异常' }
+      ],
+      businessTypeMap: {
+        0: { label: '其它', type: 'info' },
+        1: { label: '新增', type: 'success' },
+        2: { label: '修改', type: 'warning' },
+        3: { label: '删除', type: 'danger' }
+      },
+      methodTypeMap: {
+        GET: '',
+        POST: 'success',
+        PUT: 'warning',
+        DELETE: 'danger'
+      },
+      detailOpen: false,
+      detail: {}
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.loading = true
+      listProxyOperLog(this.queryParams).then(response => {
+        this.logList = response.rows || []
+        this.total = response.total || 0
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.dateRange = []
+      this.resetForm('queryForm')
+      this.queryParams.beginTime = null
+      this.queryParams.endTime = null
+      this.handleQuery()
+    },
+    handleDateChange(val) {
+      if (val && val.length === 2) {
+        this.queryParams.beginTime = val[0]
+        this.queryParams.endTime = val[1]
+      } else {
+        this.queryParams.beginTime = null
+        this.queryParams.endTime = null
+      }
+    },
+    handleDetail(row) {
+      this.detail = Object.assign({}, row)
+      this.detailOpen = true
+    },
+    handleExport() {
+      this.exportLoading = true
+      exportProxyOperLog(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
+    }
   }
 }
 </script>
+
+<style scoped>
+.mb16 { margin-bottom: 16px; }
+.filter-card { padding-bottom: 0; }
+.param-box {
+  max-height: 120px;
+  overflow-y: auto;
+  word-break: break-all;
+  white-space: pre-wrap;
+  font-size: 12px;
+  font-family: monospace;
+  background: #f5f7fa;
+  padding: 4px 8px;
+  border-radius: 4px;
+}
+</style>

+ 6 - 5
src/views/admin/qwExternalContact/index.vue

@@ -124,7 +124,7 @@
 </template>
 
 <script>
-import { listAllExternalContact, getExternalContact } from '@/api/admin/qwExternalContact'
+import { listAllExternalContact, getExternalContact, exportAllExternalContact } from '@/api/admin/qwExternalContact'
 
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
@@ -191,12 +191,13 @@ export default {
         this.viewOpen = true
       })
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      // 导出逻辑
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportAllExternalContact(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 5 - 3
src/views/admin/rechargeRecord/index.vue

@@ -94,7 +94,7 @@
 </template>
 
 <script>
-import { listRechargeRecords, getRechargeRecord } from '@/api/admin/rechargeRecord'
+import { listRechargeRecords, getRechargeRecord, exportRechargeRecord } from '@/api/admin/rechargeRecord'
 
 export default {
   name: 'AdminRechargeRecord',
@@ -154,8 +154,10 @@ export default {
     },
     handleExport() {
       this.exportLoading = true
-      this.$message.info('导出功能开发中')
-      this.exportLoading = false
+      exportRechargeRecord(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 8 - 2
src/views/admin/sop/index.vue

@@ -40,7 +40,7 @@
 </template>
 
 <script>
-import { listSop, listSopTemp } from '@/api/admin/sop'
+import { listSop, listSopTemp, exportSop } from '@/api/admin/sop'
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
@@ -71,7 +71,13 @@ export default {
     handleTabClick() { this.queryParams.pageNum = 1; this.getList() },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
     resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
-    handleExport() { this.$message.info('导出功能开发中') }
+    handleExport() {
+      this.exportLoading = true
+      exportSop(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
+    }
   }
 }
 </script>

+ 8 - 2
src/views/admin/storeOrder/index.vue

@@ -37,7 +37,7 @@
 </template>
 
 <script>
-import { listStoreOrder } from '@/api/admin/storeOrder'
+import { listStoreOrder, exportStoreOrder } from '@/api/admin/storeOrder'
 import InlineTenantSelector from "@/components/InlineTenantSelector"
 
 export default {
@@ -66,7 +66,13 @@ export default {
     },
     handleQuery() { this.queryParams.pageNum = 1; this.getList() },
     resetQuery() { this.resetForm('queryForm'); this.queryParams.companyId = null; this.handleQuery() },
-    handleExport() { this.$message.info('导出功能开发中') }
+    handleExport() {
+      this.exportLoading = true
+      exportStoreOrder(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
+    }
   }
 }
 </script>

+ 118 - 4
src/views/admin/sysCompany/index.vue

@@ -112,6 +112,66 @@
       </el-descriptions>
     </el-dialog>
 
+    <!-- ===== 新增租户弹窗 ===== -->
+    <el-dialog title="新增租户" :visible.sync="addDialog.visible" width="680px" append-to-body destroy-on-close>
+      <el-form ref="addForm" :model="addDialog.form" :rules="addDialog.rules" label-width="100px" size="small">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="企业名称" prop="companyName">
+              <el-input v-model="addDialog.form.companyName" placeholder="请输入企业名称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="联系电话" prop="companyMobile">
+              <el-input v-model="addDialog.form.companyMobile" placeholder="请输入联系电话" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="联系人" prop="linkName">
+              <el-input v-model="addDialog.form.linkName" placeholder="请输入联系人" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="商务负责人" prop="manager">
+              <el-input v-model="addDialog.form.manager" placeholder="请输入商务负责人" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="管理员账号" prop="userName">
+              <el-input v-model="addDialog.form.userName" placeholder="请输入管理员账号" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="密码" prop="password">
+              <el-input v-model="addDialog.form.password" type="password" show-password placeholder="请输入密码" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="开始时间" prop="startTime">
+              <el-date-picker v-model="addDialog.form.startTime" type="date" value-format="yyyy-MM-dd" placeholder="选择开始时间" style="width:100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="到期时间" prop="limitTime">
+              <el-date-picker v-model="addDialog.form.limitTime" type="date" value-format="yyyy-MM-dd" placeholder="选择到期时间" style="width:100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="状态" prop="status">
+              <el-radio-group v-model="addDialog.form.status">
+                <el-radio :label="0">启用</el-radio>
+                <el-radio :label="1">禁用</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer">
+        <el-button @click="addDialog.visible = false">取 消</el-button>
+        <el-button type="primary" :loading="addDialog.submitting" @click="submitAdd">确 定</el-button>
+      </div>
+    </el-dialog>
+
     <!-- ===== 充值/扣款弹窗 ===== -->
     <el-dialog :title="rechargeTitle" :visible.sync="rechargeOpen" width="420px" append-to-body>
       <el-form ref="rechargeForm" :model="rechargeForm" :rules="rechargeRules" label-width="90px">
@@ -143,7 +203,7 @@
 </template>
 
 <script>
-import { listAllCompanies, getCompanyInfo, disableCompany, enableCompany, rechargeCompany } from '@/api/admin/sysCompany'
+import { listAllCompanies, getCompanyInfo, addCompany, disableCompany, enableCompany, rechargeCompany, exportCompany } from '@/api/admin/sysCompany'
 
 export default {
   name: 'SysCompanyAdmin',
@@ -167,6 +227,28 @@ export default {
       // 详情弹窗
       viewOpen: false,
       viewForm: {},
+      // 新增租户弹窗
+      addDialog: {
+        visible: false,
+        submitting: false,
+        form: {
+          companyName: '',
+          companyMobile: '',
+          linkName: '',
+          userName: '',
+          password: '',
+          manager: '',
+          startTime: null,
+          limitTime: null,
+          status: 0
+        },
+        rules: {
+          companyName: [{ required: true, message: '请输入企业名称', trigger: 'blur' }],
+          companyMobile: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
+          userName: [{ required: true, message: '请输入管理员账号', trigger: 'blur' }],
+          password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
+        }
+      },
       // 充值/扣款弹窗
       rechargeOpen: false,
       rechargeTitle: '',
@@ -199,7 +281,37 @@ export default {
     },
     /** 新增租户 */
     handleAdd() {
-      this.$message.info('新增租户功能开发中')
+      this.addDialog.form = {
+        companyName: '',
+        companyMobile: '',
+        linkName: '',
+        userName: '',
+        password: '',
+        manager: '',
+        startTime: null,
+        limitTime: null,
+        status: 0
+      }
+      this.addDialog.visible = true
+      this.$nextTick(() => {
+        if (this.$refs.addForm) this.$refs.addForm.clearValidate()
+      })
+    },
+    /** 提交新增租户 */
+    submitAdd() {
+      this.$refs['addForm'].validate(valid => {
+        if (!valid) return
+        this.addDialog.submitting = true
+        addCompany(this.addDialog.form).then(() => {
+          this.$message.success('新增成功')
+          this.addDialog.visible = false
+          this.getList()
+        }).catch(() => {
+          this.$message.error('新增失败,请重试')
+        }).finally(() => {
+          this.addDialog.submitting = false
+        })
+      })
     },
     /** 查看详情/编辑 */
     handleView(row) {
@@ -256,8 +368,10 @@ export default {
     },
     handleExport() {
       this.exportLoading = true
-      this.$message.info('导出功能开发中')
-      this.exportLoading = false
+      exportCompany(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 6 - 4
src/views/admin/sysUser/index.vue

@@ -174,7 +174,7 @@
 </template>
 
 <script>
-import { listAllUsers, getUserInfo, disableUser, enableUser, listChangeLogs } from '@/api/admin/sysUser'
+import { listAllUsers, getUserInfo, disableUser, enableUser, listChangeLogs, exportSysUser } from '@/api/admin/sysUser'
 
 export default {
   name: 'SysUserAdmin',
@@ -276,11 +276,13 @@ export default {
         this.showChangeLogs = true
       })
     },
-    /** 导出按操作 */
+    /** 导出按操作 */
     handleExport() {
       this.exportLoading = true
-      this.$message.success('导出功能开发中')
-      this.exportLoading = false
+      exportSysUser(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 5 - 3
src/views/admin/withdrawalManage/index.vue

@@ -116,7 +116,7 @@
 </template>
 
 <script>
-import { listWithdrawals, getWithdrawal, approveWithdrawal, rejectWithdrawal, confirmPaid } from '@/api/admin/withdrawalManage'
+import { listWithdrawals, getWithdrawal, approveWithdrawal, rejectWithdrawal, confirmPaid, exportWithdrawal } from '@/api/admin/withdrawalManage'
 
 export default {
   name: 'AdminWithdrawal',
@@ -214,8 +214,10 @@ export default {
     },
     handleExport() {
       this.exportLoading = true
-      this.$message.info('导出功能开发中')
-      this.exportLoading = false
+      exportWithdrawal(this.queryParams).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => { this.exportLoading = false })
     }
   }
 }

+ 4 - 10
src/views/admin/wxConfig/index.vue

@@ -94,10 +94,10 @@
           </el-form-item>
         </el-card>
 
-        <div class="footer">
-          <el-button type="primary" :loading="submitLoading" @click="submitForm">提 交</el-button>
-        </div>
       </el-form>
+      <div style="text-align: center; margin-top: 20px; padding-bottom: 20px;">
+        <el-button type="primary" size="medium" @click="submitForm" :loading="submitLoading">保存配置</el-button>
+      </div>
     </el-card>
   </div>
 </template>
@@ -182,11 +182,5 @@ export default {
   margin: 0 8px;
   color: #606266;
 }
-.footer {
-  width: 100%;
-  display: flex;
-  margin-top: 30px;
-  align-items: flex-end;
-  justify-content: flex-end;
-}
+
 </style>