Преглед изворни кода

提示词分类管理页面修改 接口

liyangwenqi пре 5 месеци
родитељ
комит
f1b24eebed

+ 24 - 3
src/api/promptwordManagement/promptpage.ts

@@ -5,12 +5,33 @@ import {AxiosPromise} from "axios";
 /**
  * 根据id查询prompt详细
  */
-var myHeaders = new Headers();
-myHeaders.append("Authorization", "");
+
 export const getPromptById=(id:number):AxiosPromise<PromptModel>=>{
 return request({
     url: '/ai/prompt/category/' + id,
     method: 'get',
-    headers:myHeaders
+    // headers:myHeaders
 });
 };
+export const addPromptCategory=(data:PromptModel)=>{
+    return request({
+        url:'/ai/prompt/category',
+        method:'post',
+        data:data
+    })
+}
+export const putPromptCategory=(data:PromptModel)=>{
+    return request({
+        url:'/ai/prompt/category',
+        method:'put',
+        data:data
+    })
+}
+export const deletePromptCategory=(id:number)=>{
+    return request({
+        url:'/ai/prompt/category/'+id,
+        method:'delete',
+    })
+}
+
+

+ 2 - 2
src/api/promptwordManagement/types.ts

@@ -1,10 +1,10 @@
 export interface PromptModel {
     code?: string;
-    createdAt?: Date;
+    createdAt?: string;
     description?: string;
     id?: number;
     name?: string;
-    parentId?: number;
+    parentId?: number|string;
     sortOrder?: number;
     [property: string]: any;
 }

+ 7 - 1
src/router/index.ts

@@ -126,7 +126,13 @@ export const constantRoutes: RouteRecordRaw[] = [
         component: () => import('@/views/promptpermission/index.vue'),
         name:'PromptPermissionManagement',
         meta: {title: '提示词权限管理', icon: 'dashboard', affix: true}
-      }
+      },
+      {
+        path: '/modeldetailed',
+        component: () => import('@/views/modeldetailed/index.vue'),
+        name:'ModelDetailed',
+        meta: {title: '模型详细', icon: 'dashboard', affix: true}
+      },
     ]
   },
   {

+ 5 - 3
src/views/modeldetailed/index.vue

@@ -338,6 +338,7 @@ const initCallTrendChart = () => {
     display: flex;
     flex-direction: column;
     justify-content: flex-start;
+    gap: 20px;
 }
 .model-top-title {
     font-size: 16px;
@@ -349,7 +350,7 @@ const initCallTrendChart = () => {
     align-items: center;
     font-size: 13px;
     margin-bottom: 4px;
-    gap: 8px;
+    gap: 20px;
 }
 .model-top-label {
     color: #888;
@@ -369,13 +370,13 @@ const initCallTrendChart = () => {
 .model-top-right {
     flex: 1;
     display: flex;
-    flex-direction: row;
+    flex-direction: column;
     align-items: flex-start;
     justify-content: space-between;
     min-width: 360px;
     margin-left: 32px;
     margin-right: 32px;
-    gap: 32px;
+    gap: 30px;
 }
 .model-top-right-info {
     color: #222;
@@ -388,6 +389,7 @@ const initCallTrendChart = () => {
     justify-content: center;
     flex: 1;
     min-width: 180px;
+    gap: 20px;
 }
 .model-top-right-btns {
     display: flex;

+ 80 - 37
src/views/promptpermission/index.vue

@@ -9,7 +9,7 @@
     <!-- 搜索栏 -->
     <el-form :inline="true" class="search-form">
       <el-form-item>
-        <el-input style="width: 1500px" v-model="search.keyword" placeholder="请输入用户名称、角色名称" clearable />
+        <el-input style="width: 1400px" v-model="search.keyword" placeholder="请输入用户名称、角色名称" clearable />
       </el-form-item>
       <el-form-item label="类型">
         <el-select v-model="search.role" placeholder="全部" clearable>
@@ -18,7 +18,7 @@
           <el-option label="editor" value="editor" />
         </el-select>
       </el-form-item>
-      <el-button type="primary" @click="handleReset">重置</el-button>
+      <el-button type="plain" @click="handleReset">重置</el-button>
       <el-button type="primary" @click="handleSearch">搜索</el-button>
     </el-form>
 
@@ -51,61 +51,80 @@
         </div>
       </div>
         <el-divider style="margin-top: 1px"></el-divider>
-       <div class="inheritanceSettings">
-         //TODO:完成选择分类 全选 全不选样式
-         <div >
+      <div style="display: flex; align-items: center; gap: 10px;">
+        <el-select v-model="value" placeholder="选择分类" style="width: 150px">
+<!--          <el-option-->
+<!--              v-for="item in options"-->
+<!--              :key="item.value"-->
+<!--              :label="item.label"-->
+<!--              :value="item.value"-->
+<!--          />-->
+        </el-select>
+        <el-button type="plain">全选</el-button>
+        <el-button type="plain">全不选</el-button>
 
-         </div>
+      </div>
+       <div class="inheritanceSettings">
         <span>权限继承设置</span><br/>
          <el-checkbox-group v-model="inheritanceoptions" size="large">
            <el-checkbox label="0" style="color: black">从父分类继承权限</el-checkbox>
            <el-checkbox label="1"style="color: black" >从角色继承权限</el-checkbox>
          </el-checkbox-group>
-         <div style="color: #777777;font-size: small">继承的权限显示为灰色,可直接修改,如需修改,请到源头权限处修改</div>
+         <div style="color: #777777;font-size: small">继承的权限显示为灰色,可直接修改,如需修改,请到源头权限处修改</div>
        </div>
 
 
       <!-- 权限树结构 -->
-      <div class="assign-body">
-        <el-table :data="treeData" border>
-          <el-table-column prop="label" label="分类" width="200" />
-
-          <el-table-column label="查看权限">
-            <template #default="{ row }">
-              <el-select v-model="row.view" placeholder="请选择" style="width: 120px">
-                <el-option label="管理" value="manage" />
-                <el-option label="只读" value="readonly" />
-                <el-option label="无权限" value="none" />
+      <div>
+        <el-table :data="tableData" style="width: 100%">
+          <el-table-column type="expand">
+            <template #default="props">
+              <el-tree :data="props.row.children" show-checkbox node-key="id"></el-tree>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name" label="提示词分组/名称"></el-table-column>
+          <el-table-column prop="readPermission" label="读权限">
+            <template #default="scope">
+              <el-select v-model="scope.row.readPermission" placeholder="请选择">
+                <el-option label="无权限" value="无权限"></el-option>
+                <el-option label="只读" value="只读"></el-option>
+                <el-option label="可编辑" value="可编辑"></el-option>
+                <el-option label="管理" value="管理"></el-option>
               </el-select>
             </template>
           </el-table-column>
-
-          <el-table-column label="编辑权限">
-            <template #default="{ row }">
-              <el-select v-model="row.edit" placeholder="请选择" style="width: 120px">
-                <el-option label="管理" value="manage" />
-                <el-option label="只读" value="readonly" />
-                <el-option label="无权限" value="none" />
+          <el-table-column prop="writePermission" label="写权限">
+            <template #default="scope">
+              <el-select v-model="scope.row.writePermission" placeholder="请选择">
+                <el-option label="无权限" value="无权限"></el-option>
+                <el-option label="只读" value="只读"></el-option>
+                <el-option label="可编辑" value="可编辑"></el-option>
+                <el-option label="管理" value="管理"></el-option>
               </el-select>
             </template>
           </el-table-column>
-
-          <el-table-column label="写作权限">
-            <template #default="{ row }">
-              <el-select v-model="row.write" placeholder="请选择" style="width: 120px">
-                <el-option label="管理" value="manage" />
-                <el-option label="只读" value="readonly" />
-                <el-option label="无权限" value="none" />
+          <el-table-column prop="deletePermission" label="删除权限">
+            <template #default="scope">
+              <el-select v-model="scope.row.deletePermission" placeholder="请选择">
+                <el-option label="无权限" value="无权限"></el-option>
+                <el-option label="只读" value="只读"></el-option>
+                <el-option label="可编辑" value="可编辑"></el-option>
+                <el-option label="管理" value="管理"></el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column prop="managePermission" label="管理权限">
+            <template #default="scope">
+              <el-select v-model="scope.row.managePermission" placeholder="请选择">
+                <el-option label="无权限" value="无权限"></el-option>
+                <el-option label="只读" value="只读"></el-option>
+                <el-option label="可编辑" value="可编辑"></el-option>
+                <el-option label="管理" value="管理"></el-option>
               </el-select>
             </template>
           </el-table-column>
         </el-table>
       </div>
-
-      <div class="assign-footer">
-        <el-button type="primary" @click="savePermission">保存并分配权限</el-button>
-        <el-button type="danger">批量移除</el-button>
-      </div>
     </div>
   </div>
 </template>
@@ -118,7 +137,30 @@ const search = ref({
   keyword: '',
   role: ''
 })
-
+const tableData=ref([
+  {
+    name: '内容创作',
+    readPermission: '',
+    writePermission: '',
+    deletePermission: '',
+    managePermission: '',
+    children: [
+      { id: 1, label: '文章撰写' },
+      { id: 2, label: '创意写作模板' }
+    ]
+  },{
+  name: '知识问答',
+    readPermission: '',
+    writePermission: '',
+    deletePermission: '',
+    managePermission: '',
+    children: [
+  { id: 1, label: '文章撰写' },
+  { id: 2, label: '创意写作模板' }
+]
+}
+  // 更多行...
+])
 const userList = ref([
   { name: 'admin', type: '角色', readpermission: 12, writepermission: 5, managepermission: 3 },
   { name: 'editor', type: '角色', readpermission: 8, writepermission: 2, managepermission: 1 },
@@ -181,6 +223,7 @@ const savePermission = () => {
 <style scoped>
 .inheritanceSettings{
   background-color: #F5F7FA;
+  margin-top: 30px;
 }
 .permission-page {
   padding: 20px;

+ 271 - 72
src/views/promptwordManagement/index.vue

@@ -1,127 +1,246 @@
 <template>
   <el-row :gutter="20">
     <!-- 左侧树形结构 -->
-    <el-col :span="6">
+    <el-col :span="3">
       <el-card shadow="never">
         <div class="header">
           <span>分类树</span>
-          <el-button type="primary" size="small" class="add-btn">添加根分类</el-button>
+          <el-button class="add-btn" size="small" type="primary" @click="addcategory">添加根分类</el-button>
         </div>
-        <el-tree :data="treeData" :props="treeProps" node-key="id" highlight-current @node-click="handleNodeClick" />
+        <el-divider></el-divider>
+        <el-tree ref="treeRef" :data="treeData" :props="treeProps" :render-content="renderTreeContent"
+                 :row-style="{height:'100px'}"
+                 highlight-current node-key="id" @node-click="handleNodeClick"/>
       </el-card>
+      <!-- 树形结构下方按钮 -->
+      <div style="margin-top: 10px; display: flex; justify-content: space-between;">
+        <el-button size="default" @click="expandAll">展开所有</el-button>
+        <el-button size="default" @click="collapseAll">折叠所有</el-button>
+      </div>
     </el-col>
 
     <!-- 中间表单区域 -->
-    <el-col :span="18">
+    <el-col :span="21">
       <el-card shadow="never">
-        <h3>编辑分类</h3>
-        <el-form :model="form" label-width="120px">
-          <el-form-item label="分类名称">
-            <el-input v-model="form.name" />
-          </el-form-item>
-          <el-form-item label="分类编码">
-            <el-input v-model="form.code" />
-          </el-form-item>
-          <el-form-item label="父级分类">
-            <el-select v-model="form.parentId" placeholder="请选择父级分类">
-              <el-option label="无(根分类)" value="1" />
-            </el-select>
+       <div style="display: flex;justify-content: space-between">
+         <h3>{{ addOrEdit }}分类</h3>
+        <el-tag round effect="light">ID:{{form.id}}</el-tag>
+       </div>
+
+        <el-form ref="formvalidate" :model="form" :rules="rules" label-position="top" label-width="120px">
+          <el-form-item label="分类名称" prop="name">
+            <el-input v-model="form.name"/>
           </el-form-item>
-          <el-form-item label="排序顺序">
-            <el-input-number v-model="form.sort" :min="1" />
+          <el-form-item label="分类编码" prop="code">
+            <el-input v-model="form.code"/>
+            <div>
+              <span style="color: #777777">分类编码 用于系统标识,只能包含字母,数字和连字符</span>
+            </div>
           </el-form-item>
-          <el-form-item label="分类描述">
-            <el-input v-model="form.description" type="textarea" />
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="父级分类" prop="parentId">
+                <el-select v-model="form.parentId" placeholder="请选择父级分类">
+                  <el-option label="无(根分类)" :value="1"/>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="排序顺序" prop="sort">
+                <el-input v-model="form.sort" :min="1" style="width: 100%;"/>
+                <div style="color: #999; font-size: 14px; margin-top: 5px;">数值越小排序越靠前</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-form-item label="分类描述" prop="description">
+            <el-input v-model="form.description" type="textarea"/>
           </el-form-item>
         </el-form>
         <!-- 关键词提示模块 -->
         <div style="color: #777777">关键词提示词</div>
         <div class="keyword-box" style="display: flex">
           <div class="keyword-content" style="margin-top: 20px;margin-bottom: 20px;margin-left: 20px">
-            <span >该分类下共有 {{ templateCount }} 个提示词模板</span><br>
-            <el-button type="plain" size="small" @click="viewKeywords" style="margin-top: 10px ">查看关联提示词</el-button>
+            <span>该分类下共有 {{ templateCount }} 个提示词模板</span><br>
+            <el-button plain size="small" style="margin-top: 10px " @click="viewKeywords">查看关联提示词</el-button>
           </div>
         </div>
         <div class="form-footer">
-          <el-button type="danger">删除分类</el-button>
+          <el-button v-show="showdeletebutton" type="danger" @click="deletecategory">删除分类</el-button>
           <div class="right-btns">
             <el-button>取消</el-button>
-            <el-button type="primary">保存</el-button>
+            <el-button type="primary" @click="saveform(formvalidate)">{{ saveoradd }}</el-button>
           </div>
         </div>
       </el-card>
     </el-col>
   </el-row>
+
 </template>
 
-<script setup>
-import { ref } from 'vue';
-// import {PromptModel} from '/src/api/promptwordManagement/types.js'
-import {getPromptById} from '/src/api/promptwordManagement/promptpage.js'
-import {onMounted}  from "vue";
+<script lang="ts" setup>
+import {ref} from 'vue';
+import {PromptModel} from '@/api/promptwordManagement/types'
+import {getPromptById, addPromptCategory, putPromptCategory,deletePromptCategory} from '@/api/promptwordManagement/promptpage.js'
+import {onMounted} from "vue";
+import {ElMessage} from "element-plus/es";
+import type {FormInstance, FormRules} from 'element-plus'
+import {Document, Folder} from '@element-plus/icons-vue';
 
-const templateCount=ref(5)
+const showaddpromptcategory = ref(false)
+const templateCount = ref(5)
+const saveoradd = ref('保存')
+const showdeletebutton = ref(false)
+const addOrEdit = ref('新增')
+let form_add = reactive<PromptModel>({
+  id: 0,
+  name: '',
+  code: '',
+  description: '',
+  parentId: 0,
+  sortOrder: 0,
+  createdAt: ''
+})
 const treeData = ref([
   {
     id: 1,
-    label: '内容创作',
+    name: '内容创作',
+    code: '123',
+    description: '简单介绍',
+    parentid: '0',
+    sortOrder: '1',
     children: [
-      { id: 2, label: '文案撰写' },
-      { id: 3, label: '文章生成' }
+      {
+        id: 2,
+        name: '内容创作',
+        code: '123',
+        description: '简单介绍',
+        parentid: '0',
+        sortOrder: '1',
+      },
+      {
+        id: 3,
+        name: '内容创作',
+        code: '123',
+        description: '简单介绍',
+        parentid: '0',
+        sortOrder: '1',
+      }
     ]
   },
   {
     id: 4,
-    label: '知识问答',
+    name: '通用回答',
+    code: '123',
+    description: '简单介绍',
+    parentid: '0',
+    sortOrder: '1',
     children: [
-      { id: 5, label: '通用回答' },
-      { id: 6, label: '专业回答' }
+      {
+        id: 5,
+        name: '通用回答',
+        code: '123',
+        description: '简单介绍',
+        parentid: '0',
+        sortOrder: '1',
+      },
+      {
+        id: 6,
+        name: '专业回答',
+        code: '123',
+        description: '简单介绍',
+        parentid: '0',
+        sortOrder: '2',
+      }
     ]
   },
-  {
-    id: 7,
-    label: '代码助手',
-    children: [
-      { id: 7, label: '代码生成' },
-      { id: 9, label: '代码解释' },
-      { id:10,  label: 'Bug修复'}
-    ]
-  },
-  {
-    id: 11,
-    label: '聊天对话',
-    children: [
 
-    ]
-  },
-  {
-    id: 12,
-    label: '系统提示词',
-    children: [
 
-    ]
-  }
 ])
 
 const treeProps = {
   children: 'children',
-  label: 'label'
+  label: 'name'
 }
-
+const addcategory = () => {
+  saveoradd.value = '添加'
+  addOrEdit.value = '新增'
+  showdeletebutton.value = false
+  formvalidate.value.resetFields()
+}
+const viewKeywords = ref()
 const form = ref({
+  id:null,
   name: '',
   code: '',
   parentId: '',
-  sort: 1,
+  sort: null,
   description: ''
 })
+const rules = reactive<FormRules<PromptModel>>({
+  name: [
+    {required: true, message: '分类名称不能为空', trigger: 'blur'}
+  ],
+  code: [
+    {required: true, message: '分类编码不能为空', trigger: 'blur'}
+  ],
+  parentId: [
+    {required: true, message: '父分类不能为空', trigger: 'blur'}
+  ],
+  description: [
+    {required: true, message: '分类描述不能为空', trigger: 'blur'}
+  ],
+  sort: [
+    {required: true, message: '排序顺序不能为空', trigger: 'blur'}
+  ]
+})
+const formvalidate = ref<FormInstance>()
+const saveform = async (formvalidate: FormInstance | undefined) => {
+  // if (!formEl)return
+  const valid = await formvalidate.validate()
+  try {
+    if (valid) {
+      console.log('校验通过')
+      if (addOrEdit.value === '新增') {
+        await addPromptCategory(form.value)
+      } else {
+        await putPromptCategory(form.value)
+      }
+    }
+  } catch (error) {
+    ElMessage.error("出错了!")
+    console.log('出错:', error)
+  }
+
+
+}
+
+
+const renderTreeContent = (h, {node, data}) => {
+  const isFolder = !data.isLeaf;
+  return h(
+      'span',
+      {
+        style: {
+          display: 'flex',
+          alignItems: 'center'
+        }
+      },
+      [
+        h(ElIcon, {style: {marginRight: '6px'}}, () => isFolder ? h(Folder) : h(Document)),
+        h('span', null, node.label)
+      ]
+  );
+}
+
 function handleNodeClick(data, node) {
+  addOrEdit.value = '编辑'
+  saveoradd.value = '保存'
+  showdeletebutton.value = true
   const parent = node.parent
 
-  if (parent&&parent.level>0) {
+  if (parent && parent.level > 0) {
     // ✅ 如果有父节点,把它的 id 设置为 form.parentId
     form.value.parentId = parent.data.id
-    console.log('父节点ID为:', parent.data.id)
   } else {
     // 如果没有父节点(顶级节点),parentId 设为 null 或 ''
     form.value.parentId = '无(根分类)'
@@ -129,45 +248,125 @@ function handleNodeClick(data, node) {
   }
 
   // 其他表单字段可选填充
-  form.value.name = data.label
+  form.value.id=data.id
+  form.value.name = data.name
+  form.value.code = data.code
+  form.value.description = data.description
+  form.value.sort=data.sortOrder
 }
-const getData=async ()=>{
-  const data=await getPromptById(1)
-  const res=data.data
-  console.log('获得返回数据',res)
 
+
+const treeRef = ref() // 用于获取 el-tree 实例
+
+// 展开所有节点
+const expandAll = () => {
+  const tree = treeRef.value
+  if (tree) {
+    // 设置所有节点为展开状态
+    treeData.value.forEach(node => {
+      tree.store.nodesMap[node.id].expanded = true
+    })
+  }
 }
-console.log("组件被调用了")
-onMounted(()=>{
-  getData();
+
+// 折叠所有节点(只显示根节点)
+const collapseAll = () => {
+  const tree = treeRef.value
+  if (tree) {
+    // 设置所有节点为折叠状态
+    treeData.value.forEach(node => {
+      tree.store.nodesMap[node.id].expanded = false
+    })
+  }
+}
+// 递归删除节点
+const removeNode = (nodes, id) => {
+  for (let i = 0; i < nodes.length; i++) {
+    if (nodes[i].id === id) {
+      // 找到节点,从数组中移除
+      nodes.splice(i, 1);
+      return true;
+    }
+    if (nodes[i].children && nodes[i].children.length) {
+      const found = removeNode(nodes[i].children, id);
+      if (found) return true;
+    }
+  }
+  return false;
+};
+const deletecategory = async () => {
+  const nodeIdToDelete = form.value.id;
+
+  if (!nodeIdToDelete) {
+    ElMessage.warning('请选择一个分类进行删除');
+    return;
+  }
+
+  try {
+    await deletePromptCategory(nodeIdToDelete); // 调用接口删除
+    const deleted = removeNode(treeData.value, nodeIdToDelete);
+    if (deleted) {
+      ElMessage.success('删除成功');
+      form.value = {
+        id: null,
+        name: '',
+        code: '',
+        parentId: '',
+        sort: null,
+        description: ''
+      };
+      addOrEdit.value = '新增';
+      saveoradd.value = '添加';
+      showdeletebutton.value = false;
+    }
+  } catch (error) {
+    ElMessage.error('删除失败,请重试');
+    console.error('删除失败:', error);
+  }
+};
+
+
+onMounted(() => {
+  // getData();
 })
 
 </script>
 
 <style scoped>
-.keyword-content{
+.keyword-content {
   margin-top: 10px;
 }
-.keyword-box{
+
+.keyword-box {
   background-color: #F5F7FA;
 }
+
 .header {
   display: flex;
   justify-content: space-between;
   align-items: center;
   margin-bottom: 10px;
 }
+
 .add-btn {
   font-size: 12px;
 }
+
 .form-footer {
   display: flex;
   justify-content: space-between;
   align-items: center;
   margin-top: 20px;
 }
+
 .right-btns {
   display: flex;
   gap: 10px;
+  margin-left: auto;
+}
+
+.custom-tree-node {
+  display: flex;
+  align-items: center;
 }
 </style>