Compare commits

..

No commits in common. "27c89ea96fe7621ea4e98b093ad5b83669814e26" and "6b4d979fd626d4d2943d78f855f7e0b5383e6476" have entirely different histories.

13 changed files with 117 additions and 283 deletions

1
components.d.ts vendored
View File

@ -79,6 +79,5 @@ declare module '@vue/runtime-core' {
TableEdit: typeof import('./src/components/table-edit.vue')['default'] TableEdit: typeof import('./src/components/table-edit.vue')['default']
TableSearch: typeof import('./src/components/table-search.vue')['default'] TableSearch: typeof import('./src/components/table-search.vue')['default']
Tabs: typeof import('./src/components/tabs.vue')['default'] Tabs: typeof import('./src/components/tabs.vue')['default']
UploadFile: typeof import('./src/components/upload-file.vue')['default']
} }
} }

View File

@ -19,6 +19,12 @@ export const menuData: Menus[] = [
index: '/system-user', index: '/system-user',
title: '用户管理', title: '用户管理',
}, },
{
id: '51',
pid: '1',
index: '/manage-session',
title: '会话管理',
},
{ {
id: '52', id: '52',
pid: '1', pid: '1',
@ -31,22 +37,6 @@ export const menuData: Menus[] = [
index: '/function', index: '/function',
title: '功能管理', title: '功能管理',
}, },
],
},
{
'id': '71',
'title': '用户功能管理',
'index': '71',
'icon': 'HomeFilled',
'children': [
{
id: '51',
pid: '1',
index: '/manage-session',
title: '会话管理',
},
{ {
id: '56', id: '56',
pid: '1', pid: '1',

View File

@ -59,9 +59,6 @@
<el-button type="danger" size="small" :icon="Link" @click="handlePush(row)" v-if="item.operate.push.link"> <el-button type="danger" size="small" :icon="Link" @click="handlePush(row)" v-if="item.operate.push.link">
{{item.operate.push.label}} {{item.operate.push.label}}
</el-button> </el-button>
<el-button type="danger" size="small" :icon="Link" @click="genOperate(row)" v-if="item.operate.gen.show">
{{item.operate.gen.label}}
</el-button>
</template> </template>
<span v-else-if="item.formatter"> <span v-else-if="item.formatter">
{{ item.formatter(row[item.prop]) }} {{ item.formatter(row[item.prop]) }}
@ -150,11 +147,7 @@ const props = defineProps({
changePage: { changePage: {
type: Function, type: Function,
default: () => { } default: () => { }
}, }
genOperate: {
type: Function,
default: () => { }
},
}) })
let { let {
@ -206,13 +199,6 @@ const handlePush = (row) => {
.catch(() => { }); .catch(() => { });
}; };
const handleGen = (row) => {
async () => {
console.log("gen row:", row);
props.genOperate(row);
}
};
const getIndex = (index: number) => { const getIndex = (index: number) => {
return index + 1 + (currentPage.value - 1) * pageSize.value return index + 1 + (currentPage.value - 1) * pageSize.value
} }

View File

@ -14,7 +14,7 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" :icon="Search" @click="search">搜索</el-button> <el-button type="primary" :icon="Search" @click="search">搜索</el-button>
<el-button :icon="Refresh" @click="refresh">重置</el-button> <el-button :icon="Refresh" @click="resetForm(searchRef)">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
@ -38,10 +38,6 @@ const props = defineProps({
search: { search: {
type: Function, type: Function,
default: () => { } default: () => { }
},
refresh: {
type: Function,
default: () => { }
} }
}); });

View File

@ -1,94 +0,0 @@
<template>
<div class="container">
<div class="content-title">支持拖拽</div>
<el-upload class="upload-demo" drag
action="https://pm.ljsea.top/file/upload" multiple
:data="uploadData"
:headers="headers"
:on-success="handleSuccess"
:on-error="handleError"
:before-upload="beforeUpload"
:on-change="handle">
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
将文件拖到此处
<em>点击上传</em>
</div>
<div class="el-upload__tip">只能上传 doc, docx, pdf, txt, png, jpg, jpeg 格式且不超过 5MB 的文件</div>
</el-upload>
<!-- <template #tip>
<div class="el-upload__tip">只能上传 doc, docx, pdf, txt, png, jpg, jpeg 格式且不超过 2MB 的文件</div>
</template> -->
</div>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus';
const handle = (rawFile: any) => {
console.log(rawFile);
};
const allowedTypes = ['doc', 'docx', 'pdf', 'txt', 'png', 'jpg', 'jpeg'];
interface UploadData {
upload_type: string;
auth_type: string;
md5: string;
type: string;
}
const uploadData: UploadData = {
upload_type: 'file',
auth_type: 'public',
md5: '',
type: 'file',
};
const headers = {
"token": localStorage.getItem('token') || '',
};
const handleSuccess = (response: any, file: any, fileList: any) => {
let res = response;
if (res.code !== 0){
ElMessage.error(res.error);
return;
}
console.log('上传成功', res);
ElMessage.success('上传成功');
};
const handleError = (error: any, file: any, fileList: any) => {
console.log('上传失败', error);
ElMessage.error('上传失败');
};
const beforeUpload = (file: any) => {
const fileExtension = file.name.split('.').pop().toLowerCase();
const isAllowedType = allowedTypes.includes(fileExtension);
if (!isAllowedType) {
ElMessage.error('不允许的文件类型,仅支持 doc, docx, pdf, txt, png, jpg, jpeg 格式');
return false;
}
//
const isLt2M = file.size / 1024 / 1024 < 5;
if (!isLt2M) {
ElMessage.error('上传文件大小不能超过 5MB');
}
return isLt2M;
};
</script>
<style scoped>
.content-title {
font-weight: 400;
line-height: 50px;
margin: 10px 0;
font-size: 22px;
color: #1f2f3d;
}
.upload-demo {
width: 30%;
}
</style>

View File

@ -1,61 +1,60 @@
import { defineStore } from "pinia"; import { defineStore } from 'pinia';
interface ObjectList { interface ObjectList {
[key: string]: string[]; [key: string]: string[];
} }
export const usePermissStore = defineStore("permiss", { export const usePermissStore = defineStore('permiss', {
state: () => { state: () => {
const keys = localStorage.getItem("ms_keys"); const keys = localStorage.getItem('ms_keys');
return { return {
key: keys ? JSON.parse(keys) : <string[]>[], key: keys ? JSON.parse(keys) : <string[]>[],
defaultList: <ObjectList>{ defaultList: <ObjectList>{
admin: [ admin: [
"0", '0',
"1", //系统管理 '1',
"11", //用户管理 '11', //用户管理
"12", '12',
"13", '13',
"2", '2',
"21", '21',
"22", '22',
"23", '23',
"24", '24',
"25", '25',
"26", '26',
"27", '27',
"28", '28',
"29", '29',
"291", '291',
"292", '292',
"3", '3',
"31", '31',
"32", '32',
"33", '33',
"34", '34',
"4", '4',
"41", '41',
"42", '42',
"5", '5',
"7", '7',
"6", '6',
"8", '8',
"61", '61',
"62", '62',
"63", '63',
"64", '64',
"65", '65',
"66", '66',
"9", '9',
"51", //会话管理 '51', //会话管理
"52", //模型管理 '52', //模型管理
"53", //通用人机对话 '53', //通用人机对话
"54", //功能管理 '54', //功能管理
"55", //提示词生成 '55', //提示词生成
"56", //文件管理 '56', //文件管理
"71", //用户功能管理
], ],
user: ["0", "71", "8", "7", "9", "61", "53", "51", "56"], user: ['0', '8', '7','9', '61','53'],
}, },
}; };
}, },

View File

@ -1,12 +1,6 @@
export interface File { export interface File {
ID: number; name: string;
CreatedAt: string; size: number;
UpdatedAt: string; type: string;
DeletedAt: string; lastModified: number;
UserFileName: string;
UploadType: string;
IsPrivate: boolean;
file_store_name: string;
} }
export const fileUrl ="https://pm.ljsea.top/file/";

View File

@ -13,6 +13,21 @@
<el-button @click="resetSystemTheme">重置主题</el-button> <el-button @click="resetSystemTheme">重置主题</el-button>
</div> </div>
</el-card> </el-card>
<el-card class="mgb20" shadow="hover">
<template #header>
<div class="content-title">Element-Plus主题</div>
</template>
<div class="theme-list mgb20">
<div class="theme-item" v-for="theme in themes">
<el-button :type="theme.name">{{ theme.name }}</el-button>
<div class="theme-color">{{ theme.color }}</div>
<el-color-picker v-model="color[theme.name]" @change="changeColor(theme.name)" />
</div>
</div>
<div class="flex-center">
<el-button @click="resetTheme">重置主题</el-button>
</div>
</el-card>
<el-row :gutter="50"> <el-row :gutter="50">
<el-col :span="12"> <el-col :span="12">

View File

@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" :refresh="getData" /> <TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
<div class="container"> <div class="container">
<TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView" <TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView"
:delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit" :refresh="getData"> :delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit">
<template #toolbarBtn> <template #toolbarBtn>
<el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">新增</el-button> <el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">新增</el-button>
</template> </template>
@ -73,7 +73,7 @@ let columns = ref([
{ prop: 'Function', label: '功能' }, { prop: 'Function', label: '功能' },
{ prop: 'Info', label: '描述信息' }, { prop: 'Info', label: '描述信息' },
{ prop: 'CreatedAt', label: '创建时间',type: 'date' }, { prop: 'CreatedAt', label: '创建时间',type: 'date' },
{ prop: 'operator', label: '操作', width: 250 , operate: { view: true, edit: true, delete: true,push: {link: false,label:"继续该会话"},gen: {show: false,label:"下载文件"} }}, { prop: 'operator', label: '操作', width: 250 , operate: { view: true, edit: true, delete: true,push: {link: false,label:"继续该会话"} }},
]) ])
const page = reactive({ const page = reactive({
index: 1, index: 1,

View File

@ -1,11 +1,11 @@
<template> <template>
<div> <div>
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" :refresh="getData" /> <TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
<div class="container"> <div class="container">
<TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView" <TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView"
:delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit" :genOperate="handleGenOperate" :refresh="getData"> :delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit">
<template #toolbarBtn> <template #toolbarBtn>
<el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">上传文件</el-button> <el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">新增</el-button>
</template> </template>
</TableCustom> </TableCustom>
@ -14,9 +14,9 @@
:close-on-click-modal="false" @close="closeDialog"> :close-on-click-modal="false" @close="closeDialog">
<TableEdit :form-data="rowData" :options="options_edit" :edit="isEdit" :update="updateData" /> <TableEdit :form-data="rowData" :options="options_edit" :edit="isEdit" :update="updateData" />
</el-dialog> </el-dialog>
<el-dialog :title="isAdd ? '上传' : '上传'" v-model="visible_add" width="700px" destroy-on-close <el-dialog :title="isAdd ? '新增' : '新增'" v-model="visible_add" width="700px" destroy-on-close
:close-on-click-modal="false" @close="closeDialog"> :close-on-click-modal="false" @close="closeDialog">
<UploadFile></UploadFile> <TableEdit :form-data="rowData" :options="options" :edit="isAdd" :update="addData" />
</el-dialog> </el-dialog>
<el-dialog title="查看详情" v-model="visible1" width="700px" destroy-on-close> <el-dialog title="查看详情" v-model="visible1" width="700px" destroy-on-close>
<TableDetail :data="viewData"></TableDetail> <TableDetail :data="viewData"></TableDetail>
@ -26,17 +26,15 @@
<script setup lang="ts" name="system-user"> <script setup lang="ts" name="system-user">
import { ref, reactive } from 'vue'; import { ref, reactive } from 'vue';
import { ElMessage,ElMessageBox } from 'element-plus'; import { ElMessage } from 'element-plus';
import { CirclePlusFilled } from '@element-plus/icons-vue'; import { CirclePlusFilled } from '@element-plus/icons-vue';
import { Session } from '@/types/session'; import { Session } from '@/types/session';
import {FindUserFileService} from "@/api/file"; import {FindUserFileService} from "@/api/file";
import {UpdateUserFileService} from "@/api/file"; import {UpdateUserFileService} from "@/api/file";
import {DelUserFileService} from "@/api/file"; import {DelUserFileService} from "@/api/file";
import { File,fileUrl } from '@/types/file';
import TableCustom from '@/components/table-custom.vue'; import TableCustom from '@/components/table-custom.vue';
import TableDetail from '@/components/table-detail.vue'; import TableDetail from '@/components/table-detail.vue';
import TableSearch from '@/components/table-search.vue'; import TableSearch from '@/components/table-search.vue';
import UploadFile from '@/components/upload-file.vue';
import { FormOption, FormOptionList } from '@/types/form-option'; import { FormOption, FormOptionList } from '@/types/form-option';
const userRole = localStorage.getItem('role') == 'admin'; const userRole = localStorage.getItem('role') == 'admin';
@ -45,14 +43,14 @@ const page = reactive({
size: 10, size: 10,
total: 122, total: 122,
}) })
const tableData = ref<File[]>([]); const tableData = ref<[]>([]);
// //
const query = reactive({ const query = reactive({
name: '', name: '',
}); });
const searchOpt = ref<FormOptionList[]>([ const searchOpt = ref<FormOptionList[]>([
{ type: 'input', label: '文件名', prop: 'name' } { type: 'input', label: '会话ID', prop: 'name' }
]) ])
const handleSearch = async () => { const handleSearch = async () => {
// if (isFinite(query.name) == false){ // if (isFinite(query.name) == false){
@ -61,12 +59,8 @@ const handleSearch = async () => {
// } // }
let req={ let req={
token: localStorage.getItem('token'), token: localStorage.getItem('token'),
type: "search", type: "ID",
file_name: query.name, id: parseInt(query.name)
}
if (!req.file_name) {
ElMessage.error("请求参数不能为空");
return;
} }
let result = await FindUserFileService(req); let result = await FindUserFileService(req);
tableData.value = result.data; tableData.value = result.data;
@ -81,8 +75,7 @@ let columns = ref([
{ prop: "UploadType", label: "上传类型",width: 100}, { prop: "UploadType", label: "上传类型",width: 100},
{ prop: 'CreatedAt', label: '创建时间',type: 'date',width: 200 }, { prop: 'CreatedAt', label: '创建时间',type: 'date',width: 200 },
{ prop: 'UpdatedAt', label: '更新时间',type: 'date',width: 200 }, { prop: 'UpdatedAt', label: '更新时间',type: 'date',width: 200 },
{ prop: 'operator', label: '操作' , operate: { view: false, edit: true, delete: true,push: {link: false,label:"继续该会话"} ,gen: {show: true,label:"下载文件"}}, { prop: 'operator', label: '操作' , operate: { view: false, edit: true, delete: true,push: {link: false,label:"继续该会话"} }},
align: 'center', fixed: 'right' },
]) ])
const getData = async () => { const getData = async () => {
@ -136,15 +129,9 @@ const updateData = async (data) => {
try{ try{
let req={ let req={
token:localStorage.getItem("token"), token:localStorage.getItem("token"),
file_id: data.ID, id: data.ID,
file_name: data.UserFileName, name: data.Name
}; };
console.log("update row data:", req);
//
if (!req.file_name) {
ElMessage.error("请求参数错误");
return;
}
result = await UpdateUserFileService(req) result = await UpdateUserFileService(req)
if (result["code"] === 0) { if (result["code"] === 0) {
ElMessage.success("更新成功"); ElMessage.success("更新成功");
@ -156,7 +143,7 @@ const updateData = async (data) => {
console.log(e); console.log(e);
} }
closeDialog(); closeDialog();
getData(); handleSearch();
}; };
const addData = async (data) => { const addData = async (data) => {
@ -166,7 +153,7 @@ const addData = async (data) => {
token:localStorage.getItem("token"), token:localStorage.getItem("token"),
name: data.Name name: data.Name
}; };
//result = await AddSessionService(req) result = await AddSessionService(req)
if (result["code"] === 0) { if (result["code"] === 0) {
ElMessage.success("新增成功"); ElMessage.success("新增成功");
} else { } else {
@ -193,7 +180,7 @@ const viewData = ref({
row: {}, row: {},
list: [] list: []
}); });
const handleView =async (row: File) => { const handleView =async (row: Session) => {
viewData.value.row = row; viewData.value.row = row;
viewData.value.list = [ viewData.value.list = [
@ -201,38 +188,8 @@ const handleView =async (row: File) => {
visible1.value = true; visible1.value = true;
}; };
const handleGenOperate = async (row: File) => {
console.log("gen row:", row);
//
ElMessageBox.confirm('确定要下载吗?', '提示', {
type: 'warning'
})
.then(async () => {
//
downloadFile(row);
})
.catch(() => { });
}
const downloadFile = async (row: File) => {
const fileUrl_ = fileUrl+row.file_store_name;
const response = await fetch(fileUrl_)
const blob = await response.blob()
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = row.UserFileName //
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
//
window.URL.revokeObjectURL(url)
ElMessage.success('文件下载成功')
};
// //
const handleDelete = async (row: File) => { const handleDelete = async (row: Session) => {
let req={ let req={
token: localStorage.getItem('token'), token: localStorage.getItem('token'),
id: row.ID, id: row.ID,

View File

@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" :refresh="getData" /> <TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
<div class="container"> <div class="container">
<TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView" <TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView"
:delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit" :genOperate="handleGenOperate" :refresh="getData"> :delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit">
<template #toolbarBtn> <template #toolbarBtn>
<el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">新增</el-button> <el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">新增</el-button>
</template> </template>
@ -74,7 +74,7 @@ let columns = ref([
{ prop: 'Parameter', label: '参数', width: 250 }, { prop: 'Parameter', label: '参数', width: 250 },
{prop: 'Url', label: 'URl'}, {prop: 'Url', label: 'URl'},
{ prop: 'CreatedAt', label: '创建时间',type: 'date' }, { prop: 'CreatedAt', label: '创建时间',type: 'date' },
{ prop: 'operator', label: '操作', width: 250 , operate: { view: true, edit: true, delete: true,push: {link: false,label:"继续该会话"},gen: {show: false,label:"下载文件"} }}, { prop: 'operator', label: '操作', width: 250 , operate: { view: true, edit: true, delete: true,push: {link: false,label:"继续该会话"} }},
]) ])
const page = reactive({ const page = reactive({
index: 1, index: 1,
@ -190,10 +190,6 @@ const closeDialog = () => {
isEdit.value = false; isEdit.value = false;
}; };
const handleGenOperate = async (row: File) => {
console.log("gen row:", row);
}
// //
const visible1 = ref(false); const visible1 = ref(false);
const viewData = ref({ const viewData = ref({

View File

@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" :refresh="getData" /> <TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
<div class="container"> <div class="container">
<TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView" <TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView"
:delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit" :genOperate="handleGenOperate" :refresh="getData"> :delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit">
<template #toolbarBtn> <template #toolbarBtn>
<el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">新增</el-button> <el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true" v-if="userRole">新增</el-button>
</template> </template>
@ -80,7 +80,7 @@ let columns = ref([
{ prop: "Context", label: "会话背景参数" ,width: 100}, { prop: "Context", label: "会话背景参数" ,width: 100},
{ prop: 'CreatedAt', label: '创建时间',type: 'date',width: 150 }, { prop: 'CreatedAt', label: '创建时间',type: 'date',width: 150 },
{ prop: 'UpdatedAt', label: '更新时间',type: 'date',width: 150 }, { prop: 'UpdatedAt', label: '更新时间',type: 'date',width: 150 },
{ prop: 'operator', label: '操作' , operate: { view: false, edit: true, delete: true,push: {link: true,label:"继续该会话"},gen: {show: false,label:"下载文件"}}}, { prop: 'operator', label: '操作' , operate: { view: false, edit: true, delete: true,push: {link: true,label:"继续该会话"} }},
]) ])
const getData = async () => { const getData = async () => {
@ -99,10 +99,6 @@ const changePage = (val: number) => {
getData(); getData();
}; };
const handleGenOperate = async (row: File) => {
console.log("gen row:", row);
}
// //
let options = ref<FormOption>({ let options = ref<FormOption>({
labelWidth: '100px', labelWidth: '100px',

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<TableSearch :query="query" :options="searchOpt" :search="handleSearch" :refresh="getData" /> <TableSearch :query="query" :options="searchOpt" :search="handleSearch" />
<div class="container"> <div class="container">
<TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView" <TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView"
:delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit"> :delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit">
@ -73,7 +73,7 @@ let columns = ref([
{ prop: 'Role', label: '角色' }, { prop: 'Role', label: '角色' },
{ prop: 'CreatedAt', label: '创建时间',type: 'date' }, { prop: 'CreatedAt', label: '创建时间',type: 'date' },
{ prop: 'Email', label: '邮箱' }, { prop: 'Email', label: '邮箱' },
{ prop: 'operator', label: '操作', width: 250 ,operate: { view: true, edit: true, delete: true ,push: {link: false,label:"继续该会话"},gen: {show: false,label:"下载文件"}}}, { prop: 'operator', label: '操作', width: 250 ,operate: { view: true, edit: true, delete: true ,push: {link: false,label:"继续该会话"}}},
]) ])
const page = reactive({ const page = reactive({
index: 1, index: 1,