改进
This commit is contained in:
parent
834928dbe9
commit
e9e1e3e0ca
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
|
|
||||||
"spaces": 2,
|
|
||||||
"generator-cli": {
|
|
||||||
"version": "7.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
745
api/swagger.json
745
api/swagger.json
@ -1,745 +0,0 @@
|
|||||||
{
|
|
||||||
"swagger": "2.0",
|
|
||||||
"info": {
|
|
||||||
"description": "This is a sample server celler server.",
|
|
||||||
"title": "Swagger Example API",
|
|
||||||
"contact": {},
|
|
||||||
"version": "1.0"
|
|
||||||
},
|
|
||||||
"paths": {
|
|
||||||
"/libraries": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Libraries"
|
|
||||||
],
|
|
||||||
"summary": "获取资料库列表",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "页码",
|
|
||||||
"name": "Page",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponsePaginated"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"post": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Libraries"
|
|
||||||
],
|
|
||||||
"summary": "新建资料库",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "资料库名称",
|
|
||||||
"name": "Name",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"201": {
|
|
||||||
"description": "Created",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/model.Library"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/library/{LibraryId}": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Libraries"
|
|
||||||
],
|
|
||||||
"summary": "显示资料库",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"204": {
|
|
||||||
"description": "No Content"
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"delete": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Libraries"
|
|
||||||
],
|
|
||||||
"summary": "删除资料库",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"204": {
|
|
||||||
"description": "No Content"
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/library/{LibraryId}/document/{DocumentId}": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Documents"
|
|
||||||
],
|
|
||||||
"summary": "显示文档",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "文档 ID",
|
|
||||||
"name": "DocumentId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/model.Document"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"put": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Documents"
|
|
||||||
],
|
|
||||||
"summary": "更新文档",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "文档 ID",
|
|
||||||
"name": "DocumentId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "标题",
|
|
||||||
"name": "Title",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "内容",
|
|
||||||
"name": "Content",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/model.Document"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"delete": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Documents"
|
|
||||||
],
|
|
||||||
"summary": "删除文档",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "文档 ID",
|
|
||||||
"name": "DocumentId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"204": {
|
|
||||||
"description": "No Content"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/library/{LibraryId}/document/{DocumentId}/chunks": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Documents"
|
|
||||||
],
|
|
||||||
"summary": "查看处理状态",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "文档 ID",
|
|
||||||
"name": "DocumentId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/controller.chunkStatusResponse"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/library/{LibraryId}/documents": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "获取当前账号的文档列表",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Documents"
|
|
||||||
],
|
|
||||||
"summary": "获取文档列表",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "页码",
|
|
||||||
"name": "Page",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponsePaginated"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"post": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Documents"
|
|
||||||
],
|
|
||||||
"summary": "新建文档",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "标题",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "标题",
|
|
||||||
"name": "Title",
|
|
||||||
"in": "formData",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "描述",
|
|
||||||
"name": "Description",
|
|
||||||
"in": "formData"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "文档内容",
|
|
||||||
"name": "Content",
|
|
||||||
"in": "formData"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"201": {
|
|
||||||
"description": "Created",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/model.Document"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/library/{LibraryId}/query": {
|
|
||||||
"get": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"BearerToken": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Documents"
|
|
||||||
],
|
|
||||||
"summary": "Server Sent Events 查询文档",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "资料库 ID",
|
|
||||||
"name": "LibraryId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "问题",
|
|
||||||
"name": "Question",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"description": "Forbidden",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/pkg.ResponseError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"definitions": {
|
|
||||||
"controller.chunkStatusResponse": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"chunked": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"completed": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"total": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"gorm.DeletedAt": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"time": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"valid": {
|
|
||||||
"description": "Valid is true if Time is not NULL",
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"model.Document": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"chunked": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"content": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"deletedAt": {
|
|
||||||
"$ref": "#/definitions/gorm.DeletedAt"
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"libraryId": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"title": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"updatedAt": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"userId": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"model.Library": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"createdAt": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"deletedAt": {
|
|
||||||
"$ref": "#/definitions/gorm.DeletedAt"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"updatedAt": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"userId": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pkg.ResponseError": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"message": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pkg.ResponsePaginated": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Data": {},
|
|
||||||
"Limit": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"Page": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"Total": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"securityDefinitions": {
|
|
||||||
"BearerToken": {
|
|
||||||
"type": "apiKey",
|
|
||||||
"name": "Authorization",
|
|
||||||
"in": "header"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,6 +19,7 @@
|
|||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"google-protobuf": "^3.21.2",
|
"google-protobuf": "^3.21.2",
|
||||||
"grpc-web": "^1.5.0",
|
"grpc-web": "^1.5.0",
|
||||||
|
"keycloak-js": "^24.0.4",
|
||||||
"mammoth": "^1.6.0",
|
"mammoth": "^1.6.0",
|
||||||
"md-editor-v3": "^4.8.3",
|
"md-editor-v3": "^4.8.3",
|
||||||
"pdfjs-dist": "^4.0.269",
|
"pdfjs-dist": "^4.0.269",
|
||||||
|
@ -5,60 +5,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { library } from "@/plugins/api";
|
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useUserStore } from "@/store/user";
|
import * as libraryProto from "@/proto/library/library";
|
||||||
import {GrpcWebFetchTransport} from "@protobuf-ts/grpcweb-transport"
|
import * as documentProto from "@/proto/document/document";
|
||||||
import {LibraryServiceClient} from "@/proto/library/library.client.ts"
|
import keycloak from "@/plugins/keycloak"
|
||||||
import {DocumentServiceClient} from "@/proto/document/document.client.ts"
|
import {libraryServiceClient} from "@/plugins/rpc"
|
||||||
import * as libraryProto from "@/proto/library/library.ts";
|
|
||||||
import * as documentProto from "@/proto/document/document.ts";
|
|
||||||
|
|
||||||
let listLibrary: libraryProto.ListLibrariesRequest = {
|
let listLibrary: libraryProto.ListLibrariesRequest = {
|
||||||
page: 1
|
page: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
let empty: documentProto.Empty = {}
|
|
||||||
|
|
||||||
let transport = new GrpcWebFetchTransport({
|
libraryServiceClient.listLibraries(listLibrary)
|
||||||
baseUrl: "https://test.ivampiresp.com",
|
|
||||||
format: "text",
|
|
||||||
meta: {
|
|
||||||
"Authorization": "Bearer 1",
|
|
||||||
},
|
|
||||||
timeout: 100 * 1000,
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
let client = new LibraryServiceClient(transport)
|
|
||||||
let documentClient = new DocumentServiceClient(transport)
|
|
||||||
|
|
||||||
let s = documentClient.testStream(empty)
|
|
||||||
|
|
||||||
s.responses.onMessage(e => {
|
|
||||||
console.log(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
s.then(res => {
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
console.log(s)
|
|
||||||
|
|
||||||
// let out = client.listLibraries(listLibrary, {})
|
|
||||||
// out.then((r) => console.log(r))
|
|
||||||
|
|
||||||
const userStore = useUserStore();
|
|
||||||
const token = ref("");
|
|
||||||
|
|
||||||
const settoken = () => {
|
|
||||||
userStore.login("0", token.value);
|
|
||||||
|
|
||||||
console.log(userStore.jwt_token);
|
|
||||||
};
|
|
||||||
|
|
||||||
const testrequest = () => {
|
|
||||||
library.librariesGet(1).then((r) => console.log(r));
|
|
||||||
};
|
|
||||||
|
|
||||||
// library.libraryLibraryIdDocumentsGet(1,2)
|
|
||||||
</script>
|
</script>
|
||||||
|
4
src/openapi/.gitignore
vendored
4
src/openapi/.gitignore
vendored
@ -1,4 +0,0 @@
|
|||||||
wwwroot/*.js
|
|
||||||
node_modules
|
|
||||||
typings
|
|
||||||
dist
|
|
@ -1 +0,0 @@
|
|||||||
# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm
|
|
@ -1,23 +0,0 @@
|
|||||||
# OpenAPI Generator Ignore
|
|
||||||
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
|
||||||
|
|
||||||
# Use this file to prevent files from being overwritten by the generator.
|
|
||||||
# The patterns follow closely to .gitignore or .dockerignore.
|
|
||||||
|
|
||||||
# As an example, the C# client generator defines ApiClient.cs.
|
|
||||||
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
|
||||||
#ApiClient.cs
|
|
||||||
|
|
||||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
|
||||||
#foo/*/qux
|
|
||||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
|
||||||
|
|
||||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
|
||||||
#foo/**/qux
|
|
||||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
|
||||||
|
|
||||||
# You can also negate patterns with an exclamation (!).
|
|
||||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
|
||||||
#docs/*.md
|
|
||||||
# Then explicitly reverse the ignore rule for a single file:
|
|
||||||
#!docs/README.md
|
|
@ -1,8 +0,0 @@
|
|||||||
.gitignore
|
|
||||||
.npmignore
|
|
||||||
api.ts
|
|
||||||
base.ts
|
|
||||||
common.ts
|
|
||||||
configuration.ts
|
|
||||||
git_push.sh
|
|
||||||
index.ts
|
|
@ -1 +0,0 @@
|
|||||||
7.1.0
|
|
1208
src/openapi/api.ts
1208
src/openapi/api.ts
File diff suppressed because it is too large
Load Diff
@ -1,86 +0,0 @@
|
|||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Swagger Example API
|
|
||||||
* This is a sample server celler server.
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import type { Configuration } from './configuration';
|
|
||||||
// Some imports not used depending on template conditions
|
|
||||||
// @ts-ignore
|
|
||||||
import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
||||||
import globalAxios from 'axios';
|
|
||||||
|
|
||||||
export const BASE_PATH = "http://localhost".replace(/\/+$/, "");
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const COLLECTION_FORMATS = {
|
|
||||||
csv: ",",
|
|
||||||
ssv: " ",
|
|
||||||
tsv: "\t",
|
|
||||||
pipes: "|",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface RequestArgs
|
|
||||||
*/
|
|
||||||
export interface RequestArgs {
|
|
||||||
url: string;
|
|
||||||
options: AxiosRequestConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class BaseAPI
|
|
||||||
*/
|
|
||||||
export class BaseAPI {
|
|
||||||
protected configuration: Configuration | undefined;
|
|
||||||
|
|
||||||
constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
|
|
||||||
if (configuration) {
|
|
||||||
this.configuration = configuration;
|
|
||||||
this.basePath = configuration.basePath ?? basePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class RequiredError
|
|
||||||
* @extends {Error}
|
|
||||||
*/
|
|
||||||
export class RequiredError extends Error {
|
|
||||||
constructor(public field: string, msg?: string) {
|
|
||||||
super(msg);
|
|
||||||
this.name = "RequiredError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ServerMap {
|
|
||||||
[key: string]: {
|
|
||||||
url: string,
|
|
||||||
description: string,
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const operationServerMap: ServerMap = {
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Swagger Example API
|
|
||||||
* This is a sample server celler server.
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import type { Configuration } from "./configuration";
|
|
||||||
import type { RequestArgs } from "./base";
|
|
||||||
import type { AxiosInstance, AxiosResponse } from 'axios';
|
|
||||||
import { RequiredError } from "./base";
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const DUMMY_BASE_URL = 'https://example.com'
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @throws {RequiredError}
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) {
|
|
||||||
if (paramValue === null || paramValue === undefined) {
|
|
||||||
throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) {
|
|
||||||
if (configuration && configuration.apiKey) {
|
|
||||||
const localVarApiKeyValue = typeof configuration.apiKey === 'function'
|
|
||||||
? await configuration.apiKey(keyParamName)
|
|
||||||
: await configuration.apiKey;
|
|
||||||
object[keyParamName] = localVarApiKeyValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setBasicAuthToObject = function (object: any, configuration?: Configuration) {
|
|
||||||
if (configuration && (configuration.username || configuration.password)) {
|
|
||||||
object["auth"] = { username: configuration.username, password: configuration.password };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) {
|
|
||||||
if (configuration && configuration.accessToken) {
|
|
||||||
const accessToken = typeof configuration.accessToken === 'function'
|
|
||||||
? await configuration.accessToken()
|
|
||||||
: await configuration.accessToken;
|
|
||||||
object["Authorization"] = "Bearer " + accessToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) {
|
|
||||||
if (configuration && configuration.accessToken) {
|
|
||||||
const localVarAccessTokenValue = typeof configuration.accessToken === 'function'
|
|
||||||
? await configuration.accessToken(name, scopes)
|
|
||||||
: await configuration.accessToken;
|
|
||||||
object["Authorization"] = "Bearer " + localVarAccessTokenValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: any, key: string = ""): void {
|
|
||||||
if (parameter == null) return;
|
|
||||||
if (typeof parameter === "object") {
|
|
||||||
if (Array.isArray(parameter)) {
|
|
||||||
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Object.keys(parameter).forEach(currentKey =>
|
|
||||||
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (urlSearchParams.has(key)) {
|
|
||||||
urlSearchParams.append(key, parameter);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
urlSearchParams.set(key, parameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setSearchParams = function (url: URL, ...objects: any[]) {
|
|
||||||
const searchParams = new URLSearchParams(url.search);
|
|
||||||
setFlattenedQueryParams(searchParams, objects);
|
|
||||||
url.search = searchParams.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) {
|
|
||||||
const nonString = typeof value !== 'string';
|
|
||||||
const needsSerialization = nonString && configuration && configuration.isJsonMime
|
|
||||||
? configuration.isJsonMime(requestOptions.headers['Content-Type'])
|
|
||||||
: nonString;
|
|
||||||
return needsSerialization
|
|
||||||
? JSON.stringify(value !== undefined ? value : {})
|
|
||||||
: (value || "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const toPathString = function (url: URL) {
|
|
||||||
return url.pathname + url.search + url.hash
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) {
|
|
||||||
return <T = unknown, R = AxiosResponse<T>>(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
|
||||||
const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || axios.defaults.baseURL || basePath) + axiosArgs.url};
|
|
||||||
return axios.request<T, R>(axiosRequestArgs);
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Swagger Example API
|
|
||||||
* This is a sample server celler server.
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
export interface ConfigurationParameters {
|
|
||||||
apiKey?: string | Promise<string> | ((name: string) => string) | ((name: string) => Promise<string>);
|
|
||||||
username?: string;
|
|
||||||
password?: string;
|
|
||||||
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
|
|
||||||
basePath?: string;
|
|
||||||
serverIndex?: number;
|
|
||||||
baseOptions?: any;
|
|
||||||
formDataCtor?: new () => any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Configuration {
|
|
||||||
/**
|
|
||||||
* parameter for apiKey security
|
|
||||||
* @param name security name
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
apiKey?: string | Promise<string> | ((name: string) => string) | ((name: string) => Promise<string>);
|
|
||||||
/**
|
|
||||||
* parameter for basic security
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
username?: string;
|
|
||||||
/**
|
|
||||||
* parameter for basic security
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
password?: string;
|
|
||||||
/**
|
|
||||||
* parameter for oauth2 security
|
|
||||||
* @param name security name
|
|
||||||
* @param scopes oauth2 scope
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
|
|
||||||
/**
|
|
||||||
* override base path
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
basePath?: string;
|
|
||||||
/**
|
|
||||||
* override server index
|
|
||||||
*
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
serverIndex?: number;
|
|
||||||
/**
|
|
||||||
* base options for axios calls
|
|
||||||
*
|
|
||||||
* @type {any}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
baseOptions?: any;
|
|
||||||
/**
|
|
||||||
* The FormData constructor that will be used to create multipart form data
|
|
||||||
* requests. You can inject this here so that execution environments that
|
|
||||||
* do not support the FormData class can still run the generated client.
|
|
||||||
*
|
|
||||||
* @type {new () => FormData}
|
|
||||||
*/
|
|
||||||
formDataCtor?: new () => any;
|
|
||||||
|
|
||||||
constructor(param: ConfigurationParameters = {}) {
|
|
||||||
this.apiKey = param.apiKey;
|
|
||||||
this.username = param.username;
|
|
||||||
this.password = param.password;
|
|
||||||
this.accessToken = param.accessToken;
|
|
||||||
this.basePath = param.basePath;
|
|
||||||
this.serverIndex = param.serverIndex;
|
|
||||||
this.baseOptions = param.baseOptions;
|
|
||||||
this.formDataCtor = param.formDataCtor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given MIME is a JSON MIME.
|
|
||||||
* JSON MIME examples:
|
|
||||||
* application/json
|
|
||||||
* application/json; charset=UTF8
|
|
||||||
* APPLICATION/JSON
|
|
||||||
* application/vnd.company+json
|
|
||||||
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
|
||||||
* @return True if the given MIME is JSON, false otherwise.
|
|
||||||
*/
|
|
||||||
public isJsonMime(mime: string): boolean {
|
|
||||||
const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i');
|
|
||||||
return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
|
|
||||||
#
|
|
||||||
# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
|
|
||||||
|
|
||||||
git_user_id=$1
|
|
||||||
git_repo_id=$2
|
|
||||||
release_note=$3
|
|
||||||
git_host=$4
|
|
||||||
|
|
||||||
if [ "$git_host" = "" ]; then
|
|
||||||
git_host="github.com"
|
|
||||||
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$git_user_id" = "" ]; then
|
|
||||||
git_user_id="GIT_USER_ID"
|
|
||||||
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$git_repo_id" = "" ]; then
|
|
||||||
git_repo_id="GIT_REPO_ID"
|
|
||||||
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$release_note" = "" ]; then
|
|
||||||
release_note="Minor update"
|
|
||||||
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Initialize the local directory as a Git repository
|
|
||||||
git init
|
|
||||||
|
|
||||||
# Adds the files in the local repository and stages them for commit.
|
|
||||||
git add .
|
|
||||||
|
|
||||||
# Commits the tracked changes and prepares them to be pushed to a remote repository.
|
|
||||||
git commit -m "$release_note"
|
|
||||||
|
|
||||||
# Sets the new remote
|
|
||||||
git_remote=$(git remote)
|
|
||||||
if [ "$git_remote" = "" ]; then # git remote not defined
|
|
||||||
|
|
||||||
if [ "$GIT_TOKEN" = "" ]; then
|
|
||||||
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
|
|
||||||
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
|
|
||||||
else
|
|
||||||
git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
git pull origin master
|
|
||||||
|
|
||||||
# Pushes (Forces) the changes in the local repository up to the remote repository
|
|
||||||
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
|
|
||||||
git push origin master 2>&1 | grep -v 'To https'
|
|
@ -1,18 +0,0 @@
|
|||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Swagger Example API
|
|
||||||
* This is a sample server celler server.
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
export * from "./api";
|
|
||||||
export * from "./configuration";
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
import { DocumentsApi, Configuration, LibrariesApi } from "../openapi";
|
|
||||||
|
|
||||||
// import axios from "axios";
|
|
||||||
// import router from "@/router";
|
|
||||||
import {useUserStore} from "@/store/user";
|
|
||||||
import { useConfigStore } from "@/store/config";
|
|
||||||
|
|
||||||
|
|
||||||
const userStore = useUserStore()
|
|
||||||
const configStore = useConfigStore()
|
|
||||||
|
|
||||||
const conf = new Configuration
|
|
||||||
conf.basePath = configStore.apiServer
|
|
||||||
|
|
||||||
conf.apiKey = "Bearer " + userStore.jwt_token
|
|
||||||
const document = new DocumentsApi(conf);
|
|
||||||
const library = new LibrariesApi(conf);
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
|
||||||
document, library, conf
|
|
||||||
}
|
|
14
src/plugins/config.ts
Normal file
14
src/plugins/config.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
let staticConfig = {
|
||||||
|
url: "https://auth.leaflow.cn/",
|
||||||
|
realm: "UserLand",
|
||||||
|
clientId: "Leaf Library",
|
||||||
|
|
||||||
|
scope: "openid profile",
|
||||||
|
checkLoginIframe: false,
|
||||||
|
redirectUri: window.location.origin + "/auth/login",
|
||||||
|
|
||||||
|
rpc_base_url: "http://127.0.0.1:18081"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default staticConfig
|
41
src/plugins/keycloak.ts
Normal file
41
src/plugins/keycloak.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import Keycloak, { KeycloakConfig, KeycloakInitOptions } from "keycloak-js";
|
||||||
|
import config from "@/plugins/config"
|
||||||
|
|
||||||
|
|
||||||
|
const keycloakConfig: KeycloakConfig = {
|
||||||
|
url: config.url,
|
||||||
|
realm: config.realm,
|
||||||
|
clientId: config.clientId,
|
||||||
|
}
|
||||||
|
|
||||||
|
const keycloakOptions: KeycloakInitOptions = {
|
||||||
|
scope: config.scope,
|
||||||
|
checkLoginIframe: config.checkLoginIframe,
|
||||||
|
redirectUri: config.redirectUri,
|
||||||
|
// onLoad: 'login-required',
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// kc.updateToken
|
||||||
|
|
||||||
|
// async function newKeycloak() {
|
||||||
|
// return new Keycloak(configStore.getKeyCloakConfig());
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
const kc = new Keycloak(keycloakConfig);
|
||||||
|
|
||||||
|
kc.init(keycloakOptions).then((auth) => {
|
||||||
|
console.log(`User is ${auth ? 'authenticated' : 'not authenticated'}`);
|
||||||
|
|
||||||
|
kc.onTokenExpired = () => {
|
||||||
|
kc.updateToken(5).then(auth => {
|
||||||
|
console.log(auth);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// save kc to local storage
|
||||||
|
localStorage.setItem('keycloak', JSON.stringify(kc));
|
||||||
|
|
||||||
|
export default kc
|
24
src/plugins/rpc.ts
Normal file
24
src/plugins/rpc.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
import { GrpcWebFetchTransport } from "@protobuf-ts/grpcweb-transport";
|
||||||
|
import keycloak from "@/plugins/keycloak"
|
||||||
|
import { DocumentServiceClient } from "@/proto/document/document.client";
|
||||||
|
import { LibraryServiceClient } from "@/proto/library/library.client";
|
||||||
|
import config from "@/plugins/config"
|
||||||
|
|
||||||
|
let transport = new GrpcWebFetchTransport({
|
||||||
|
baseUrl: config.rpc_base_url,
|
||||||
|
format: "text",
|
||||||
|
meta: {
|
||||||
|
"Authorization": "Bearer " + keycloak.idToken,
|
||||||
|
},
|
||||||
|
timeout: 100 * 1000,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let libraryServiceClient = new LibraryServiceClient(transport)
|
||||||
|
let documentClient = new DocumentServiceClient(transport)
|
||||||
|
|
||||||
|
export {
|
||||||
|
libraryServiceClient,
|
||||||
|
documentClient
|
||||||
|
}
|
@ -1,14 +1,15 @@
|
|||||||
// Composables
|
// Composables
|
||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import { useUserStore } from "@/store/user";
|
|
||||||
import { useConfigStore } from "@/store/config";
|
import { useConfigStore } from "@/store/config";
|
||||||
|
import keycloak from "@/plugins/keycloak"
|
||||||
|
import { useLoginUrlStore } from "@/store/login_url";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
name: "home",
|
name: "home",
|
||||||
meta: {
|
meta: {
|
||||||
auth: true,
|
auth: false,
|
||||||
},
|
},
|
||||||
// route level code-splitting
|
// route level code-splitting
|
||||||
// this generates a separate chunk (Home-[hash].js) for this route
|
// this generates a separate chunk (Home-[hash].js) for this route
|
||||||
@ -23,6 +24,9 @@ const routes = [
|
|||||||
{
|
{
|
||||||
path: "/libraries",
|
path: "/libraries",
|
||||||
name: "libraries",
|
name: "libraries",
|
||||||
|
meta: {
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
component: () => import("@/views/libraries/List.vue"),
|
component: () => import("@/views/libraries/List.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -59,12 +63,30 @@ const router = createRouter({
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.beforeEach((to, from) => {
|
router.beforeEach((to, from) => {
|
||||||
|
|
||||||
// get route name
|
// get route name
|
||||||
console.log(from.name, from.fullPath)
|
console.log(from.name, from.fullPath)
|
||||||
|
|
||||||
const userStore = useUserStore();
|
|
||||||
const configStore = useConfigStore();
|
const configStore = useConfigStore();
|
||||||
|
const loginUrl = useLoginUrlStore();
|
||||||
|
|
||||||
|
if (to.name != "login") {
|
||||||
|
console.log("last visit:" + to.fullPath)
|
||||||
|
// 设置最后访问 url
|
||||||
|
loginUrl.setLastVisitUrl(to.fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 如果来自登录的 url,则跳转到最后访问的 url
|
||||||
|
// if (from.name === "login") {
|
||||||
|
// const last_visit = loginUrl.getLastVisitUrl()
|
||||||
|
|
||||||
|
// if (last_visit) {
|
||||||
|
// console.log("跳转:" + last_visit)
|
||||||
|
// // window.location.href = last_visit
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if (to.matched.length === 0) {
|
// if (to.matched.length === 0) {
|
||||||
// return router.push({ name: "errors.404" });
|
// return router.push({ name: "errors.404" });
|
||||||
@ -76,9 +98,8 @@ router.beforeEach((to, from) => {
|
|||||||
document.title = configStore.getAppName();
|
document.title = configStore.getAppName();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to.meta.auth == true) {
|
if (to.meta.auth) {
|
||||||
// validate login state
|
if (!keycloak.authenticated) {
|
||||||
if (userStore.jwt_token == null) {
|
|
||||||
router.push({ name: "login" });
|
router.push({ name: "login" });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,23 +5,11 @@ export const useConfigStore = defineStore('app', {
|
|||||||
state: () => ({
|
state: () => ({
|
||||||
appName: "资料库",
|
appName: "资料库",
|
||||||
description: "Leaf Library",
|
description: "Leaf Library",
|
||||||
accountServer: "https://oauth.leaflow.cn",
|
|
||||||
apiServer: "https://document-api.leaflow.cn/api",
|
apiServer: "https://document-api.leaflow.cn/api",
|
||||||
// apiServer: "http://localhost:8080/api",
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
getAppName(): string {
|
getAppName(): string {
|
||||||
return this.appName !== null ? this.appName : "Leaf Library"
|
return this.appName !== null ? this.appName : "Leaf Library"
|
||||||
},
|
},
|
||||||
getRefreshUrl(): string {
|
|
||||||
return this.accountServer + "/public/auth_request/refresh"
|
|
||||||
},
|
|
||||||
getLoginUrl(): string {
|
|
||||||
let url = new URL(this.accountServer + "/public/auth_request")
|
|
||||||
url.searchParams.append("description", this.description)
|
|
||||||
// url.searchParams.append("callback_uri", window.location.href)
|
|
||||||
url.searchParams.append("attributes[app]", "todo")
|
|
||||||
return url.toString()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
@ -1,12 +0,0 @@
|
|||||||
import {defineStore} from 'pinia'
|
|
||||||
import axios from "axios";
|
|
||||||
import {useConfigStore} from "./config";
|
|
||||||
|
|
||||||
export const useLibrariesStore = defineStore('libraries', {
|
|
||||||
state: () => ({
|
|
||||||
libraries: [{
|
|
||||||
ID: 0,
|
|
||||||
Name: "",
|
|
||||||
}],
|
|
||||||
}),
|
|
||||||
})
|
|
18
src/store/login_url.ts
Normal file
18
src/store/login_url.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import {defineStore} from 'pinia'
|
||||||
|
|
||||||
|
export const useLoginUrlStore = defineStore('login_url', {
|
||||||
|
persist: true,
|
||||||
|
state: () => ({
|
||||||
|
last_visit_url: null as null | string
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
setLastVisitUrl(url: string) {
|
||||||
|
this.last_visit_url = url
|
||||||
|
},
|
||||||
|
getLastVisitUrl() {
|
||||||
|
return this.last_visit_url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
@ -1,68 +0,0 @@
|
|||||||
import { defineStore } from "pinia";
|
|
||||||
import axios from "axios";
|
|
||||||
import { useConfigStore } from "./config";
|
|
||||||
|
|
||||||
const useUserStore = defineStore("user", {
|
|
||||||
persist: true,
|
|
||||||
state: () => ({
|
|
||||||
refresh_token: null as null | string,
|
|
||||||
jwt_token: null as null | string,
|
|
||||||
expired_at: null as null | Date,
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
isLoggedIn(): boolean {
|
|
||||||
return this.jwt_token !== null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
login(refresh_token: string, jwt_token: string) {
|
|
||||||
this.refresh_token = refresh_token;
|
|
||||||
this.jwt_token = jwt_token;
|
|
||||||
},
|
|
||||||
setExpired(expires_in: number) {
|
|
||||||
// get date(current + seconds)
|
|
||||||
this.expired_at = new Date(Date.now() + expires_in * 1000);
|
|
||||||
},
|
|
||||||
logout() {
|
|
||||||
console.log("logout");
|
|
||||||
this.refresh_token = null;
|
|
||||||
this.jwt_token = null;
|
|
||||||
},
|
|
||||||
refresh() {
|
|
||||||
let config = useConfigStore();
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post(config.getRefreshUrl(), {
|
|
||||||
refresh_token: this.refresh_token,
|
|
||||||
})
|
|
||||||
.then((r) => {
|
|
||||||
this.jwt_token = r.data.token;
|
|
||||||
this.setExpired(r.data.expires_in);
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error(e);
|
|
||||||
this.logout();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
get_token() {
|
|
||||||
return this.jwt_token;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
// check expired
|
|
||||||
const currentDate = new Date();
|
|
||||||
|
|
||||||
const userStore = useUserStore();
|
|
||||||
const expiredAt = new Date(userStore.expired_at || 0);
|
|
||||||
|
|
||||||
// if has expired
|
|
||||||
if (userStore.expired_at !== null && expiredAt < currentDate) {
|
|
||||||
if (userStore.jwt_token !== null && userStore.refresh_token !== null) {
|
|
||||||
userStore.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
export { useUserStore };
|
|
@ -1,123 +1,46 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div class="container">
|
||||||
class="d-flex text-center"
|
<p>请稍等,我们正在让您登录。</p>
|
||||||
style="
|
|
||||||
width: 100%;
|
|
||||||
height: 100vh;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<v-progress-circular
|
|
||||||
indeterminate
|
|
||||||
v-if="status == 0 || status == 3 || status == 1"
|
|
||||||
></v-progress-circular>
|
|
||||||
</div>
|
|
||||||
<div class="mt-5">
|
|
||||||
<div v-if="status == 0">
|
|
||||||
<p>正在请求账户服务器...</p>
|
|
||||||
</div>
|
|
||||||
<div v-if="status == 1">
|
|
||||||
<p>前往授权页面。</p>
|
|
||||||
</div>
|
|
||||||
<div v-if="status == 2">
|
|
||||||
<v-icon color="red">mdi-alert</v-icon>
|
|
||||||
<p>创建 Auth Requests 时出现了问题。</p>
|
|
||||||
|
|
||||||
<v-btn @click="restart" class="mt-3">重试</v-btn>
|
|
||||||
</div>
|
|
||||||
<div v-if="status == 3">
|
|
||||||
<p>正在获取 Token</p>
|
|
||||||
</div>
|
|
||||||
<div v-if="status == 4">
|
|
||||||
<p>验证失败。</p>
|
|
||||||
|
|
||||||
<v-btn @click="restart" class="mt-3">重试</v-btn>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import axios from "axios";
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { useConfigStore } from "@/store/config";
|
|
||||||
import { useUserStore } from "@/store/user";
|
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
import keycloak from "@/plugins/keycloak";
|
||||||
|
import { useLoginUrlStore } from "@/store/login_url";
|
||||||
|
|
||||||
const status = ref(0);
|
const login = async () => {
|
||||||
const configStore = useConfigStore();
|
try {
|
||||||
const userStore = useUserStore();
|
await keycloak.login();
|
||||||
|
|
||||||
console.log(configStore.accountServer);
|
back();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to initialize adapter:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const restart = () => {
|
const urlHash = window.location.hash;
|
||||||
status.value = 0;
|
|
||||||
|
if (!urlHash) {
|
||||||
login();
|
login();
|
||||||
};
|
|
||||||
|
|
||||||
// read the router query para
|
|
||||||
const query = router.currentRoute.value.query;
|
|
||||||
|
|
||||||
const login = () => {
|
|
||||||
// clear url
|
|
||||||
window.history.replaceState(null, "", window.location.pathname);
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post(configStore.accountServer + "/public/auth_request", {
|
|
||||||
description: configStore.appName,
|
|
||||||
callback_uri: window.location.href,
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
if (res.data.url) {
|
|
||||||
status.value = 1;
|
|
||||||
|
|
||||||
window.location.href = res.data.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(status.value)
|
|
||||||
// console.log(res.data);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
status.value = 2;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const validate = () => {
|
|
||||||
status.value = 3;
|
|
||||||
|
|
||||||
axios
|
|
||||||
.get(
|
|
||||||
configStore.accountServer + "/public/auth_request/" + query.auth_request
|
|
||||||
)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.data.refresh_token && res.data.token) {
|
|
||||||
userStore.login(res.data.refresh_token, res.data.token);
|
|
||||||
|
|
||||||
userStore.setExpired(res.data.expires_in);
|
|
||||||
console.log(userStore.expired_at);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
// window.location.href = "/";
|
|
||||||
router.push("/");
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(res.data);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
status.value = 4;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (query.auth_request != null) {
|
|
||||||
validate();
|
|
||||||
} else {
|
} else {
|
||||||
login();
|
back();
|
||||||
|
}
|
||||||
|
|
||||||
|
function back() {
|
||||||
|
const loginUrl = useLoginUrlStore();
|
||||||
|
|
||||||
|
let last_url = loginUrl.getLastVisitUrl();
|
||||||
|
|
||||||
|
if (!last_url) {
|
||||||
|
router.push({
|
||||||
|
path: "/",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("跳转:" + last_url);
|
||||||
|
router.push({
|
||||||
|
path: last_url,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-btn class="mb-3" @click="router.back()">返回</v-btn>
|
|
||||||
|
|
||||||
<h2>新建文档</h2>
|
|
||||||
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<v-text-field
|
|
||||||
v-model="createData.Title"
|
|
||||||
label="文档标题"
|
|
||||||
required
|
|
||||||
hide-details
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<MdEditor :theme="getTheme" v-model="createData.Content" />
|
|
||||||
|
|
||||||
<v-btn class="mt-3" color="primary" @click="createDocument">新建文档</v-btn>
|
|
||||||
|
|
||||||
<v-file-input
|
|
||||||
class="mt-3"
|
|
||||||
:error-messages="errorMsg"
|
|
||||||
label="加载 PDF / DOCX"
|
|
||||||
v-model="file"
|
|
||||||
></v-file-input>
|
|
||||||
|
|
||||||
<v-alert
|
|
||||||
v-show="created"
|
|
||||||
class="mt-3"
|
|
||||||
type="success"
|
|
||||||
title="创建完成"
|
|
||||||
text="您成功创建了一篇文档,稍后我们将开始索引您的文档。在完成后您就可以使用 AI 工具了。"
|
|
||||||
></v-alert>
|
|
||||||
|
|
||||||
<v-snackbar v-model="show_created_failed" vertical>
|
|
||||||
<div class="text-subtitle-1 pb-2">创建失败</div>
|
|
||||||
|
|
||||||
<p>可能出现了一些问题,比如您没有完整填写,或者某一个内容超出了长度。</p>
|
|
||||||
|
|
||||||
<template v-slot:actions>
|
|
||||||
<v-btn color="pink" variant="text" @click="show_created_failed = false">
|
|
||||||
关闭
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
</v-snackbar>
|
|
||||||
|
|
||||||
<v-snackbar v-model="show_title_is_not_filled">
|
|
||||||
<p>您还没有填写标题。</p>
|
|
||||||
|
|
||||||
<template v-slot:actions>
|
|
||||||
<v-btn
|
|
||||||
color="pink"
|
|
||||||
variant="text"
|
|
||||||
@click="show_title_is_not_filled = false"
|
|
||||||
>
|
|
||||||
关闭
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
</v-snackbar>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { MdEditor } from "md-editor-v3";
|
|
||||||
import "md-editor-v3/lib/style.css";
|
|
||||||
import router from "@/router/index";
|
|
||||||
import { document } from "@/plugins/api";
|
|
||||||
import getTheme from "@/plugins/getTheme";
|
|
||||||
import { watch } from "vue";
|
|
||||||
import { getDocument } from "pdfjs-dist";
|
|
||||||
import "pdfjs-dist/build/pdf.worker.mjs";
|
|
||||||
import { convertToHtml } from "mammoth/mammoth.browser";
|
|
||||||
import html2markdown from "@notable/html2markdown";
|
|
||||||
|
|
||||||
// 错误提示
|
|
||||||
const errorMsg = ref("");
|
|
||||||
|
|
||||||
const created = ref(false);
|
|
||||||
|
|
||||||
const libraryIdInt = parseInt(router.currentRoute.value.params.LibraryId);
|
|
||||||
|
|
||||||
const createData = ref({
|
|
||||||
Title: "",
|
|
||||||
Content: "# Markdown 支持",
|
|
||||||
});
|
|
||||||
|
|
||||||
const show_created_failed = ref(false);
|
|
||||||
const show_title_is_not_filled = ref(false);
|
|
||||||
|
|
||||||
function createDocument() {
|
|
||||||
if (createData.value.Title == "") {
|
|
||||||
show_title_is_not_filled.value = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
document
|
|
||||||
.libraryLibraryIdDocumentsPost(
|
|
||||||
libraryIdInt,
|
|
||||||
{
|
|
||||||
Title: createData.value.Title,
|
|
||||||
Content: createData.value.Content,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((r) => {
|
|
||||||
console.log(r);
|
|
||||||
|
|
||||||
created.value = true;
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error(e);
|
|
||||||
show_created_failed.value = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const file = ref([]);
|
|
||||||
|
|
||||||
watch(file, (newVal) => {
|
|
||||||
console.log(newVal[0]);
|
|
||||||
|
|
||||||
if (newVal.length == 0) {
|
|
||||||
errorMsg.value = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get file content
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.readAsArrayBuffer(newVal[0]);
|
|
||||||
reader.onload = () => {
|
|
||||||
// 如果不是 pdf 或者 docx
|
|
||||||
if (newVal[0].type == "application/pdf") {
|
|
||||||
const typedarray = new Uint8Array(reader.result);
|
|
||||||
|
|
||||||
getDocument(typedarray).promise.then(
|
|
||||||
function (pdf) {
|
|
||||||
// 获取PDF文档中所有页面的文本内容
|
|
||||||
const pagesPromises = [];
|
|
||||||
for (let i = 0; i < pdf.numPages; i++) {
|
|
||||||
// Required to prevent that i is always the total of pages
|
|
||||||
((pageNumber) => {
|
|
||||||
pagesPromises.push(getPdfPageText(pageNumber, pdf));
|
|
||||||
})(i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all(pagesPromises).then(function (pagesText) {
|
|
||||||
// Display text of all the pages in the console
|
|
||||||
// console.log(pagesText); // 或者处理文本内容
|
|
||||||
|
|
||||||
// fill to createData
|
|
||||||
createData.value.Content = pagesText.join("\n\n");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else if (
|
|
||||||
newVal[0].type ==
|
|
||||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
||||||
) {
|
|
||||||
convertToHtml({ arrayBuffer: reader.result }).then(function (
|
|
||||||
resultObject
|
|
||||||
) {
|
|
||||||
let html = resultObject.value; // The generated HTML
|
|
||||||
let messages = resultObject.messages; // Any messages, such as warnings during conversion
|
|
||||||
|
|
||||||
createData.value.Content = html2markdown(html);
|
|
||||||
|
|
||||||
if (createData.value.Title == "") {
|
|
||||||
// get first line of Content
|
|
||||||
|
|
||||||
const firstLine = createData.value.Content.split("\n")[0] ?? "";
|
|
||||||
|
|
||||||
if (firstLine) {
|
|
||||||
createData.value.Title = firstLine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(html);
|
|
||||||
console.warn(messages);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
errorMsg.value = "您只能选择 DPF 或者 DOCX 文件。";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
function getPdfPageText(pageNum, PDFDocumentInstance) {
|
|
||||||
// 返回一个Promise,该Promise解决为页面文本内容
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
PDFDocumentInstance.getPage(pageNum).then(function (pdfPage) {
|
|
||||||
// 返回页面文本内容
|
|
||||||
pdfPage.getTextContent().then(function (textContent) {
|
|
||||||
let textItems = textContent.items;
|
|
||||||
let finalString = "";
|
|
||||||
|
|
||||||
// Concatenate the string of the item to the final string
|
|
||||||
for (let i = 0; i < textItems.length; i++) {
|
|
||||||
let item = textItems[i];
|
|
||||||
finalString += item.str + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Solve promise with the text content of the page
|
|
||||||
resolve(finalString);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,112 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-btn class="mb-3" @click="router.back()">返回</v-btn>
|
|
||||||
|
|
||||||
<div v-if="loading">
|
|
||||||
<LoadingComponent> </LoadingComponent>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<h2>编辑: {{ docu.Title }}</h2>
|
|
||||||
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<v-text-field
|
|
||||||
v-model="docu.Title"
|
|
||||||
label="文档标题"
|
|
||||||
required
|
|
||||||
hide-details
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<MdEditor :theme="getTheme" v-model="docu.Content" />
|
|
||||||
|
|
||||||
<v-btn class="mt-3" color="primary" @click="updateDocument">更新文档</v-btn>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<v-snackbar v-model="show_created_failed" vertical>
|
|
||||||
<div class="text-subtitle-1 pb-2">更新失败</div>
|
|
||||||
|
|
||||||
<p>可能出现了一些问题,比如您没有完整填写,或者某一个内容超出了长度。</p>
|
|
||||||
|
|
||||||
<template v-slot:actions>
|
|
||||||
<v-btn color="pink" variant="text" @click="show_created_failed = false">
|
|
||||||
关闭
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
</v-snackbar>
|
|
||||||
|
|
||||||
<v-snackbar v-model="show_title_is_not_filled">
|
|
||||||
<p>您还没有填写标题。</p>
|
|
||||||
|
|
||||||
<template v-slot:actions>
|
|
||||||
<v-btn
|
|
||||||
color="pink"
|
|
||||||
variant="text"
|
|
||||||
@click="show_title_is_not_filled = false"
|
|
||||||
>
|
|
||||||
关闭
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
</v-snackbar>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { MdEditor } from "md-editor-v3";
|
|
||||||
import "md-editor-v3/lib/style.css";
|
|
||||||
import router from "@/router/index";
|
|
||||||
import { document } from "@/plugins/api";
|
|
||||||
import getTheme from "@/plugins/getTheme";
|
|
||||||
import LoadingComponent from "@/components/Loading.vue";
|
|
||||||
|
|
||||||
const loading = ref(true);
|
|
||||||
const libraryIdInt = parseInt(router.currentRoute.value.params.LibraryId);
|
|
||||||
const documentIdInt = parseInt(router.currentRoute.value.params.DocumentId);
|
|
||||||
|
|
||||||
const docu = ref({
|
|
||||||
Title: "",
|
|
||||||
Content: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
document
|
|
||||||
.libraryLibraryIdDocumentDocumentIdGet(libraryIdInt, documentIdInt)
|
|
||||||
.then((r) => {
|
|
||||||
docu.value = r.data;
|
|
||||||
|
|
||||||
console.log(r.data);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
const show_created_failed = ref(false);
|
|
||||||
const show_title_is_not_filled = ref(false);
|
|
||||||
|
|
||||||
function goto_document() {
|
|
||||||
router.push({
|
|
||||||
name: "library.documents.view",
|
|
||||||
params: {
|
|
||||||
DocumentId: documentIdInt,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateDocument() {
|
|
||||||
if (docu.value.Title == "") {
|
|
||||||
show_title_is_not_filled.value = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
document
|
|
||||||
.libraryLibraryIdDocumentDocumentIdPut(
|
|
||||||
libraryIdInt,
|
|
||||||
documentIdInt,
|
|
||||||
docu.value.Title,
|
|
||||||
docu.value.Content
|
|
||||||
)
|
|
||||||
.then((r) => {
|
|
||||||
goto_document()
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
show_created_failed.value = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,133 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="loading">
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="12" md="4" xl="2" v-for="n in 6" :key="n">
|
|
||||||
<v-skeleton-loader
|
|
||||||
v-for="n in 2"
|
|
||||||
:key="n"
|
|
||||||
class="mx-auto border mt-3"
|
|
||||||
max-width="300"
|
|
||||||
type="article,actions"
|
|
||||||
:elevation="24"
|
|
||||||
></v-skeleton-loader>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<div class="mb-3">
|
|
||||||
<v-btn @click="goto_create_document">创建</v-btn>
|
|
||||||
<v-btn class="ml-2" @click="goto_query_library">查询</v-btn>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<v-row>
|
|
||||||
<v-col
|
|
||||||
cols="12"
|
|
||||||
md="4"
|
|
||||||
xl="2"
|
|
||||||
v-for="document in documents.Data"
|
|
||||||
:key="document.id"
|
|
||||||
>
|
|
||||||
<v-card>
|
|
||||||
<v-card-title>{{ document.Title }}</v-card-title>
|
|
||||||
<v-card-subtitle>{{
|
|
||||||
document.Chunked ? "分块的文档" : "还没有处理"
|
|
||||||
}}</v-card-subtitle>
|
|
||||||
<v-card-subtitle>
|
|
||||||
{{ new Date(document.CreatedAt).toLocaleString() }}
|
|
||||||
</v-card-subtitle>
|
|
||||||
<v-card-text>{{ document.content }}</v-card-text>
|
|
||||||
<v-card-actions>
|
|
||||||
<v-btn text color="primary" @click="goto_document(document.ID)"
|
|
||||||
>预览</v-btn
|
|
||||||
>
|
|
||||||
<v-btn text color="secondary">编辑</v-btn>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</div>
|
|
||||||
<div v-if="documents.Total == 0" class="mt-5">
|
|
||||||
<v-alert text="看样子你还没有创建任何文档。"></v-alert>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center">
|
|
||||||
<v-container>
|
|
||||||
<v-row justify="center">
|
|
||||||
<v-col cols="8">
|
|
||||||
<v-container class="max-width">
|
|
||||||
<v-pagination
|
|
||||||
v-model="page"
|
|
||||||
class="my-4"
|
|
||||||
:length="documents.Total"
|
|
||||||
:disabled="loading"
|
|
||||||
@update:model-value="load"
|
|
||||||
></v-pagination>
|
|
||||||
</v-container>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-container>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { document } from "@/plugins/api";
|
|
||||||
import router from "@/router";
|
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
const libraryId = router.currentRoute.value.params.LibraryId;
|
|
||||||
const page = ref(1);
|
|
||||||
const documents = ref({});
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
loading.value = true;
|
|
||||||
|
|
||||||
document
|
|
||||||
.libraryLibraryIdDocumentsGet(page.value, libraryId)
|
|
||||||
.then((r) => {
|
|
||||||
documents.value = r.data;
|
|
||||||
|
|
||||||
|
|
||||||
console.log(page.value)
|
|
||||||
if (page.value == 1) {
|
|
||||||
if (r.data.Data.length == 1) {
|
|
||||||
goto_document(r.data.Data[0].ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
load();
|
|
||||||
console.log(libraryId);
|
|
||||||
|
|
||||||
function goto_create_document() {
|
|
||||||
router.push({
|
|
||||||
name: "library.documents.create",
|
|
||||||
params: {
|
|
||||||
LibraryId: libraryId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function goto_document(documentId) {
|
|
||||||
router.push({
|
|
||||||
name: "library.documents.view",
|
|
||||||
params: {
|
|
||||||
DocumentId: documentId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function goto_query_library() {
|
|
||||||
router.push({
|
|
||||||
name: "library.query",
|
|
||||||
params: {
|
|
||||||
LibraryId: libraryId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,113 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import router from "@/router";
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { document } from "@/plugins/api";
|
|
||||||
import { MdPreview } from "md-editor-v3";
|
|
||||||
import LoadingComponent from "@/components/Loading.vue";
|
|
||||||
import getTheme from "@/plugins/getTheme";
|
|
||||||
|
|
||||||
const libraryId = parseInt(router.currentRoute.value.params.LibraryId);
|
|
||||||
const documentId = parseInt(router.currentRoute.value.params.DocumentId);
|
|
||||||
const loading = ref(true);
|
|
||||||
|
|
||||||
const docu = ref({
|
|
||||||
Title: "",
|
|
||||||
Content: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const status = ref({
|
|
||||||
Total: 0,
|
|
||||||
Chunked: 0,
|
|
||||||
Completed: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
document
|
|
||||||
.libraryLibraryIdDocumentDocumentIdGet(libraryId, documentId)
|
|
||||||
.then((r) => {
|
|
||||||
docu.value = r.data;
|
|
||||||
|
|
||||||
console.log(r.data);
|
|
||||||
|
|
||||||
document
|
|
||||||
.libraryLibraryIdDocumentDocumentIdChunksGet(libraryId, documentId)
|
|
||||||
.then((r) => {
|
|
||||||
status.value.Total = r.data.Total;
|
|
||||||
status.value.Chunked = r.data.Chunked;
|
|
||||||
status.value.Completed = r.data.Completed;
|
|
||||||
|
|
||||||
console.log(status.value);
|
|
||||||
|
|
||||||
// calc percent
|
|
||||||
if (status.value.Completed !== null) {
|
|
||||||
if (status.value.Completed) {
|
|
||||||
status.value.Chunked = status.value.Total;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
"percent: " + (status.value.Chunked / status.value.Total) * 100
|
|
||||||
);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
function goto_create_document() {
|
|
||||||
router.push({
|
|
||||||
name: "library.documents.create",
|
|
||||||
params: {
|
|
||||||
LibraryId: libraryId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function goto_query_library() {
|
|
||||||
router.push({
|
|
||||||
name: "library.query",
|
|
||||||
params: {
|
|
||||||
LibraryId: libraryId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function goto_edit_document() {
|
|
||||||
router.push({
|
|
||||||
name: "library.documents.edit",
|
|
||||||
params: {
|
|
||||||
LibraryId: libraryId,
|
|
||||||
DocumentId: documentId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<v-btn @click="router.back(0)">返回</v-btn>
|
|
||||||
<v-btn class="ml-2" @click="goto_create_document">新建文档</v-btn>
|
|
||||||
<v-btn class="ml-2" @click="goto_edit_document">修改文档</v-btn>
|
|
||||||
<v-btn class="ml-2" @click="goto_query_library">查询</v-btn>
|
|
||||||
<v-tooltip :text="status.Completed ? '文档处理完成' : '正在处理 ' + status.Chunked + ' 于 ' + status.Total">
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-progress-circular
|
|
||||||
v-bind="props"
|
|
||||||
class="ml-2"
|
|
||||||
:indeterminate="status.Completed == null"
|
|
||||||
:model-value="(status.Chunked / status.Total) * 100"
|
|
||||||
></v-progress-circular>
|
|
||||||
</template>
|
|
||||||
</v-tooltip>
|
|
||||||
|
|
||||||
<!-- <v-progress-circular class="ml-2" v-else indeterminate></v-progress-circular> -->
|
|
||||||
|
|
||||||
<div v-if="loading">
|
|
||||||
<LoadingComponent> </LoadingComponent>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<h2>{{ docu.Title }}</h2>
|
|
||||||
|
|
||||||
<MdPreview class="mt-3" :theme="getTheme" :modelValue="docu.Content" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -1,125 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<LoadingComponent v-if="loading"> </LoadingComponent>
|
<p>资料库</p>
|
||||||
<div v-else>
|
|
||||||
<h1>资料库</h1>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
@click="selectAll"
|
|
||||||
:color="selected_ids.length > 0 ? 'primary' : ''"
|
|
||||||
>全选</v-btn
|
|
||||||
>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
class="ml-2"
|
|
||||||
:disabled="selected_ids.length === 0"
|
|
||||||
:loading="is_deleting"
|
|
||||||
>删除所选
|
|
||||||
|
|
||||||
<v-dialog v-model="show_dialog" activator="parent" width="auto">
|
|
||||||
<v-card>
|
|
||||||
<v-card-text
|
|
||||||
v-text="is_deleting ? '正在为你准备新项目。' : '确认删除所选项?'"
|
|
||||||
></v-card-text>
|
|
||||||
<v-card-actions>
|
|
||||||
<v-btn
|
|
||||||
color="primary"
|
|
||||||
@click="deleteSelected"
|
|
||||||
:loading="is_deleting"
|
|
||||||
>确认删除</v-btn
|
|
||||||
>
|
|
||||||
<v-btn @click="show_dialog = false">取消</v-btn>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-dialog>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-btn :loading="creatingLibrary" class="ml-2"
|
|
||||||
>新建资料库
|
|
||||||
|
|
||||||
<v-dialog
|
|
||||||
v-model="showCreateLibraryDialog"
|
|
||||||
activator="parent"
|
|
||||||
width="auto"
|
|
||||||
>
|
|
||||||
<v-card>
|
|
||||||
<v-text-field
|
|
||||||
v-model="newLibraryName"
|
|
||||||
label="资料库名称"
|
|
||||||
required
|
|
||||||
hide-details
|
|
||||||
></v-text-field>
|
|
||||||
|
|
||||||
<v-card-actions>
|
|
||||||
<v-btn @click="showCreateLibraryDialog = false">取消</v-btn>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
color="primary"
|
|
||||||
@click="newLibrary"
|
|
||||||
:loading="creatingLibrary"
|
|
||||||
>新建</v-btn
|
|
||||||
>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-dialog>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-card class="mt-3">
|
|
||||||
<v-list>
|
|
||||||
<v-list-item
|
|
||||||
v-for="item in libraries.Data"
|
|
||||||
:key="item.ID"
|
|
||||||
@click.stop="goto(item.ID)"
|
|
||||||
>
|
|
||||||
<template v-slot:prepend="{ isActive }">
|
|
||||||
<v-list-item-action start>
|
|
||||||
<v-checkbox-btn
|
|
||||||
:model-value="isSelected(item.ID)"
|
|
||||||
@click.stop="toggleSelection(item.ID)"
|
|
||||||
></v-checkbox-btn>
|
|
||||||
</v-list-item-action>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:append="{ isActive }">
|
|
||||||
<v-list-item-action end>
|
|
||||||
<v-btn rounded="xl" @click.stop="console.log(isActive)">
|
|
||||||
<v-icon>mdi-check</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</v-list-item-action>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<v-list-item-title>{{ item.Name }}</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center">
|
|
||||||
<v-container>
|
|
||||||
<v-row justify="center">
|
|
||||||
<v-col cols="8">
|
|
||||||
<v-container class="max-width">
|
|
||||||
<v-pagination
|
|
||||||
v-model="page"
|
|
||||||
class="my-4"
|
|
||||||
:length="libraries.Total"
|
|
||||||
:disabled="loading"
|
|
||||||
@update:model-value="load"
|
|
||||||
></v-pagination>
|
|
||||||
</v-container>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-container>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup >
|
<script setup >
|
||||||
import { library } from "@/plugins/api";
|
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import LoadingComponent from "@/components/Loading.vue";
|
import LoadingComponent from "@/components/Loading.vue";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
|
||||||
|
import * as libraryProto from "@/proto/library/library";
|
||||||
|
import * as documentProto from "@/proto/document/document";
|
||||||
|
import keycloak from "@/plugins/keycloak"
|
||||||
|
import {libraryServiceClient} from "@/plugins/rpc"
|
||||||
|
|
||||||
|
let listLibrary = {
|
||||||
|
page: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
libraryServiceClient.listLibraries(listLibrary).then(res => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
@ -128,121 +33,4 @@ const selected_ids = ref([]);
|
|||||||
const is_deleting = ref(false);
|
const is_deleting = ref(false);
|
||||||
const show_dialog = ref(false);
|
const show_dialog = ref(false);
|
||||||
|
|
||||||
const load = (show_load = true) => {
|
|
||||||
if (show_load) {
|
|
||||||
loading.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
selected_ids.value = [];
|
|
||||||
library
|
|
||||||
.librariesGet(page.value)
|
|
||||||
.then((r) => {
|
|
||||||
libraries.value = r.data;
|
|
||||||
page.value = r.data.Page;
|
|
||||||
console.log(r.data.Data);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
if (show_load) {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
load();
|
|
||||||
|
|
||||||
const goto = (libraryId) => {
|
|
||||||
router.push({
|
|
||||||
name: "library.documents",
|
|
||||||
params: {
|
|
||||||
LibraryId: libraryId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function isSelected(id) {
|
|
||||||
return selected_ids.value.includes(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleSelection(id) {
|
|
||||||
const index = selected_ids.value.indexOf(id);
|
|
||||||
if (index !== -1) {
|
|
||||||
// 如果已经选中,点击后移除
|
|
||||||
selected_ids.value.splice(index, 1);
|
|
||||||
} else {
|
|
||||||
// 如果没有选中,点击后添加
|
|
||||||
selected_ids.value.push(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects all items if none are selected, otherwise clears the selection.
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
function selectAll() {
|
|
||||||
if (selected_ids.value.length > 0) {
|
|
||||||
selected_ids.value = [];
|
|
||||||
} else {
|
|
||||||
const data = libraries.value.Data;
|
|
||||||
if (data.length > 0) {
|
|
||||||
data.forEach((item) => selected_ids.value.push(item.ID));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteSelected() {
|
|
||||||
if (selected_ids.value.length > 0) {
|
|
||||||
is_deleting.value = true;
|
|
||||||
selected_ids.value.forEach((item) => {
|
|
||||||
library.libraryLibraryIdDelete(item).then((r) => {
|
|
||||||
console.log("Library deleted: " + item);
|
|
||||||
|
|
||||||
// remove
|
|
||||||
libraries.value.Data = libraries.value.Data.filter(
|
|
||||||
(i) => i.ID !== item
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
selected_ids.value = [];
|
|
||||||
setTimeout(() => {
|
|
||||||
if (page.value == libraries.value.Page) {
|
|
||||||
page.value = page.value - 1;
|
|
||||||
}
|
|
||||||
if (page.value == 0) {
|
|
||||||
page.value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
load(false);
|
|
||||||
|
|
||||||
is_deleting.value = false;
|
|
||||||
|
|
||||||
show_dialog.value = false;
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const showCreateLibraryDialog = ref(false);
|
|
||||||
const creatingLibrary = ref(false);
|
|
||||||
const newLibraryName = ref("");
|
|
||||||
|
|
||||||
function newLibrary() {
|
|
||||||
if (newLibraryName.value == "") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
creatingLibrary.value = true;
|
|
||||||
|
|
||||||
library
|
|
||||||
.librariesPost(newLibraryName.value)
|
|
||||||
.then(() => {})
|
|
||||||
.finally(() => {
|
|
||||||
showCreateLibraryDialog.value = false;
|
|
||||||
creatingLibrary.value = false;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
load();
|
|
||||||
}, 250);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
18
yarn.lock
18
yarn.lock
@ -1855,6 +1855,11 @@ isexe@^2.0.0:
|
|||||||
resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz"
|
resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz"
|
||||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||||
|
|
||||||
|
js-sha256@^0.11.0:
|
||||||
|
version "0.11.0"
|
||||||
|
resolved "https://mirrors.cloud.tencent.com/npm/js-sha256/-/js-sha256-0.11.0.tgz#256a921d9292f7fe98905face82e367abaca9576"
|
||||||
|
integrity sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q==
|
||||||
|
|
||||||
js-yaml@^4.1.0:
|
js-yaml@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz"
|
resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz"
|
||||||
@ -1887,6 +1892,19 @@ jszip@^3.7.1:
|
|||||||
readable-stream "~2.3.6"
|
readable-stream "~2.3.6"
|
||||||
setimmediate "^1.0.5"
|
setimmediate "^1.0.5"
|
||||||
|
|
||||||
|
jwt-decode@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://mirrors.cloud.tencent.com/npm/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b"
|
||||||
|
integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==
|
||||||
|
|
||||||
|
keycloak-js@^24.0.4:
|
||||||
|
version "24.0.4"
|
||||||
|
resolved "https://mirrors.cloud.tencent.com/npm/keycloak-js/-/keycloak-js-24.0.4.tgz#bfd78af853f0a45bb2f0b4dd24c135aef22cbab6"
|
||||||
|
integrity sha512-eLjG7CzGGgAXh78M76QUJy1R8+QDQvIJXJf6T3bq9VJZ6RXBGZXMsXvII66b83ueYDFa1gi2JojmA31Z23HO0g==
|
||||||
|
dependencies:
|
||||||
|
js-sha256 "^0.11.0"
|
||||||
|
jwt-decode "^4.0.0"
|
||||||
|
|
||||||
keyv@^4.5.3:
|
keyv@^4.5.3:
|
||||||
version "4.5.4"
|
version "4.5.4"
|
||||||
resolved "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz"
|
resolved "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz"
|
||||||
|
Loading…
Reference in New Issue
Block a user