Selaa lähdekoodia

feat: 声音与推荐列表

sheldon 1 kuukausi sitten
vanhempi
commit
9325fd582c

+ 11 - 2
src/api/modules/anycallService.ts

@@ -1,8 +1,14 @@
 // anycall
 import { request } from '@/api'
 import type { TAgent } from '@/types/role'
+import type { TVoice } from '@/types/voice'
 
-export function anycallPage(params: any){
+export function anycallPage(params: {
+  page: number,
+  size: number,
+  name?: string,
+  topFlag?: boolean
+}){
   return request<{
     total: number,
     content: TAgent[]
@@ -15,7 +21,10 @@ export function updateTopFlag(params: any){
   return request(`/anycall/updateTopFlag`, params)
 }
 export function voiceList(params: any){
-  return request(`/anycall/selectVoiceList`, params)
+  return request<{
+    total: number,
+    content: TVoice[]
+  }>(`/anycall/selectVoiceList`, params)
 }
 export function addRole(params: any){
   return request(`/anycall/create`, params)

+ 2 - 2
src/router/modules/recomendation.ts

@@ -18,9 +18,9 @@ const routes: RouteRecordRaw = {
     {
       path: '',
       name: 'recomendationIndex',
-      component: () => import('@/views/role-management/index.vue'),
+      component: () => import('@/views/recomendation-management/index.vue'),
       meta: {
-        title: 'Role Management',
+        title: 'Recomendation Management',
         menu: false,
         breadcrumb: false,
         activeMenu: '/recomendation',

+ 2 - 2
src/router/modules/voice.ts

@@ -17,9 +17,9 @@ const routes: RouteRecordRaw = {
     {
       path: '',
       name: 'voiceManagementIndex',
-      component: () => import('@/views/role-management/index.vue'),
+      component: () => import('@/views/voice-management/index.vue'),
       meta: {
-        title: 'Role Management',
+        title: 'Voice Management',
         menu: false,
         breadcrumb: false,
         activeMenu: '/voiceManagement',

+ 174 - 0
src/views/recomendation-management/index.vue

@@ -0,0 +1,174 @@
+<script setup lang="ts">
+
+defineOptions({
+  name: 'Role Management',
+})
+import { Plus } from '@element-plus/icons-vue'
+import { ElButton, ElDialog, ElEmpty, ElInput, ElOption, ElPagination, ElSelect, ElTable, ElTableColumn, ElTag } from 'element-plus'
+// import SearchForm from './components/SearchForm.vue'
+
+import type { TAgent } from '@/types/role'
+import { anycallPage } from '@/api/modules/anycallService'
+import { formatDateGeneral } from '@/utils'
+
+const tableRef = ref()
+const loading = ref(false)
+const router = useRouter()
+const route = useRoute()
+
+// 搜索参数
+const searchParams = ref({
+  name: '',
+})
+const dataList = ref<TAgent[]>([]);
+
+// 从URL获取初始分页参数
+const getInitialPagination = () => {
+  const page = Number(route.query.page) || 1
+  const size = Number(route.query.size) || 20
+  return {
+    total: 0,
+    page: page > 0 ? page : 1,
+    size: [10, 20, 50, 100].includes(size) ? size : 20,
+  }
+}
+
+// 分页信息
+const pagination = ref(getInitialPagination())
+
+// 更新URL中的分页参数
+const updateUrlParams = (page: number, size: number) => {
+  const query = {
+    ...route.query,
+    page: page.toString(),
+    size: size.toString(),
+  }
+
+  // 使用replace模式更新URL,避免产生历史记录
+  router.replace({
+    path: route.path,
+    query
+  })
+}
+
+
+const  handleRecommend = (id: string) => {
+
+}
+
+async function fetchData() {
+  loading.value = true
+  const res = await anycallPage({
+    name: searchParams.value.name,
+    page: pagination.value.page,
+    size: pagination.value.size,
+    topFlag: true,
+  })
+  if(res.code === 0){
+    dataList.value = res.data.content
+    pagination.value.total = res.data.total
+  }
+  loading.value = false
+}
+function handlePageChange(page: number) {
+  pagination.value.page = page
+  updateUrlParams(page, pagination.value.size)
+  fetchData()
+}
+
+function handleSizeChange(size: number) {
+  pagination.value.size = size
+  pagination.value.page = 1
+  updateUrlParams(1, size)
+  fetchData()
+}
+
+function handleSearch () {
+  pagination.value.page = 1 // 搜索时重置到第一页
+  updateUrlParams(1, pagination.value.size)
+  fetchData()
+}
+
+function handleReset () {
+  searchParams.value = {
+    name: '',
+  }
+  pagination.value.page = 1 // 重置时重置到第一页
+  updateUrlParams(1, pagination.value.size)
+  fetchData()
+}
+
+
+// 监听URL参数变化,用于处理浏览器后退/前进
+watch(
+  () => route.query,
+  (newQuery) => {
+    const newPage = Number(newQuery.page) || 1
+    const newSize = Number(newQuery.size) || 20
+
+    // 只有当参数真正发生变化时才更新
+    if (newPage !== pagination.value.page || newSize !== pagination.value.size) {
+      pagination.value.page = newPage > 0 ? newPage : 1
+      pagination.value.size = [10, 20, 50, 100].includes(newSize) ? newSize : 20
+      fetchData()
+    }
+  },
+  { deep: true }
+)
+
+onMounted(async () => {
+  await fetchData()
+})
+
+
+</script>
+
+<template>
+  <div class="absolute-container">
+    <FaPageHeader title="Recommendation Management" />
+    <FaPageMain class="flex-1 overflow-auto" main-class="flex-1 flex flex-col overflow-auto">
+      <ElTable
+        ref="tableRef" :data="dataList" stripe highlight-current-row border height="100%"
+      >
+        <ElTableColumn label="ID" prop="id" min-width="240" />
+        <ElTableColumn label="Agent ID" prop="agentId" min-width="220" />
+        <ElTableColumn label="Role Name" prop="name" min-width="220" />
+        <ElTableColumn label="Avatar" prop="photo">
+          <template #default="{row}">
+            <ElImage :src="row.photo" fit="cover" class="w-12 h-12 rounded" />
+          </template>
+        </ElTableColumn>
+        <ElTableColumn label="callings" prop="callings" />
+        <ElTableColumn label="Voice Name" prop="voiceName" min-width="240" />
+        <ElTableColumn label="prompt" prop="prompt" min-width="340">
+          <template #default="{row}">
+            <ElTag type="info" v-for="(tag, index) in row.prompt.split(/\,|\,/)" :key="index" class="mb-1 mr-1">
+              <div :title="tag">{{ tag }}</div>
+            </ElTag>
+          </template>
+        </ElTableColumn>
+        <ElTableColumn label="Language" prop="language" width="180" />
+      </ElTable>
+      <div class="p-4">
+        <ElPagination
+          v-model:current-page="pagination.page"
+          v-model:page-size="pagination.size"
+          :total="pagination.total"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handlePageChange"
+        />
+      </div>
+    </FaPageMain>
+  </div>
+</template>
+<style scoped>
+.absolute-container {
+  position: absolute;
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 11 - 2
src/views/role-management/index.vue

@@ -123,9 +123,9 @@ onMounted(async () => {
 </script>
 
 <template>
-  <div>
+  <div class="absolute-container">
     <FaPageHeader title="Role Management" />
-    <FaPageMain>
+    <FaPageMain class="flex-1 overflow-auto" main-class="flex-1 flex flex-col overflow-auto">
       <ElTable
         ref="tableRef" :data="dataList" stripe highlight-current-row border height="100%"
       >
@@ -167,3 +167,12 @@ onMounted(async () => {
     </FaPageMain>
   </div>
 </template>
+<style scoped>
+.absolute-container {
+  position: absolute;
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 175 - 0
src/views/voice-management/index.vue

@@ -0,0 +1,175 @@
+<script setup lang="ts">
+
+defineOptions({
+  name: 'Voice Management',
+})
+import { Plus } from '@element-plus/icons-vue'
+import { ElButton, ElDialog, ElEmpty, ElInput, ElOption, ElPagination, ElSelect, ElTable, ElTableColumn, ElTag } from 'element-plus'
+// import SearchForm from './components/SearchForm.vue'
+
+import type { TVoice } from '@/types/voice'
+import { voiceList } from '@/api/modules/anycallService'
+import { formatDateGeneral } from '@/utils'
+
+const tableRef = ref()
+const loading = ref(false)
+const router = useRouter()
+const route = useRoute()
+
+// 搜索参数
+const searchParams = ref({
+  name: '',
+})
+const dataList = ref<TVoice[]>([]);
+
+// 从URL获取初始分页参数
+const getInitialPagination = () => {
+  const page = Number(route.query.page) || 1
+  const size = Number(route.query.size) || 20
+  return {
+    total: 0,
+    page: page > 0 ? page : 1,
+    size: [10, 20, 50, 100].includes(size) ? size : 20,
+  }
+}
+
+// 分页信息
+const pagination = ref(getInitialPagination())
+
+// 更新URL中的分页参数
+const updateUrlParams = (page: number, size: number) => {
+  const query = {
+    ...route.query,
+    page: page.toString(),
+    size: size.toString(),
+  }
+
+  // 使用replace模式更新URL,避免产生历史记录
+  router.replace({
+    path: route.path,
+    query
+  })
+}
+
+
+const  handleRecommend = (id: string) => {
+
+}
+
+async function fetchData() {
+  loading.value = true
+  const res = await voiceList({
+    gender: 1,
+    system: true,
+    name: searchParams.value.name,
+    page: pagination.value.page,
+    size: pagination.value.size,
+  })
+  console.log('res', res)
+  if(res.code === 0){
+    dataList.value = res.data.content
+    pagination.value.total = res.data.total
+  }
+  loading.value = false
+}
+function handlePageChange(page: number) {
+  pagination.value.page = page
+  updateUrlParams(page, pagination.value.size)
+  fetchData()
+}
+
+function handleSizeChange(size: number) {
+  pagination.value.size = size
+  pagination.value.page = 1
+  updateUrlParams(1, size)
+  fetchData()
+}
+
+function handleSearch () {
+  pagination.value.page = 1 // 搜索时重置到第一页
+  updateUrlParams(1, pagination.value.size)
+  fetchData()
+}
+
+function handleReset () {
+  searchParams.value = {
+    name: '',
+  }
+  pagination.value.page = 1 // 重置时重置到第一页
+  updateUrlParams(1, pagination.value.size)
+  fetchData()
+}
+
+
+// 监听URL参数变化,用于处理浏览器后退/前进
+watch(
+  () => route.query,
+  (newQuery) => {
+    const newPage = Number(newQuery.page) || 1
+    const newSize = Number(newQuery.size) || 20
+
+    // 只有当参数真正发生变化时才更新
+    if (newPage !== pagination.value.page || newSize !== pagination.value.size) {
+      pagination.value.page = newPage > 0 ? newPage : 1
+      pagination.value.size = [10, 20, 50, 100].includes(newSize) ? newSize : 20
+      fetchData()
+    }
+  },
+  { deep: true }
+)
+
+onMounted(async () => {
+  await fetchData()
+})
+
+
+</script>
+
+<template>
+  <div class="absolute-container">
+    <FaPageHeader title="Voice Management" />
+    <FaPageMain class="flex-1 overflow-auto" main-class="flex-1 flex flex-col overflow-auto">
+      <ElTable
+        ref="tableRef" :data="dataList" stripe highlight-current-row border height="100%"
+      >
+        <ElTableColumn label="ID" prop="id" width="280" />
+        <ElTableColumn label="Name" prop="name" min-width="200"/>
+        <ElTableColumn label="Gender" prop="gender">
+          <template #default="{row}">
+            {{ row.gender === 1 ? '男':"女" }}
+          </template>
+        </ElTableColumn>
+        <ElTableColumn label="service" prop="service" width="120" />
+        <ElTableColumn label="fromTrained" prop="fromTrained" width="120" />
+        <ElTableColumn label="customEdit" prop="customEdit" width="120"/>
+        <ElTableColumn label="spaceId" prop="spaceId" width="120" />
+        <ElTableColumn label="status" prop="status" width="120" />
+        <ElTableColumn label="create time" prop="ctime" width="280">
+          <template #default="{row}">
+            {{ formatDateGeneral(row.ctime) }}
+          </template>
+        </ElTableColumn>
+      </ElTable>
+      <div class="p-4">
+        <ElPagination
+          v-model:current-page="pagination.page"
+          v-model:page-size="pagination.size"
+          :total="pagination.total"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handlePageChange"
+        />
+      </div>
+    </FaPageMain>
+  </div>
+</template>
+<style scoped>
+.absolute-container {
+  position: absolute;
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  height: 100%;
+}
+</style>