diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 016498e..95df8bc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,110 +44,3 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - fetch-tags: true - - # https://github.com/astral-sh/ruff-action - - name: Static check with Ruff - uses: astral-sh/ruff-action@v2 - with: - version: ">=0.8.2" - args: "check" - - - name: Build ragflow:nightly-slim - run: | - RUNNER_WORKSPACE_PREFIX=${RUNNER_WORKSPACE_PREFIX:-$HOME} - sudo docker pull ubuntu:22.04 - sudo docker build --progress=plain --build-arg LIGHTEN=1 --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim . - - - name: Build ragflow:nightly - run: | - sudo docker build --progress=plain --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly . - - - name: Start ragflow:nightly-slim - run: | - echo -e "\nRAGFLOW_IMAGE=infiniflow/ragflow:nightly-slim" >> docker/.env - sudo docker compose -f docker/docker-compose.yml up -d - - - name: Stop ragflow:nightly-slim - if: always() # always run this step even if previous steps failed - run: | - sudo docker compose -f docker/docker-compose.yml down -v - - - name: Start ragflow:nightly - run: | - echo -e "\nRAGFLOW_IMAGE=infiniflow/ragflow:nightly" >> docker/.env - sudo docker compose -f docker/docker-compose.yml up -d - - - name: Run sdk tests against Elasticsearch - run: | - export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY="" - export HOST_ADDRESS=http://host.docker.internal:9380 - until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do - echo "Waiting for service to be available..." - sleep 5 - done - cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_sdk_api && pytest -s --tb=short get_email.py t_dataset.py t_chat.py t_session.py t_document.py t_chunk.py - - - name: Run frontend api tests against Elasticsearch - run: | - export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY="" - export HOST_ADDRESS=http://host.docker.internal:9380 - until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do - echo "Waiting for service to be available..." - sleep 5 - done - cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_frontend_api && pytest -s --tb=short get_email.py test_dataset.py - - - name: Run http api tests against Elasticsearch - run: | - export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY="" - export HOST_ADDRESS=http://host.docker.internal:9380 - until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do - echo "Waiting for service to be available..." - sleep 5 - done - cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_http_api && pytest -s --tb=short -m "not slow" - - - name: Stop ragflow:nightly - if: always() # always run this step even if previous steps failed - run: | - sudo docker compose -f docker/docker-compose.yml down -v - - - name: Start ragflow:nightly - run: | - sudo DOC_ENGINE=infinity docker compose -f docker/docker-compose.yml up -d - - - name: Run sdk tests against Infinity - run: | - export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY="" - export HOST_ADDRESS=http://host.docker.internal:9380 - until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do - echo "Waiting for service to be available..." - sleep 5 - done - cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_sdk_api && pytest -s --tb=short get_email.py t_dataset.py t_chat.py t_session.py t_document.py t_chunk.py - - - name: Run frontend api tests against Infinity - run: | - export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY="" - export HOST_ADDRESS=http://host.docker.internal:9380 - until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do - echo "Waiting for service to be available..." - sleep 5 - done - cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_frontend_api && pytest -s --tb=short get_email.py test_dataset.py - - - name: Run http api tests against Infinity - run: | - export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY="" - export HOST_ADDRESS=http://host.docker.internal:9380 - until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do - echo "Waiting for service to be available..." - sleep 5 - done - cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_http_api && DOC_ENGINE=infinity pytest -s --tb=short -m "not slow" - - - name: Stop ragflow:nightly - if: always() # always run this step even if previous steps failed - run: | - sudo DOC_ENGINE=infinity docker compose -f docker/docker-compose.yml down -v diff --git a/README.md b/README.md index 4cf5c1b..9abd857 100644 --- a/README.md +++ b/README.md @@ -8,51 +8,28 @@ Ragflow-Plus 是一个基于 Ragflow 的开源项目,主旨是在不影响 Rag ### 一. 用户后台管理系统 -移除原登陆页用户注册的通道,搭建用户后台管理系统,可对用户进行管理,包括用户注册、查询、删除、修改等功能。 +移除原登陆页用户注册的通道,搭建用户后台管理系统,可对用户进行管理,包括用户管理、团队管理、用户模型配置管理等功能。 -### 二. 优化对话显示 -微调了对话界面的样式,使其观感更为友好 - -### 三. 文档撰写功能 +### 二. 文档撰写功能 新增文档撰写全新的交互方式,支持直接导出为 Word 文档 ## 使用方式 -### 1. 前端文件替换 +#### 1. 使用Docker Compose运行 -1. 克隆项目 -```bash -git clone https://github.com/zstar1003/ragflow-plus.git -``` - -2. 打包web文件 -```bash -cd web -pnpm run build -``` - -3. 进入到容器,删除容器中已有的/ragflow/web/dist文件 -```bash -docker exec -it ragflow-server /bin/sh -rm -rf /ragflow/web/dist -``` - -4. 将打包好的web文件拷贝到容器中 -```bash -docker cp dist ragflow-server:/ragflow/web/ -``` - -### 2. 管理系统运行方式 - -#### 2.1 使用Docker Compose运行 +和运行 ragflow 原始项目一样,项目根目录下执行 ```bash -docker compose -f management/docker-compose.yml up -d +docker compose -f docker/docker-compose.yml up -d ``` +访问地址:`服务器ip:80`,进入到ragflow原始界面 -访问地址:`服务器ip:8080`,进入到管理界面 +访问地址:`服务器ip:8888`,进入到管理界面 -#### 2.2 源码运行 + +#### 2. 源码运行 + +也可以通过下面的方式单独运行管理系统 启动后端: @@ -87,6 +64,34 @@ pnpm dev +#### 3. 前端文件替换(可选) + +ragflow-plus 还对原有的前端文件进行了若干优化,包含新增加的文档撰写功能,如需体验,可通过以下步骤替换原文件: + +1. 克隆项目 +```bash +git clone https://github.com/zstar1003/ragflow-plus.git +``` + +2. 打包web文件 +```bash +cd web +pnpm run build +``` + +3. 进入到容器,删除容器中已有的/ragflow/web/dist文件 +```bash +docker exec -it ragflow-server /bin/sh +rm -rf /ragflow/web/dist +``` + +4. 将打包好的web文件拷贝到容器中 +```bash +docker cp dist ragflow-server:/ragflow/web/ +``` + + + ## Agent功能恢复 由于在我的应用场景中,不需要Agent功能,故隐藏了Agent按钮的入口,如需恢复Agent功能,可修改`web\src\layouts\components\header\index.tsx`,对以下内容取消注释: @@ -98,14 +103,6 @@ pnpm dev 同时可将排列样式进行重置,以还原原本的样式布局,修改`web\src\layouts\components\header\index.less`文件,替换为ragflow原始样式:`https://github.com/infiniflow/ragflow/blob/main/web/src/layouts/components/header/index.less` -## Todo List - -- [x] 搭建用户后台管理系统 - -- [ ] 知识库批量上传解析 - -- [ ] 文档撰写图表支持 - ## 交流群 如果有其它需求或问题建议,可加入交流群进行讨论 @@ -123,7 +120,7 @@ pnpm dev ## 更新信息获取 -主要更新日志会在我的微信公众号[我有一计]上发布,欢迎关注。 +目前该项目仍在持续更新中,更新日志会在我的微信公众号[我有一计]上发布,欢迎关注。 ## Star History diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index b3fa364..ed09286 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -30,10 +30,18 @@ services: extra_hosts: - "host.docker.internal:host-gateway" + + # 新增加的用户后台信息管理系统 + management-frontend: + image: zstar1003/ragflowplus-management-web:v0.1.1 + ports: + - "8888:80" + management-frontend: image: zstar1003/ragflowplus-management-web:v0.1.1 ports: - "8080:80" + depends_on: - management-backend environment: @@ -47,7 +55,7 @@ services: - "5000:5000" environment: - FLASK_ENV=development - - CORS_ALLOWED_ORIGINS=http://localhost:8080,http://management-frontend + - CORS_ALLOWED_ORIGINS=http://localhost:8888,http://management-frontend extra_hosts: - "host.docker.internal:host-gateway" networks: diff --git a/management/docker-compose.yml b/management/docker-compose.yml index e073099..773a28e 100644 --- a/management/docker-compose.yml +++ b/management/docker-compose.yml @@ -1,19 +1,19 @@ services: frontend: - image: zstar1003/ragflowplus-management-web:v0.1.0 + image: zstar1003/ragflowplus-management-web:v0.1.1 build: context: . dockerfile: Dockerfile target: frontend ports: - - "8080:80" + - "8888:80" depends_on: - backend environment: - API_URL=http://backend:5000 backend: - image: zstar1003/ragflowplus-management-server:v0.1.0 + image: zstar1003/ragflowplus-management-server:v0.1.1 build: context: . dockerfile: Dockerfile @@ -22,6 +22,6 @@ services: - "5000:5000" environment: - FLASK_ENV=development - - CORS_ALLOWED_ORIGINS=http://localhost:8080,http://frontend + - CORS_ALLOWED_ORIGINS=http://localhost:8888,http://frontend extra_hosts: - "host.docker.internal:host-gateway" \ No newline at end of file diff --git a/management/web/src/common/apis/teams/type.ts b/management/web/src/common/apis/teams/type.ts index 52d3ba6..a8d11e4 100644 --- a/management/web/src/common/apis/teams/type.ts +++ b/management/web/src/common/apis/teams/type.ts @@ -14,6 +14,8 @@ export interface TableRequestData { username?: string /** 查询参数:邮箱 */ email?: string + /** 查询参数:团队名称 */ + name?: string // 添加 name 属性 } export interface TableData { diff --git a/management/web/src/pages/team-management/index.vue b/management/web/src/pages/team-management/index.vue index b85d351..beb5b17 100644 --- a/management/web/src/pages/team-management/index.vue +++ b/management/web/src/pages/team-management/index.vue @@ -34,9 +34,7 @@ function handleDelete() { ElMessage.success("如需解散该团队,可直接删除负责人账号") } -const tableData = ref([ - -]) +const tableData = ref([]) const searchData = reactive({ name: "" @@ -54,7 +52,14 @@ function getTableData() { name: searchData.name }).then(({ data }) => { paginationData.total = data.total - tableData.value = data.list + tableData.value = data.list.map((item: any) => ({ + id: item.id, + name: item.name, + ownerName: item.ownerName, + memberCount: item.memberCount, + createTime: item.createTime, + updateTime: item.updateTime + })) // 清空选中数据 multipleSelection.value = [] }).catch(() => { @@ -87,7 +92,7 @@ const memberLoading = ref(false) const addMemberDialogVisible = ref(false) const userList = ref<{ id: number, username: string }[]>([]) const userLoading = ref(false) -const selectedUser = ref(null) +const selectedUser = ref(undefined) const selectedRole = ref("normal") function handleManageMembers(row: TeamData) { @@ -100,7 +105,7 @@ function handleManageMembers(row: TeamData) { function getTeamMembers(teamId: number) { memberLoading.value = true getTeamMembersApi(teamId) - .then((response) => { + .then((response: any) => { if (response.data && Array.isArray(response.data.list)) { teamMembers.value = response.data.list } else if (Array.isArray(response.data)) { @@ -128,8 +133,12 @@ function handleAddMember() { // 获取用户列表 function getUserList() { userLoading.value = true - getUsersApi().then(({ data }) => { - userList.value = data.list + getUsersApi().then((res: any) => { + if (res.data) { + userList.value = res.data.list + } else { + userList.value = [] + } }).catch(() => { userList.value = [] }).finally(() => { @@ -163,7 +172,7 @@ function confirmAddMember() { // 刷新团队列表(更新成员数量) getTableData() // 重置选择 - selectedUser.value = null + selectedUser.value = undefined selectedRole.value = "normal" }).catch((error) => { console.error("添加成员失败:", error) @@ -178,8 +187,12 @@ function handleRemoveMember(member: TeamMember) { cancelButtonText: "取消", type: "warning" }).then(() => { + if (!currentTeam.value || !currentTeam.value.id) { + ElMessage.error("当前团队信息不存在") + return + } removeTeamMemberApi({ - teamId: currentTeam.value?.id, + teamId: currentTeam.value.id, memberId: member.userId }).then(() => { ElMessage.success("成员移除成功") @@ -228,7 +241,7 @@ watch([() => paginationData.currentPage, () => paginationData.pageSize], getTabl 成员管理 - + 删除