| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- <script setup lang="ts">
- defineOptions({
- name: 'Role Management',
- })
- import { Plus, Upload, ArrowDown } from '@element-plus/icons-vue'
- import { ElButton, ElDialog, ElEmpty, ElInput, ElMessage, ElOption, ElPagination, ElSelect, ElTable, ElTableColumn, ElTag } from 'element-plus'
- import type { UploadFile, UploadFiles } from 'element-plus'
- import FileImportUploader from '@/components/Uploader/FileImportUploader.vue'
- import EditForm from './components/EditForm.vue'
- import EditLLMForm from './components/EditLLMForm.vue'
- import EditCallingsForm from './components/EditCallingsForm.vue'
- import SearchForm from './components/SearchForm.vue'
- import type { TAgent } from '@/types/role'
- import { anycallPage, updateTopFlag, type TRole } from '@/api/modules/anycallService'
- import { formatDateGeneral } from '@/utils'
- import { toast } from 'vue-sonner'
- const tableRef = ref()
- const loading = ref(false)
- // 控制 EditForm 显示状态
- const editFormVisible = ref(false)
- const editMode = ref<'create' | 'edit'>('create')
- const currentData = ref<any>(null)
- const currentCloneId = ref<string>()
- const editLLMFormVisible = ref(false)
- const editCallingsFormVisible = ref(false)
- const importedResultDialogVisible = ref(false)
- const importedFile = ref<UploadFile | null>(null)
- const importedResult = ref<{name: string, msg: string}[]>([
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- // {name: 'test1.csv', msg: '成功'},
- ])
- // 搜索参数
- const searchParams = ref({
- // name: '',
- nameOrTags: '',
- })
- const dataList = ref<TAgent[]>([]);
- // 分页信息
- const pagination = ref({
- total: 0,
- size: 20,
- page:1,
- })
- async function fetchData() {
- loading.value = true
- const res = await anycallPage({
- nameOrTags: searchParams.value.nameOrTags,
- page: pagination.value.page,
- size: pagination.value.size,
- })
- 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
- fetchData()
- }
- function handleSizeChange(size: number) {
- pagination.value.size = size
- pagination.value.page = 1
- fetchData()
- }
- function handleRefresh () {
- pagination.value.page = 1 // 搜索时重置到第一页
- fetchData()
- }
- const handleFormCancel = () => {
- editFormVisible.value = false
- };
- const handleRecommend = async (id: string, topFlag: boolean) => {
- const {code} = await updateTopFlag({
- id,
- topFlag: topFlag,
- })
- if(code === 0){
- ElMessage.success('操作成功')
- await fetchData()
- }
- }
- function handleUploadSuccess(res:any, file: any) {
- console.log(res, file)
- if(res.code === 0){
- importedResult.value = res.data as {name: string, msg: string}[]
- importedResultDialogVisible.value = true
- return
- }
- toast.error('Error', {
- description: res.msg || '导入失败',
- })
- }
- const handleCreate = () => {
- editMode.value = 'create'
- currentData.value = null
- editFormVisible.value = true
- }
- const handleEdit = (data: TAgent) => {
- editMode.value = 'edit'
- const gender = data.gender !== 'null' ? Number(data.gender) : 1;
- currentData.value = {...data, avatar: [data.photo], gender}
- console.log(currentData.value,33344)
- editFormVisible.value = true
- }
- const handleEditLLM = (data: TAgent) => {
- console.log(data)
- currentData.value = data
- currentCloneId.value = data.id
- editLLMFormVisible.value = true
- }
- const handleEditCallings = (data: TAgent) => {
- console.log(data)
- currentData.value = data
- currentCloneId.value = data.id
- editCallingsFormVisible.value = true
- }
- const handleSearch = () => {
- pagination.value.page = 1
- fetchData()
- }
- const handleReset = () => {
- pagination.value.page = 1
- pagination.value.size = 10
- searchParams.value.name = ''
- fetchData()
- }
- onMounted(async () => {
- await fetchData()
- })
- </script>
- <template>
- <div class="absolute-container">
- <div class="p-4 pb-0 bg-white dark-bg-black/50">
- <SearchForm v-model="searchParams" :loading="loading" @search="handleSearch" @reset="handleReset" />
- </div>
- <FaPageMain class="flex-1 overflow-auto" main-class="flex-1 flex flex-col overflow-auto">
- <div class="pb-4">
- <ElSpace>
- <FileImportUploader @success="handleUploadSuccess" ></FileImportUploader>
- <ElButton type="primary" :icon="Plus" @click="handleCreate">Create Role</ElButton>
- {{ importedFile?.name }}
- </ElSpace>
- </div>
- <ElTable
- v-loading="loading"
- ref="tableRef" :data="dataList" stripe highlight-current-row border height="100%"
- >
- <ElTableColumn label="id" prop="id" min-width="240" />
- <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="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="tags" prop="tags" min-width="340">
- <template #default="{row}">
- <ElTag type="info" v-for="(tag, index) in row.tags ?? []" :key="index" class="mb-1 mr-1">
- <div :title="tag">{{ tag }}</div>
- </ElTag>
- </template>
- </ElTableColumn>
- <ElTableColumn label="推荐" prop="topFlag" min-width="120">
- <template #default="{row}">
- <ElSwitch v-model="row.topFlag" @change="()=> handleRecommend(row.id, row.topFlag)" />
- </template>
- </ElTableColumn>
- <ElTableColumn label="Language" prop="language" min-width="180" />
- <ElTableColumn label="voiceName" prop="voiceName" min-width="240" />
- <ElTableColumn fixed="right" label="操作" min-width="140">
- <template #default="{row}">
- <el-dropdown>
- <span class="el-dropdown-link">
- Actions
- <el-icon class="el-icon--right">
- <ArrowDown />
- </el-icon>
- </span>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item><ElButton link type="primary" size="small" @click="handleEdit(row)">编辑</ElButton></el-dropdown-item>
- <el-dropdown-item><ElButton link type="primary" size="small" @click="handleEditLLM(row)">绑定大模型</ElButton></el-dropdown-item>
- <el-dropdown-item><ElButton link type="primary" size="small" @click="handleEditCallings(row)">修改 callings</ElButton></el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- <!-- <ElPopconfirm title="确定推荐吗?" @confirm="handleRecommend(row.id, row.topFlag)">
- <template #reference>
- <ElButton link type="primary" size="small">
- 推荐
- </ElButton>
- </template>
- </ElPopconfirm> -->
- </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>
- <EditForm v-model:visible="editFormVisible" :model-value="currentData" :mode="editMode" @refresh="handleRefresh"
- @cancel="handleFormCancel" />
- <EditLLMForm v-model:visible="editLLMFormVisible" :cloneId="currentCloneId ?? ''" @refresh="handleRefresh"></EditLLMForm>
- <EditCallingsForm v-model:visible="editCallingsFormVisible" :model-value="currentData" :cloneId="currentCloneId ?? ''" @refresh="handleRefresh"></EditCallingsForm>
- <ElDialog title="导入结果" v-model="importedResultDialogVisible" align-center
- width="800" :z-index="2000" :close-on-click-modal="false">
- <div class="max-h-200 overflow-y-auto leading-6">
- <el-table :data="importedResult" stripe style="width: 100%;" height="450">
- <el-table-column prop="name" label="name" width="180" />
- <el-table-column prop="msg" label="message" min-width="180" />
- </el-table>
- </div>
- </ElDialog>
- </div>
- </template>
- <style scoped>
- .absolute-container {
- position: absolute;
- display: flex;
- flex-direction: column;
- width: 100%;
- height: 100%;
- }
- </style>
|