├── .gitignore ├── README.md ├── uni-ai-admin ├── .env.development ├── .env.production ├── .eslintrc.cjs ├── .gitignore ├── .prettierrc.json ├── README.md ├── env.d.ts ├── index.html ├── package-lock.json ├── package.json ├── public │ └── favicon.ico ├── scripts │ └── generate-api.js ├── src │ ├── App.vue │ ├── apis │ │ └── sms │ │ │ └── sms-api.ts │ ├── assets │ │ ├── background.jpg │ │ ├── dashscope-knowledge.png │ │ ├── image-gc.png │ │ ├── logo.jpg │ │ ├── openai-knowledge.png │ │ ├── qianfan-knowledge.png │ │ ├── qianfan.png │ │ ├── qwen.png │ │ ├── qwenvl.png │ │ └── spark.png │ ├── components │ │ ├── base │ │ │ ├── dialog │ │ │ │ ├── dialog-helper.ts │ │ │ │ └── footer-button.vue │ │ │ ├── form │ │ │ │ ├── form-helper.ts │ │ │ │ └── remote-select.vue │ │ │ ├── query │ │ │ │ └── query-helper.ts │ │ │ └── table │ │ │ │ └── table-helper.ts │ │ ├── datetime │ │ │ └── datetime-picker.vue │ │ ├── dict │ │ │ ├── dict-column.vue │ │ │ ├── dict-select.vue │ │ │ └── dict.ts │ │ ├── image │ │ │ └── image-upload.vue │ │ └── key-value │ │ │ ├── key-value-input.vue │ │ │ └── value-input.vue │ ├── layout │ │ ├── components │ │ │ ├── aside-menu.vue │ │ │ ├── router-tag.vue │ │ │ └── router-tags.vue │ │ ├── layout-view.vue │ │ └── store │ │ │ └── tag-store.ts │ ├── main.ts │ ├── router │ │ └── index.ts │ ├── stores │ │ └── home-store.ts │ ├── typings │ │ └── index.d.ts │ ├── utils │ │ ├── api-instance.ts │ │ ├── common.ts │ │ └── request.ts │ └── views │ │ ├── ai │ │ ├── ai-chat │ │ │ ├── ai-chat-view.vue │ │ │ ├── components │ │ │ │ ├── ai-options.vue │ │ │ │ ├── markdown-message.vue │ │ │ │ ├── message-input.vue │ │ │ │ ├── message-row.vue │ │ │ │ ├── session-item.vue │ │ │ │ └── text-loading.vue │ │ │ └── store │ │ │ │ └── ai-chat-store.ts │ │ ├── ai-collection │ │ │ ├── ai-collection-view.vue │ │ │ ├── components │ │ │ │ ├── ai-collection-create-form.vue │ │ │ │ ├── ai-collection-dialog.vue │ │ │ │ ├── ai-collection-query.vue │ │ │ │ ├── ai-collection-table.vue │ │ │ │ └── ai-collection-update-form.vue │ │ │ └── store │ │ │ │ └── ai-collection-store.ts │ │ ├── ai-document │ │ │ ├── ai-document-view.vue │ │ │ ├── components │ │ │ │ ├── ai-document-create-form.vue │ │ │ │ ├── ai-document-dialog.vue │ │ │ │ ├── ai-document-query.vue │ │ │ │ ├── ai-document-table.vue │ │ │ │ └── ai-document-update-form.vue │ │ │ └── store │ │ │ │ └── ai-document-store.ts │ │ ├── ai-factory │ │ │ ├── ai-factory-view.vue │ │ │ ├── components │ │ │ │ ├── ai-factory-create-form.vue │ │ │ │ ├── ai-factory-dialog.vue │ │ │ │ ├── ai-factory-query.vue │ │ │ │ ├── ai-factory-table.vue │ │ │ │ ├── ai-factory-update-form.vue │ │ │ │ └── options │ │ │ │ │ ├── dash-scope-options.vue │ │ │ │ │ ├── kimi-options.vue │ │ │ │ │ ├── open-ai-options.vue │ │ │ │ │ ├── options.vue │ │ │ │ │ ├── qian-fan-options.vue │ │ │ │ │ └── zhi-pu-options.vue │ │ │ └── store │ │ │ │ └── ai-factory-store.ts │ │ ├── ai-message │ │ │ ├── ai-message-view.vue │ │ │ ├── components │ │ │ │ ├── ai-message-create-form.vue │ │ │ │ ├── ai-message-dialog.vue │ │ │ │ ├── ai-message-query.vue │ │ │ │ ├── ai-message-table.vue │ │ │ │ └── ai-message-update-form.vue │ │ │ └── store │ │ │ │ └── ai-message-store.ts │ │ ├── ai-model │ │ │ ├── ai-model-view.vue │ │ │ ├── components │ │ │ │ ├── ai-model-create-form.vue │ │ │ │ ├── ai-model-dialog.vue │ │ │ │ ├── ai-model-query.vue │ │ │ │ ├── ai-model-table.vue │ │ │ │ ├── ai-model-update-form.vue │ │ │ │ ├── chat-options │ │ │ │ │ ├── chat-options.vue │ │ │ │ │ ├── dash-scope-ai-chat-options.vue │ │ │ │ │ ├── kimi-ai-chat-options.vue │ │ │ │ │ ├── open-ai-chat-options.vue │ │ │ │ │ ├── qian-fan-ai-chat-options.vue │ │ │ │ │ └── zhi-pu-ai-chat-options.vue │ │ │ │ ├── embedding-options │ │ │ │ │ ├── dash-scope-embedding-options.vue │ │ │ │ │ ├── embedding-options.vue │ │ │ │ │ └── zhi-pu-embedding-options.vue │ │ │ │ └── image-options │ │ │ │ │ ├── dash-scope-image-options.vue │ │ │ │ │ ├── image-options.vue │ │ │ │ │ ├── open-ai-image-options.vue │ │ │ │ │ └── zhi-pu-ai-image-options.vue │ │ │ └── store │ │ │ │ └── ai-model-store.ts │ │ ├── ai-plugin │ │ │ ├── ai-plugin-view.vue │ │ │ ├── components │ │ │ │ ├── ai-plugin-create-form.vue │ │ │ │ ├── ai-plugin-dialog.vue │ │ │ │ ├── ai-plugin-query.vue │ │ │ │ ├── ai-plugin-table.vue │ │ │ │ └── ai-plugin-update-form.vue │ │ │ └── store │ │ │ │ └── ai-plugin-store.ts │ │ ├── ai-role │ │ │ ├── ai-role-view.vue │ │ │ ├── components │ │ │ │ ├── ai-role-create-form.vue │ │ │ │ ├── ai-role-dialog.vue │ │ │ │ ├── ai-role-query.vue │ │ │ │ ├── ai-role-table.vue │ │ │ │ └── ai-role-update-form.vue │ │ │ └── store │ │ │ │ └── ai-role-store.ts │ │ ├── ai-session │ │ │ ├── ai-session-view.vue │ │ │ ├── components │ │ │ │ ├── ai-session-create-form.vue │ │ │ │ ├── ai-session-dialog.vue │ │ │ │ ├── ai-session-query.vue │ │ │ │ ├── ai-session-table.vue │ │ │ │ └── ai-session-update-form.vue │ │ │ └── store │ │ │ │ └── ai-session-store.ts │ │ └── ai-tag │ │ │ ├── ai-tag-view.vue │ │ │ ├── components │ │ │ ├── ai-tag-create-form.vue │ │ │ ├── ai-tag-dialog.vue │ │ │ ├── ai-tag-query.vue │ │ │ ├── ai-tag-table.vue │ │ │ └── ai-tag-update-form.vue │ │ │ └── store │ │ │ └── ai-tag-store.ts │ │ ├── dict │ │ ├── components │ │ │ ├── dict-create-form.vue │ │ │ ├── dict-dialog.vue │ │ │ ├── dict-query.vue │ │ │ ├── dict-table.vue │ │ │ └── dict-update-form.vue │ │ ├── dict-view.vue │ │ └── store │ │ │ └── dict-store.ts │ │ ├── login │ │ ├── login-view.vue │ │ ├── register-view.vue │ │ └── rest-password-view.vue │ │ ├── menu │ │ ├── components │ │ │ ├── menu-create-form.vue │ │ │ ├── menu-dialog.vue │ │ │ ├── menu-query.vue │ │ │ ├── menu-table.vue │ │ │ ├── menu-tree.vue │ │ │ └── menu-update-form.vue │ │ ├── menu-view.vue │ │ └── store │ │ │ └── menu-store.ts │ │ ├── oss │ │ └── oss-view.vue │ │ ├── role │ │ ├── components │ │ │ ├── role-create-form.vue │ │ │ ├── role-dialog.vue │ │ │ ├── role-query.vue │ │ │ ├── role-table.vue │ │ │ └── role-update-form.vue │ │ ├── role-view.vue │ │ └── store │ │ │ └── role-store.ts │ │ ├── setting │ │ └── setting-view.vue │ │ ├── user │ │ ├── components │ │ │ ├── user-choose-table.vue │ │ │ ├── user-create-form.vue │ │ │ ├── user-dialog.vue │ │ │ ├── user-query.vue │ │ │ ├── user-table.vue │ │ │ └── user-update-form.vue │ │ ├── store │ │ │ └── user-store.ts │ │ └── user-view.vue │ │ └── wallet │ │ ├── wallet-item │ │ ├── components │ │ │ ├── wallet-item-create-form.vue │ │ │ ├── wallet-item-dialog.vue │ │ │ ├── wallet-item-query.vue │ │ │ ├── wallet-item-table.vue │ │ │ └── wallet-item-update-form.vue │ │ ├── store │ │ │ └── wallet-item-store.ts │ │ └── wallet-item-view.vue │ │ ├── wallet-order │ │ ├── components │ │ │ ├── wallet-order-create-form.vue │ │ │ ├── wallet-order-dialog.vue │ │ │ ├── wallet-order-query.vue │ │ │ ├── wallet-order-table.vue │ │ │ └── wallet-order-update-form.vue │ │ ├── store │ │ │ └── wallet-order-store.ts │ │ └── wallet-order-view.vue │ │ ├── wallet-record │ │ ├── components │ │ │ ├── wallet-record-create-form.vue │ │ │ ├── wallet-record-dialog.vue │ │ │ ├── wallet-record-query.vue │ │ │ ├── wallet-record-table.vue │ │ │ └── wallet-record-update-form.vue │ │ ├── store │ │ │ └── wallet-record-store.ts │ │ ├── wallet-record-stats.vue │ │ └── wallet-record-view.vue │ │ └── wallet │ │ ├── components │ │ ├── wallet-create-form.vue │ │ ├── wallet-dialog.vue │ │ ├── wallet-query.vue │ │ ├── wallet-table.vue │ │ └── wallet-update-form.vue │ │ ├── store │ │ └── wallet-store.ts │ │ └── wallet-view.vue ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts └── uni-ai-backend ├── .gitignore ├── common ├── pom.xml └── src │ └── main │ └── java │ └── io │ └── qifan │ └── infrastructure │ └── common │ ├── constants │ ├── BaseEnum.java │ └── ResultCode.java │ ├── exception │ ├── BusinessException.java │ └── SystemException.java │ ├── lombok.config │ ├── model │ ├── PageResult.java │ └── R.java │ └── validation │ ├── CreateGroup.java │ ├── UpdateGroup.java │ └── ValidateGroup.java ├── generator-core ├── pom.xml └── src │ └── main │ └── java │ └── io │ └── qifan │ └── infrastructure │ └── generator │ └── core │ ├── GenAssociationField.java │ ├── GenBooleanField.java │ ├── GenDateTimeField.java │ ├── GenDictField.java │ ├── GenEntity.java │ ├── GenField.java │ ├── GenFileField.java │ ├── GenImageField.java │ ├── GenKeyValueField.java │ ├── GenNumberField.java │ ├── GenTextAreaField.java │ ├── GenTextField.java │ ├── GenValueField.java │ └── ItemType.java ├── generator-processor ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── qifan │ │ └── infrastructure │ │ └── generator │ │ └── processor │ │ ├── QiFanGenerator.java │ │ ├── model │ │ ├── Entity.java │ │ ├── common │ │ │ ├── Field.java │ │ │ ├── FileModel.java │ │ │ ├── ModelElement.java │ │ │ ├── Parameter.java │ │ │ ├── ParameterType.java │ │ │ └── Type.java │ │ ├── controller │ │ │ ├── Controller.java │ │ │ ├── ControllerForAdmin.java │ │ │ └── ControllerForFront.java │ │ ├── dto │ │ │ └── Dto.java │ │ ├── front │ │ │ ├── Details.java │ │ │ ├── FormItem.java │ │ │ ├── ItemField.java │ │ │ ├── Query.java │ │ │ ├── QueryItem.java │ │ │ ├── Router.java │ │ │ ├── Store.java │ │ │ ├── Table.java │ │ │ ├── TableItem.java │ │ │ └── View.java │ │ ├── repository │ │ │ └── Repository.java │ │ └── service │ │ │ └── Service.java │ │ ├── processor │ │ ├── DefaultModelElementProcessorContext.java │ │ ├── EntityCreateProcessor.java │ │ ├── ModelElementProcessor.java │ │ └── RouterCreateProcessor.java │ │ ├── utils │ │ ├── FieldUtils.java │ │ └── TypeUtils.java │ │ └── writer │ │ ├── FreeMarkerModelElementWriter.java │ │ ├── FreeMarkerWritable.java │ │ ├── ModelIncludeDirective.java │ │ ├── ModelWriter.java │ │ └── Writable.java │ └── resources │ └── io │ └── qifan │ └── infrastructure │ └── generator │ └── processor │ └── model │ ├── controller │ ├── Controller.ftl │ ├── ControllerForAdmin.ftl │ └── ControllerForFront.ftl │ ├── dto │ └── Dto.ftl │ ├── front │ ├── Details.ftl │ ├── FormItem.ftl │ ├── Query.ftl │ ├── QueryItem.ftl │ ├── Router.ftl │ ├── Store.ftl │ ├── Table.ftl │ ├── TableItem.ftl │ └── View.ftl │ ├── repository │ └── Repository.ftl │ └── service │ └── Service.ftl ├── pom.xml ├── scripts ├── Dockerfile ├── build.sh ├── database.sql └── docker-compose.yml ├── server ├── pom.xml └── src │ ├── main │ ├── dto │ │ ├── ai │ │ │ ├── AiCollection.dto │ │ │ ├── AiDocument.dto │ │ │ ├── AiFactory.dto │ │ │ ├── AiMessage.dto │ │ │ ├── AiModel.dto │ │ │ ├── AiPlugin.dto │ │ │ ├── AiRole.dto │ │ │ ├── AiSession.dto │ │ │ └── AiTag.dto │ │ ├── dict │ │ │ └── Dict.dto │ │ ├── menu │ │ │ └── Menu.dto │ │ ├── role │ │ │ └── Role.dto │ │ ├── user │ │ │ ├── User.dto │ │ │ └── UserWeChat.dto │ │ └── wallet │ │ │ ├── Wallet.dto │ │ │ ├── WalletItem.dto │ │ │ ├── WalletOrder.dto │ │ │ └── WalletRecord.dto │ ├── java │ │ └── io │ │ │ └── qifan │ │ │ └── server │ │ │ ├── ServerApplication.java │ │ │ ├── ai │ │ │ ├── collection │ │ │ │ ├── controller │ │ │ │ │ ├── AiCollectionForAdminController.java │ │ │ │ │ └── AiCollectionForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ └── AiCollection.java │ │ │ │ ├── repository │ │ │ │ │ └── AiCollectionRepository.java │ │ │ │ └── service │ │ │ │ │ └── AiCollectionService.java │ │ │ ├── document │ │ │ │ ├── controller │ │ │ │ │ ├── AiDocumentForAdminController.java │ │ │ │ │ └── AiDocumentForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ └── AiDocument.java │ │ │ │ ├── repository │ │ │ │ │ └── AiDocumentRepository.java │ │ │ │ └── service │ │ │ │ │ └── AiDocumentService.java │ │ │ ├── factory │ │ │ │ ├── controller │ │ │ │ │ ├── AiFactoryForAdminController.java │ │ │ │ │ └── AiFactoryForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ └── AiFactory.java │ │ │ │ ├── repository │ │ │ │ │ └── AiFactoryRepository.java │ │ │ │ └── service │ │ │ │ │ └── AiFactoryService.java │ │ │ ├── message │ │ │ │ ├── controller │ │ │ │ │ ├── AiMessageForAdminController.java │ │ │ │ │ └── AiMessageForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ ├── AiMessage.java │ │ │ │ │ ├── dto │ │ │ │ │ │ ├── AiMessageView.java │ │ │ │ │ │ └── ChatMessageRequest.java │ │ │ │ │ └── model │ │ │ │ │ │ └── ChatParams.java │ │ │ │ ├── repository │ │ │ │ │ └── AiMessageRepository.java │ │ │ │ └── service │ │ │ │ │ ├── chat │ │ │ │ │ └── AiMessageChatService.java │ │ │ │ │ └── image │ │ │ │ │ └── AiMessageImageService.java │ │ │ ├── model │ │ │ │ ├── controller │ │ │ │ │ ├── AiModelForAdminController.java │ │ │ │ │ └── AiModelForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ └── AiModel.java │ │ │ │ ├── repository │ │ │ │ │ └── AiModelRepository.java │ │ │ │ └── service │ │ │ │ │ └── AiModelService.java │ │ │ ├── plugin │ │ │ │ ├── controller │ │ │ │ │ ├── AiPluginForAdminController.java │ │ │ │ │ └── AiPluginForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ ├── AiPlugin.java │ │ │ │ │ └── model │ │ │ │ │ │ └── Parameter.java │ │ │ │ ├── repository │ │ │ │ │ └── AiPluginRepository.java │ │ │ │ └── service │ │ │ │ │ ├── AiPluginService.java │ │ │ │ │ └── function │ │ │ │ │ ├── FunctionRegistry.java │ │ │ │ │ └── SpringSpELService.java │ │ │ ├── role │ │ │ │ ├── controller │ │ │ │ │ ├── AiRoleForAdminController.java │ │ │ │ │ └── AiRoleForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ └── AiRole.java │ │ │ │ ├── repository │ │ │ │ │ └── AiRoleRepository.java │ │ │ │ └── service │ │ │ │ │ └── AiRoleService.java │ │ │ ├── session │ │ │ │ ├── controller │ │ │ │ │ ├── AiSessionForAdminController.java │ │ │ │ │ └── AiSessionForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ └── AiSession.java │ │ │ │ ├── repository │ │ │ │ │ └── AiSessionRepository.java │ │ │ │ └── service │ │ │ │ │ └── AiSessionService.java │ │ │ ├── tag │ │ │ │ ├── model │ │ │ │ │ ├── entity │ │ │ │ │ │ └── AiModelTagRel.java │ │ │ │ │ └── repository │ │ │ │ │ │ └── AiTagModelRelRepository.java │ │ │ │ └── root │ │ │ │ │ ├── controller │ │ │ │ │ ├── AiTagForAdminController.java │ │ │ │ │ └── AiTagForFrontController.java │ │ │ │ │ ├── entity │ │ │ │ │ └── AiTag.java │ │ │ │ │ ├── repository │ │ │ │ │ └── AiTagRepository.java │ │ │ │ │ └── service │ │ │ │ │ └── AiTagService.java │ │ │ └── uni │ │ │ │ ├── chat │ │ │ │ ├── DashScopeAiChatService.java │ │ │ │ ├── KimiAiChatService.java │ │ │ │ ├── OpenAiChatService.java │ │ │ │ ├── QianFanAiChatService.java │ │ │ │ ├── UniAiChatService.java │ │ │ │ └── ZhiPuAiChatService.java │ │ │ │ ├── embedding │ │ │ │ ├── DashScopeAiEmbeddingService.java │ │ │ │ ├── OpenAiEmbeddingService.java │ │ │ │ ├── QifanAiEmbeddingService.java │ │ │ │ ├── UniAiEmbeddingService.java │ │ │ │ └── ZhiPuAiEmbeddingService.java │ │ │ │ ├── image │ │ │ │ ├── DashScopeAiImageService.java │ │ │ │ ├── OpenAiImageService.java │ │ │ │ ├── UniAiImageService.java │ │ │ │ └── ZhiPuAiImageService.java │ │ │ │ └── vector │ │ │ │ ├── RedisVectorService.java │ │ │ │ └── UniAiVectorService.java │ │ │ ├── dict │ │ │ ├── controller │ │ │ │ └── DictController.java │ │ │ ├── entity │ │ │ │ └── Dict.java │ │ │ ├── model │ │ │ │ ├── DictConstants.java │ │ │ │ └── DictGenContext.java │ │ │ ├── repository │ │ │ │ └── DictRepository.java │ │ │ └── service │ │ │ │ └── DictService.java │ │ │ ├── infrastructure │ │ │ ├── aop │ │ │ │ ├── NotRepeat.java │ │ │ │ └── NotRepeatAspect.java │ │ │ ├── config │ │ │ │ ├── GlobalExceptionAdvice.java │ │ │ │ ├── LocalDateTimeConvert.java │ │ │ │ ├── PageableConvert.java │ │ │ │ ├── RedisConfig.java │ │ │ │ ├── ResponseInterceptor.java │ │ │ │ ├── RoleMenuStpImpl.java │ │ │ │ └── WebConfig.java │ │ │ ├── jimmer │ │ │ │ ├── BaseDateTime.java │ │ │ │ ├── BaseDateTimeDraftInterceptor.java │ │ │ │ ├── BaseEntity.java │ │ │ │ ├── BaseEntityDraftInterceptor.java │ │ │ │ ├── JimmerConfig.java │ │ │ │ └── UUIDIdGenerator.java │ │ │ └── model │ │ │ │ ├── LoginDevice.java │ │ │ │ ├── QueryRequest.java │ │ │ │ └── WxPayPropertiesExtension.java │ │ │ ├── menu │ │ │ ├── controller │ │ │ │ └── MenuController.java │ │ │ ├── entity │ │ │ │ └── Menu.java │ │ │ ├── repository │ │ │ │ └── MenuRepository.java │ │ │ └── service │ │ │ │ └── MenuService.java │ │ │ ├── oss │ │ │ ├── OSSController.java │ │ │ ├── OSSRepository.java │ │ │ ├── OSSSetting.java │ │ │ ├── UniAliYunOSSService.java │ │ │ ├── UniOSSService.java │ │ │ └── UniTencentSSService.java │ │ │ ├── role │ │ │ ├── controller │ │ │ │ └── RoleController.java │ │ │ ├── entity │ │ │ │ ├── Role.java │ │ │ │ └── RoleMenuRel.java │ │ │ ├── repository │ │ │ │ └── RoleRepository.java │ │ │ └── service │ │ │ │ └── RoleService.java │ │ │ ├── setting │ │ │ ├── Setting.java │ │ │ ├── SettingController.java │ │ │ └── SettingRepository.java │ │ │ ├── user │ │ │ ├── root │ │ │ │ ├── controller │ │ │ │ │ ├── UserForAdminController.java │ │ │ │ │ └── UserForFrontController.java │ │ │ │ ├── entity │ │ │ │ │ ├── User.java │ │ │ │ │ └── UserRoleRel.java │ │ │ │ ├── repository │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ └── UserRoleRelRepository.java │ │ │ │ └── service │ │ │ │ │ └── UserService.java │ │ │ └── wechat │ │ │ │ ├── controller │ │ │ │ ├── UserWeChatForAdminController.java │ │ │ │ └── UserWeChatForFrontController.java │ │ │ │ ├── entity │ │ │ │ └── UserWeChat.java │ │ │ │ ├── model │ │ │ │ ├── UserWeChatRegisterInput.java │ │ │ │ └── UserWeChatRegisterInputV2.java │ │ │ │ ├── repository │ │ │ │ └── UserWeChatRepository.java │ │ │ │ └── service │ │ │ │ └── UserWeChatService.java │ │ │ └── wallet │ │ │ ├── item │ │ │ ├── controller │ │ │ │ ├── WalletItemForAdminController.java │ │ │ │ └── WalletItemForFrontController.java │ │ │ ├── entity │ │ │ │ ├── WalletItem.java │ │ │ │ └── dto │ │ │ │ │ └── WalletItemView.java │ │ │ ├── repository │ │ │ │ └── WalletItemRepository.java │ │ │ └── service │ │ │ │ └── WalletItemService.java │ │ │ ├── order │ │ │ ├── controller │ │ │ │ ├── WalletOrderForAdminController.java │ │ │ │ └── WalletOrderForFrontController.java │ │ │ ├── entity │ │ │ │ └── WalletOrder.java │ │ │ ├── repository │ │ │ │ └── WalletOrderRepository.java │ │ │ └── service │ │ │ │ └── WalletOrderService.java │ │ │ ├── record │ │ │ ├── controller │ │ │ │ ├── WalletRecordForAdminController.java │ │ │ │ └── WalletRecordForFrontController.java │ │ │ ├── entity │ │ │ │ └── WalletRecord.java │ │ │ ├── repository │ │ │ │ └── WalletRecordRepository.java │ │ │ └── service │ │ │ │ └── WalletRecordService.java │ │ │ ├── root │ │ │ ├── controller │ │ │ │ ├── WalletForAdminController.java │ │ │ │ └── WalletForFrontController.java │ │ │ ├── entity │ │ │ │ └── Wallet.java │ │ │ ├── repository │ │ │ │ └── WalletRepository.java │ │ │ └── service │ │ │ │ └── WalletService.java │ │ │ └── stats │ │ │ └── WalletRecordStats.java │ └── resources │ │ ├── application-dev.yml │ │ ├── application-prod.yml │ │ ├── application.yml │ │ ├── logback-spring.xml │ │ ├── logback │ │ ├── logback-dev.xml │ │ └── logback-prod.xml │ │ ├── templates │ │ ├── dict-java.ftl │ │ └── dict-ts.ftl │ │ └── wechat │ │ ├── apiclient_cert.pem │ │ └── apiclient_key.pem │ └── test │ └── java │ └── io │ └── qifan │ └── server │ └── CodeGenerator.java ├── spring-boot-starter-oss ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── qifan │ │ └── infrastructure │ │ └── oss │ │ ├── OSSAutoConfiguration.java │ │ ├── OSSProperties.java │ │ ├── aliyun │ │ ├── AliYunOSSProperties.java │ │ └── AliYunOSSService.java │ │ ├── local │ │ ├── LocalOSSProperties.java │ │ └── LocalOSSService.java │ │ ├── service │ │ └── OSSService.java │ │ └── tencent │ │ ├── TencentOSSProperties.java │ │ └── TencentOSSService.java │ └── resources │ └── META-INF │ └── spring │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports ├── spring-boot-starter-security ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── qifan │ │ └── infrastructure │ │ └── security │ │ ├── AuthAutoConfiguration.java │ │ ├── AuthErrorCode.java │ │ ├── SecurityProperties.java │ │ └── WebConfig.java │ └── resources │ └── META-INF │ └── spring │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports ├── spring-boot-starter-sms ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── qifan │ │ └── infrastructure │ │ └── sms │ │ ├── DefaultSmsService.java │ │ ├── SmsAutoConfiguration.java │ │ ├── SmsController.java │ │ ├── SmsProperties.java │ │ ├── SmsService.java │ │ └── aliyun │ │ ├── AliYunSmsProperties.java │ │ └── AliYunSmsService.java │ └── resources │ └── META-INF │ └── spring │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports └── uni-ai-bom └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | target/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | !**/src/main/**/target/ 8 | !**/src/test/**/target/ 9 | ### IntelliJ IDEA ### 10 | .idea/modules.xml 11 | .idea/jarRepositories.xml 12 | .idea/compiler.xml 13 | .idea/libraries/ 14 | *.iws 15 | *.iml 16 | *.ipr 17 | out/ 18 | !**/src/main/**/out/ 19 | !**/src/test/**/out/ 20 | 21 | ### Eclipse ### 22 | .apt_generated 23 | .classpath 24 | .factorypath 25 | .project 26 | .settings 27 | .springBeans 28 | .sts4-cache 29 | bin/ 30 | !**/src/main/**/bin/ 31 | !**/src/test/**/bin/ 32 | 33 | ### NetBeans ### 34 | /nbproject/private/ 35 | /nbbuild/ 36 | /dist/ 37 | /nbdist/ 38 | /.nb-gradle/ 39 | 40 | ### VS Code ### 41 | .vscode/ 42 | 43 | ### Mac OS ### 44 | .DS_Store 45 | /server/src/main/resources/application-private.yml 46 | /server/src/main/resources/wechat-private/ 47 | /.idea/ 48 | /template/ 49 | /log/ 50 | .flattened-pom.xml -------------------------------------------------------------------------------- /uni-ai-admin/.env.development: -------------------------------------------------------------------------------- 1 | VITE_WEBSOCKET_URL=ws://localhost:8877/handshake 2 | VITE_API_PREFIX=/api -------------------------------------------------------------------------------- /uni-ai-admin/.env.production: -------------------------------------------------------------------------------- 1 | VITE_API_PREFIX= -------------------------------------------------------------------------------- /uni-ai-admin/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | extends: [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-typescript', 10 | '@vue/eslint-config-prettier/skip-formatting' 11 | ], 12 | parserOptions: { 13 | ecmaVersion: 'latest' 14 | }, 15 | rules: { 16 | 'prettier/prettier': [ 17 | 'warn', 18 | { 19 | endOfLine: 'auto' 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /uni-ai-admin/.gitignore: -------------------------------------------------------------------------------- 1 | ### IntelliJ IDEA ### 2 | /.idea/ 3 | *.iws 4 | *.iml 5 | *.ipr 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | pnpm-debug.log* 13 | lerna-debug.log* 14 | 15 | node_modules 16 | .DS_Store 17 | dist 18 | dist-ssr 19 | coverage 20 | *.local 21 | 22 | /cypress/videos/ 23 | /cypress/screenshots/ 24 | 25 | # Editor directories and files 26 | .vscode/* 27 | !.vscode/extensions.json 28 | .idea 29 | *.suo 30 | *.ntvs* 31 | *.njsproj 32 | *.sln 33 | *.sw? 34 | 35 | /src/apis/__generated/ 36 | /scripts/ingredient-admin.tar 37 | -------------------------------------------------------------------------------- /uni-ai-admin/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /uni-ai-admin/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare module 'element-plus/dist/locale/zh-cn.mjs' 3 | -------------------------------------------------------------------------------- /uni-ai-admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /uni-ai-admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/public/favicon.ico -------------------------------------------------------------------------------- /uni-ai-admin/src/apis/sms/sms-api.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@/utils/request' 2 | 3 | export const sendSMS = (phone: string) => { 4 | return request({ url: '/sms/send?phone=' + phone, method: 'post' }) 5 | } 6 | -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/background.jpg -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/dashscope-knowledge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/dashscope-knowledge.png -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/image-gc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/image-gc.png -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/logo.jpg -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/openai-knowledge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/openai-knowledge.png -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/qianfan-knowledge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/qianfan-knowledge.png -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/qianfan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/qianfan.png -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/qwen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/qwen.png -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/qwenvl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/qwenvl.png -------------------------------------------------------------------------------- /uni-ai-admin/src/assets/spark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qifan777/uni-ai/2b0b4c8d540a0d967c92f5835b76228c5cdeb830/uni-ai-admin/src/assets/spark.png -------------------------------------------------------------------------------- /uni-ai-admin/src/components/base/dialog/dialog-helper.ts: -------------------------------------------------------------------------------- 1 | import { nextTick, ref } from 'vue' 2 | import type { EditMode } from '@/typings' 3 | 4 | export const useDialogHelper = () => { 5 | const dialogData = ref<{ width: number; title: string; visible: boolean; mode: EditMode }>({ 6 | width: 600, 7 | title: '', 8 | visible: false, 9 | mode: 'CREATE' 10 | }) 11 | const closeDialog = () => { 12 | dialogData.value.visible = false 13 | } 14 | const openDialog = async (mode?: EditMode) => { 15 | if (mode !== undefined) { 16 | dialogData.value.mode = mode 17 | } 18 | await nextTick() 19 | dialogData.value.visible = true 20 | } 21 | return { dialogData, closeDialog, openDialog } 22 | } 23 | -------------------------------------------------------------------------------- /uni-ai-admin/src/components/base/dialog/footer-button.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/components/base/form/form-helper.ts: -------------------------------------------------------------------------------- 1 | import { type Ref, ref } from 'vue' 2 | export const useFormHelper = (formValue: T) => { 3 | const formData = ref({ ...formValue }) as Ref 4 | const restForm = (form?: T) => { 5 | formData.value = { ...formValue, id: form?.id } 6 | } 7 | return { formData, restForm } 8 | } 9 | -------------------------------------------------------------------------------- /uni-ai-admin/src/components/base/query/query-helper.ts: -------------------------------------------------------------------------------- 1 | import { type Ref, ref } from 'vue' 2 | import type { LikeMode } from '@/apis/__generated/model/enums' 3 | 4 | export const useQueryHelper = (initQuery: T) => { 5 | const queryData = ref({ query: { ...initQuery }, likeMode: 'ANYWHERE' }) as Ref<{ 6 | query: T 7 | likeMode: LikeMode 8 | }> 9 | const restQuery = () => { 10 | console.log('重置查询条件') 11 | queryData.value.query = { ...initQuery } 12 | queryData.value.likeMode = 'ANYWHERE' 13 | } 14 | return { queryData, restQuery } 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-admin/src/components/datetime/datetime-picker.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /uni-ai-admin/src/components/dict/dict-column.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /uni-ai-admin/src/components/dict/dict-select.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 39 | 40 | 45 | -------------------------------------------------------------------------------- /uni-ai-admin/src/components/dict/dict.ts: -------------------------------------------------------------------------------- 1 | import type { DictSpec, Page } from '@/apis/__generated/model/static' 2 | import type { DictDto } from '@/apis/__generated/model/dto' 3 | import { api } from '@/utils/api-instance' 4 | 5 | const dictMap: Record>> = {} 6 | export const queryDict = (dictSpec: DictSpec) => { 7 | if (!dictSpec.dictId) return 8 | let res = dictMap[dictSpec.dictId] 9 | if (res) return res 10 | res = api.dictController.query({ 11 | body: { 12 | pageNum: 1, 13 | pageSize: 1000, 14 | likeMode: 'ANYWHERE', 15 | query: dictSpec, 16 | sorts: [{ property: 'dictId', direction: 'ASC' }] 17 | } 18 | }) 19 | dictMap[dictSpec.dictId] = res 20 | return res 21 | } 22 | -------------------------------------------------------------------------------- /uni-ai-admin/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import { createPinia } from 'pinia' 3 | import ElementPlus from 'element-plus' 4 | import 'element-plus/dist/index.css' 5 | import * as ElementPlusIconsVue from '@element-plus/icons-vue' 6 | import App from './App.vue' 7 | import router from './router' 8 | import { MdPreview } from 'md-editor-v3' 9 | import 'md-editor-v3/lib/preview.css' 10 | const app = createApp(App) 11 | 12 | app.use(createPinia()) 13 | app.use(ElementPlus) 14 | app.use(router) 15 | app.component('MdPreview', MdPreview) 16 | for (const [key, component] of Object.entries(ElementPlusIconsVue)) { 17 | app.component(key, component) 18 | } 19 | app.mount('#app') 20 | -------------------------------------------------------------------------------- /uni-ai-admin/src/stores/home-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | import type { MenuDto, UserDto } from '@/apis/__generated/model/dto' 4 | import { api } from '@/utils/api-instance' 5 | import type { MenuTreeDto } from '@/typings' 6 | import { buildMenuTree } from '@/views/menu/store/menu-store' 7 | import { useTagStore } from '@/layout/store/tag-store' 8 | 9 | export const useHomeStore = defineStore('home', () => { 10 | const userInfo = ref() 11 | const menuList = ref([]) 12 | const menuTreeList = ref([]) 13 | const getUserInfo = async () => { 14 | userInfo.value = await api.userForFrontController.getUserInfo() 15 | return userInfo.value 16 | } 17 | const getMenuList = async () => { 18 | if (menuList.value.length > 0) return menuList.value 19 | // 获取用户菜单 20 | const res = await api.userForFrontController.getUserMenus() 21 | // 缓存菜单列表 22 | menuList.value = res 23 | // 递归生成菜单树 24 | menuTreeList.value = buildMenuTree(null, res) 25 | return res 26 | } 27 | const init = async () => { 28 | await getUserInfo() 29 | await getMenuList() 30 | } 31 | const logout = () => { 32 | useTagStore().tags = [] 33 | menuTreeList.value = [] 34 | menuList.value = [] 35 | userInfo.value = undefined 36 | } 37 | return { userInfo, getUserInfo, init, getMenuList, logout, menuList, menuTreeList } 38 | }) 39 | -------------------------------------------------------------------------------- /uni-ai-admin/src/typings/index.d.ts: -------------------------------------------------------------------------------- 1 | import type { MenuDto } from '@/apis/__generated/model/dto' 2 | 3 | export type EditMode = 'CREATE' | 'UPDATE' 4 | export interface Scope { 5 | row: T 6 | $index: number 7 | } 8 | 9 | export interface Result { 10 | code: number 11 | success: boolean 12 | msg: string 13 | result: T 14 | } 15 | export type MenuTreeDto = { 16 | children?: MenuTreeDto[] 17 | } & MenuDto['MenuRepository/SIMPLE_FETCHER'] 18 | -------------------------------------------------------------------------------- /uni-ai-admin/src/utils/api-instance.ts: -------------------------------------------------------------------------------- 1 | import { Api } from '@/apis/__generated' 2 | import { request } from '@/utils/request' 3 | // 导出全局变量`apis` 4 | export const api = new Api(async ({ uri, method, body }) => { 5 | return await request({ url: uri, method, data: body }) 6 | }) 7 | -------------------------------------------------------------------------------- /uni-ai-admin/src/utils/common.ts: -------------------------------------------------------------------------------- 1 | import { ElMessage } from 'element-plus' 2 | import _ from 'lodash' 3 | import type { ValidateFieldsError } from 'async-validator/dist-types' 4 | 5 | export const assertSuccess = async (result: T) => { 6 | return await new Promise((resolve, reject) => { 7 | if (!_.isNil(result)) { 8 | ElMessage.success({ message: '操作成功' }) 9 | resolve(result) 10 | } else { 11 | reject(result) 12 | } 13 | }) 14 | } 15 | export const assertFormValidate = (callback: () => void) => { 16 | return (valid: boolean, fields: ValidateFieldsError | undefined) => { 17 | if (valid) { 18 | callback() 19 | } else { 20 | if (fields) { 21 | const messages: string[] = [] 22 | for (const field in fields) { 23 | fields[field].forEach((error) => { 24 | if (error.message) { 25 | messages.push(error.message) 26 | } 27 | }) 28 | } 29 | ElMessage.error({ message: messages.join('\n') }) 30 | } 31 | } 32 | } 33 | } 34 | 35 | export class Observable { 36 | observers: Array<(t: T) => void> 37 | 38 | constructor() { 39 | this.observers = [] 40 | } 41 | 42 | subscribe(func: (t: T) => void) { 43 | this.observers.push(func) 44 | } 45 | 46 | unsubscribe(func: (t: T) => void) { 47 | this.observers = this.observers.filter((observer) => observer !== func) 48 | } 49 | 50 | notify(data: T) { 51 | this.observers.forEach((observer) => observer(data)) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /uni-ai-admin/src/utils/request.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { ElMessage } from 'element-plus' 3 | import router from '@/router' 4 | 5 | const BASE_URL = import.meta.env.VITE_API_PREFIX 6 | export const request = axios.create({ 7 | baseURL: BASE_URL, 8 | timeout: 600000 9 | }) 10 | request.interceptors.response.use( 11 | (res) => { 12 | return res.data.result 13 | }, 14 | ({ response }) => { 15 | if (response.data.code !== 1) { 16 | ElMessage.warning({ message: response.data.msg }) 17 | } 18 | if (response.data.code === 1001010) { 19 | router.push('/rest-password') 20 | } 21 | if (response.data.code === 1001007 || response.data.code === 1001008) { 22 | console.log(1001007) 23 | router.push('/login') 24 | } else { 25 | /* empty */ 26 | } 27 | return Promise.reject(response.data.result) 28 | } 29 | ) 30 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-chat/components/text-loading.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 51 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-collection/ai-collection-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-collection/components/ai-collection-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-document/ai-document-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-document/components/ai-document-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-document/store/ai-document-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | AiDocumentCreateInput, 7 | AiDocumentSpec, 8 | AiDocumentUpdateInput 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | 13 | export const aiDocumentQueryOptions = async (keyword: string, id: string) => { 14 | return (await api.aiDocumentForFrontController.query({ body: { query: { name: keyword, id } } })) 15 | .content 16 | } 17 | export const useAiDocumentStore = defineStore('aiDocument', () => { 18 | const initQuery: AiDocumentSpec = {} 19 | const initForm: AiDocumentCreateInput & AiDocumentUpdateInput = { 20 | aiCollectionId: '', 21 | content: '', 22 | id: '', 23 | name: '' 24 | } 25 | const tableHelper = useTableHelper( 26 | api.aiDocumentForFrontController.query, 27 | api.aiDocumentForFrontController, 28 | initQuery 29 | ) 30 | const dialogHelper = useDialogHelper() 31 | const queryHelper = useQueryHelper(initQuery) 32 | const updateForm = ref({ ...initForm }) 33 | const createForm = ref({ ...initForm }) 34 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 35 | }) 36 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/ai-factory-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/components/ai-factory-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/components/options/dash-scope-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/components/options/kimi-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/components/options/open-ai-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/components/options/options.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/components/options/qian-fan-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/components/options/zhi-pu-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-factory/store/ai-factory-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | AiFactoryCreateInput, 7 | AiFactorySpec, 8 | AiFactoryUpdateInput 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | 13 | export const aiFactoryQueryOptions = async (_keyword: string, id: string) => { 14 | return (await api.aiFactoryForFrontController.query({ body: { query: { id } } })).content 15 | } 16 | export const useAiFactoryStore = defineStore('aiFactory', () => { 17 | const initQuery: AiFactorySpec = {} 18 | const initForm: AiFactoryCreateInput & AiFactoryUpdateInput = { 19 | id: '', 20 | name: 'DASH_SCOPE', 21 | options: {} 22 | } 23 | const tableHelper = useTableHelper( 24 | api.aiFactoryForFrontController.query, 25 | api.aiFactoryForFrontController, 26 | initQuery 27 | ) 28 | const dialogHelper = useDialogHelper() 29 | const queryHelper = useQueryHelper(initQuery) 30 | const updateForm = ref({ ...initForm }) 31 | const createForm = ref({ ...initForm }) 32 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 33 | }) 34 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-message/ai-message-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-message/components/ai-message-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-message/store/ai-message-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | AiMessageCreateInput, 7 | AiMessageSpec, 8 | AiMessageUpdateInput 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | 13 | export const useAiMessageStore = defineStore('aiMessage', () => { 14 | const initQuery: AiMessageSpec = {} 15 | const initForm: AiMessageCreateInput & AiMessageUpdateInput = { 16 | aiSessionId: '', 17 | content: '', 18 | id: '', 19 | type: 'USER' 20 | } 21 | const tableHelper = useTableHelper( 22 | api.aiMessageForAdminController.query, 23 | api.aiMessageForAdminController, 24 | initQuery 25 | ) 26 | const dialogHelper = useDialogHelper() 27 | const queryHelper = useQueryHelper(initQuery) 28 | const updateForm = ref({ ...initForm }) 29 | const createForm = ref({ ...initForm }) 30 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 31 | }) 32 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/ai-model-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/ai-model-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/chat-options/chat-options.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/chat-options/dash-scope-ai-chat-options.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/chat-options/kimi-ai-chat-options.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/chat-options/open-ai-chat-options.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/chat-options/qian-fan-ai-chat-options.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/chat-options/zhi-pu-ai-chat-options.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/embedding-options/dash-scope-embedding-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/embedding-options/embedding-options.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/embedding-options/zhi-pu-embedding-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/image-options/dash-scope-image-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/image-options/image-options.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/image-options/open-ai-image-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-model/components/image-options/zhi-pu-ai-image-options.vue: -------------------------------------------------------------------------------- 1 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-plugin/ai-plugin-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-plugin/components/ai-plugin-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-plugin/components/ai-plugin-query.vue: -------------------------------------------------------------------------------- 1 | 10 | 34 | 35 | 50 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-plugin/store/ai-plugin-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | AiPluginCreateInput, 7 | AiPluginSpec, 8 | AiPluginUpdateInput 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | 13 | export const aiPluginQueryOptions = async (keyword: string, names: string[]) => { 14 | return (await api.aiPluginForAdminController.query({ body: { query: { name: keyword, names } } })) 15 | .content 16 | } 17 | export const useAiPluginStore = defineStore('aiPlugin', () => { 18 | const initQuery: AiPluginSpec = {} 19 | const initForm: AiPluginCreateInput & AiPluginUpdateInput = { 20 | description: '', 21 | id: '', 22 | name: '', 23 | parameters: { type: '', properties: {}, required: [] } 24 | } 25 | const tableHelper = useTableHelper( 26 | api.aiPluginForAdminController.query, 27 | api.aiPluginForAdminController, 28 | initQuery 29 | ) 30 | const dialogHelper = useDialogHelper() 31 | const queryHelper = useQueryHelper(initQuery) 32 | const updateForm = ref({ ...initForm }) 33 | const createForm = ref({ ...initForm }) 34 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 35 | }) 36 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-role/ai-role-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-role/components/ai-role-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-role/store/ai-role-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | AiRoleCreateInput, 7 | AiRoleSpec, 8 | AiRoleUpdateInput 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | 13 | export const aiRoleQueryOptions = async (keyword: string, id: string) => { 14 | return (await api.aiRoleForAdminController.query({ body: { query: { name: keyword, id } } })) 15 | .content 16 | } 17 | export const useAiRoleStore = defineStore('aiRole', () => { 18 | const initQuery: AiRoleSpec = {} 19 | const initForm: AiRoleCreateInput & AiRoleUpdateInput = { 20 | description: '', 21 | id: '', 22 | name: '', 23 | prompts: [] 24 | } 25 | const tableHelper = useTableHelper( 26 | api.aiRoleForAdminController.query, 27 | api.aiRoleForAdminController, 28 | initQuery 29 | ) 30 | const dialogHelper = useDialogHelper() 31 | const queryHelper = useQueryHelper(initQuery) 32 | const updateForm = ref({ ...initForm }) 33 | const createForm = ref({ ...initForm }) 34 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 35 | }) 36 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-session/ai-session-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-session/components/ai-session-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-session/store/ai-session-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | AiSessionCreateInput, 7 | AiSessionSpec, 8 | AiSessionUpdateInput 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | 13 | export const aiSessionQueryOptions = async (keyword: string, id: string) => { 14 | return (await api.aiSessionForAdminController.query({ body: { query: { name: keyword, id } } })) 15 | .content 16 | } 17 | export const useAiSessionStore = defineStore('aiSession', () => { 18 | const initQuery: AiSessionSpec = {} 19 | const initForm: AiSessionCreateInput & AiSessionUpdateInput = { id: '', name: '' } 20 | const tableHelper = useTableHelper( 21 | api.aiSessionForAdminController.query, 22 | api.aiSessionForAdminController, 23 | initQuery 24 | ) 25 | const dialogHelper = useDialogHelper() 26 | const queryHelper = useQueryHelper(initQuery) 27 | const updateForm = ref({ ...initForm }) 28 | const createForm = ref({ ...initForm }) 29 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 30 | }) 31 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-tag/ai-tag-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-tag/components/ai-tag-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/ai/ai-tag/store/ai-tag-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { AiTagCreateInput, AiTagSpec, AiTagUpdateInput } from '@/apis/__generated/model/static' 6 | import { api } from '@/utils/api-instance' 7 | import { ref } from 'vue' 8 | 9 | export const aiTagQueryOptions = async (keyword: string, id: string) => { 10 | return (await api.aiTagForAdminController.query({ body: { query: { name: keyword, id } } })) 11 | .content 12 | } 13 | export const useAiTagStore = defineStore('aiTag', () => { 14 | const initQuery: AiTagSpec = {} 15 | const initForm: AiTagCreateInput & AiTagUpdateInput = {} 16 | const tableHelper = useTableHelper( 17 | api.aiTagForAdminController.query, 18 | api.aiTagForAdminController, 19 | initQuery 20 | ) 21 | const dialogHelper = useDialogHelper() 22 | const queryHelper = useQueryHelper(initQuery) 23 | const updateForm = ref({ ...initForm }) 24 | const createForm = ref({ ...initForm }) 25 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 26 | }) 27 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/dict/components/dict-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/dict/dict-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/dict/store/dict-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { DictInput, DictSpec } from '@/apis/__generated/model/static' 6 | import { api } from '@/utils/api-instance' 7 | import { ref } from 'vue' 8 | 9 | export const useDictStore = defineStore('dict', () => { 10 | const initQuery: DictSpec = {} 11 | const initForm: DictInput = { 12 | dictEnName: '', 13 | dictId: 0, 14 | dictName: '', 15 | keyEnName: '', 16 | keyId: 0, 17 | keyName: '', 18 | orderNum: 0 19 | } 20 | const tableHelper = useTableHelper(api.dictController.query, api.dictController, initQuery) 21 | const dialogHelper = useDialogHelper() 22 | const queryHelper = useQueryHelper(initQuery) 23 | const updateForm = ref({ ...initForm }) 24 | const createForm = ref({ ...initForm }) 25 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 26 | }) 27 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/menu/components/menu-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/menu/components/menu-tree.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/menu/menu-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/role/components/role-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/role/components/role-query.vue: -------------------------------------------------------------------------------- 1 | 10 | 31 | 32 | 47 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/role/role-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/role/store/role-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { RoleInput, RoleSpec } from '@/apis/__generated/model/static' 6 | import { api } from '@/utils/api-instance' 7 | import { ref } from 'vue' 8 | 9 | export const useRoleStore = defineStore('role', () => { 10 | const initQuery: RoleSpec = {} 11 | const initForm: RoleInput = { menuIds: [], name: '' } 12 | const tableHelper = useTableHelper(api.roleController.query, api.roleController, initQuery) 13 | const dialogHelper = useDialogHelper() 14 | const queryHelper = useQueryHelper(initQuery) 15 | const updateForm = ref({ ...initForm }) 16 | const createForm = ref({ ...initForm }) 17 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 18 | }) 19 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/setting/setting-view.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/user/components/user-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/user/user-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-item/components/wallet-item-dialog.vue: -------------------------------------------------------------------------------- 1 | 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-item/store/wallet-item-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | WalletItemCreateInput, 7 | WalletItemUpdateInput, 8 | WalletItemSpec 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | export const walletItemQueryOptions = async (keyword: string, id: string) => { 13 | return (await api.walletItemForAdminController.query({ body: { query: { name: keyword, id } } })) 14 | .content 15 | } 16 | export const useWalletItemStore = defineStore('walletItem', () => { 17 | const initQuery: WalletItemSpec = {} 18 | const initForm: WalletItemCreateInput & WalletItemUpdateInput = { 19 | amount: 0, 20 | id: '', 21 | name: '', 22 | price: 0 23 | } 24 | const tableHelper = useTableHelper( 25 | api.walletItemForAdminController.query, 26 | api.walletItemForAdminController, 27 | initQuery 28 | ) 29 | const dialogHelper = useDialogHelper() 30 | const queryHelper = useQueryHelper(initQuery) 31 | const updateForm = ref({ ...initForm }) 32 | const createForm = ref({ ...initForm }) 33 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 34 | }) 35 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-item/wallet-item-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-order/components/wallet-order-dialog.vue: -------------------------------------------------------------------------------- 1 | 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-order/store/wallet-order-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | WalletOrderCreateInput, 7 | WalletOrderUpdateInput, 8 | WalletOrderSpec 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | import type { WalletOrderDto } from '@/apis/__generated/model/dto' 13 | export const walletOrderQueryOptions = async (keyword: string, id: string) => { 14 | return (await api.walletOrderForAdminController.query({ body: { query: { name: keyword, id } } })) 15 | .content 16 | } 17 | export const useWalletOrderStore = defineStore('walletOrder', () => { 18 | const initQuery: WalletOrderSpec = {} 19 | const initForm: WalletOrderCreateInput & WalletOrderUpdateInput = {} 20 | const tableHelper = useTableHelper( 21 | api.walletOrderForAdminController.query, 22 | api.walletOrderForAdminController, 23 | initQuery 24 | ) 25 | const dialogHelper = useDialogHelper() 26 | const queryHelper = useQueryHelper(initQuery) 27 | const updateForm = ref({ ...initForm }) 28 | const createForm = ref({ ...initForm }) 29 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 30 | }) 31 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-order/wallet-order-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-record/components/wallet-record-dialog.vue: -------------------------------------------------------------------------------- 1 | 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-record/store/wallet-record-store.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useTableHelper } from '@/components/base/table/table-helper' 3 | import { useDialogHelper } from '@/components/base/dialog/dialog-helper' 4 | import { useQueryHelper } from '@/components/base/query/query-helper' 5 | import type { 6 | WalletRecordCreateInput, 7 | WalletRecordUpdateInput, 8 | WalletRecordSpec 9 | } from '@/apis/__generated/model/static' 10 | import { api } from '@/utils/api-instance' 11 | import { ref } from 'vue' 12 | export const useWalletRecordStore = defineStore('walletRecord', () => { 13 | const initQuery: WalletRecordSpec = {} 14 | const initForm: WalletRecordCreateInput & WalletRecordUpdateInput = { 15 | amount: 0, 16 | description: '', 17 | id: '', 18 | type: 'RECHARGE', 19 | walletId: '' 20 | } 21 | const tableHelper = useTableHelper( 22 | api.walletRecordForAdminController.query, 23 | api.walletRecordForAdminController, 24 | initQuery 25 | ) 26 | const dialogHelper = useDialogHelper() 27 | const queryHelper = useQueryHelper(initQuery) 28 | const updateForm = ref({ ...initForm }) 29 | const createForm = ref({ ...initForm }) 30 | return { ...tableHelper, ...dialogHelper, ...queryHelper, updateForm, createForm, initForm } 31 | }) 32 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet-record/wallet-record-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet/components/wallet-dialog.vue: -------------------------------------------------------------------------------- 1 | 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /uni-ai-admin/src/views/wallet/wallet/wallet-view.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /uni-ai-admin/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "noEmit": true, 8 | "baseUrl": ".", 9 | "paths": { 10 | "@/*": ["./src/*"] 11 | }, 12 | "types": ["element-plus/global"] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /uni-ai-admin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /uni-ai-admin/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node18/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*" 9 | ], 10 | "compilerOptions": { 11 | "composite": true, 12 | "noEmit": true, 13 | "module": "ESNext", 14 | "moduleResolution": "Bundler", 15 | "types": ["node"] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /uni-ai-admin/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import vueJsx from '@vitejs/plugin-vue-jsx' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | plugins: [vue(), vueJsx()], 10 | resolve: { 11 | alias: { 12 | '@': fileURLToPath(new URL('./src', import.meta.url)) 13 | } 14 | }, 15 | server: { 16 | host: '0.0.0.0', 17 | port: 5177, 18 | proxy: { 19 | '/api': { 20 | target: 'http://localhost:8877', 21 | changeOrigin: true, 22 | rewrite: (path) => path.replace(/^\/api/, '') 23 | } 24 | } 25 | } 26 | }) 27 | -------------------------------------------------------------------------------- /uni-ai-backend/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | out/ 16 | !**/src/main/**/out/ 17 | !**/src/test/**/out/ 18 | 19 | ### Eclipse ### 20 | .apt_generated 21 | .classpath 22 | .factorypath 23 | .project 24 | .settings 25 | .springBeans 26 | .sts4-cache 27 | bin/ 28 | !**/src/main/**/bin/ 29 | !**/src/test/**/bin/ 30 | 31 | ### NetBeans ### 32 | /nbproject/private/ 33 | /nbbuild/ 34 | /dist/ 35 | /nbdist/ 36 | /.nb-gradle/ 37 | 38 | ### VS Code ### 39 | .vscode/ 40 | 41 | ### Mac OS ### 42 | .DS_Store 43 | /server/src/main/resources/application-private.yml 44 | /server/src/main/resources/wechat-private/ 45 | /server/src/main/resources/dist/ 46 | /server/target/ 47 | -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/constants/BaseEnum.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.constants; 2 | 3 | 4 | public interface BaseEnum { 5 | 6 | Integer getCode(); 7 | 8 | 9 | String getName(); 10 | } -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/constants/ResultCode.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.constants; 2 | 3 | import java.util.Arrays; 4 | import java.util.Optional; 5 | 6 | public enum ResultCode implements BaseEnum { 7 | Success(1, "操作成功"), 8 | Fail(0, "操作失败"), 9 | NotFindError(10001, "未查询到信息"), 10 | SaveError(10002, "保存信息失败"), 11 | UpdateError(10003, "更新信息失败"), 12 | ValidateError(10004, "数据检验失败"), 13 | StatusHasValid(10005, "状态已经被启用"), 14 | StatusHasInvalid(10006, "状态已经被禁用"), 15 | SystemError(10007, "系统异常"), 16 | BusinessError(10008, "业务异常"), 17 | ParamSetIllegal(10009, "参数设置非法"), 18 | TransferStatusError(10010, "当前状态不正确,请勿重复提交"), 19 | NotGrant(10011, "权限不足"), 20 | Unauthorized(10012, "请登录"); 21 | 22 | /** 23 | * code的取值规则,xx代表模块,xxx代表功能异常 例如:基础模块(10)的查询异常(001) 24 | */ 25 | private final Integer code; 26 | /** 27 | * 异常信息 28 | */ 29 | private final String name; 30 | 31 | ResultCode(Integer code, String name) { 32 | this.code = code; 33 | this.name = name; 34 | } 35 | 36 | public static Optional of(Integer code) { 37 | return Arrays.stream(ResultCode.values()).filter(resultCode -> resultCode.getCode().equals(code)).findFirst(); 38 | } 39 | 40 | @Override 41 | public Integer getCode() { 42 | return this.code; 43 | } 44 | 45 | @Override 46 | public String getName() { 47 | return this.name; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/exception/BusinessException.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.exception; 2 | 3 | import io.qifan.infrastructure.common.constants.BaseEnum; 4 | import io.qifan.infrastructure.common.constants.ResultCode; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class BusinessException extends RuntimeException { 9 | BaseEnum resultCode; 10 | 11 | public BusinessException(String msg) { 12 | super(msg); 13 | this.resultCode = ResultCode.Fail; 14 | } 15 | 16 | public BusinessException(BaseEnum resultCode) { 17 | super(resultCode.getName()); 18 | this.resultCode = resultCode; 19 | } 20 | 21 | public BusinessException(BaseEnum resultCode, String msg) { 22 | super(msg); 23 | this.resultCode = resultCode; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/exception/SystemException.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.exception; 2 | 3 | 4 | public class SystemException extends RuntimeException { 5 | public SystemException(String msg) { 6 | super(msg); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/lombok.config: -------------------------------------------------------------------------------- 1 | lombok.equalsandhashcode.callsuper=call 2 | config.stopbubbling=true -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/model/PageResult.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.model; 2 | 3 | import lombok.Data; 4 | import lombok.experimental.Accessors; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | @Accessors(chain = true) 10 | public class PageResult { 11 | private long totalElements; 12 | private int totalPages; 13 | private int size; 14 | private int number; 15 | private List content; 16 | } 17 | -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/validation/CreateGroup.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.validation; 2 | 3 | public interface CreateGroup extends ValidateGroup { 4 | } 5 | -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/validation/UpdateGroup.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.validation; 2 | 3 | public interface UpdateGroup extends ValidateGroup { 4 | } 5 | -------------------------------------------------------------------------------- /uni-ai-backend/common/src/main/java/io/qifan/infrastructure/common/validation/ValidateGroup.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.common.validation; 2 | 3 | public interface ValidateGroup { 4 | } 5 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenAssociationField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenAssociationField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenBooleanField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenBooleanField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | } 15 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenDateTimeField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenDateTimeField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenDictField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenDictField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | 15 | // 当类型为下拉框时,填写字典编号 16 | String dictEnName() default ""; 17 | } 18 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenEntity.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface GenEntity { 11 | } 12 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenField { 9 | 10 | // 字段注释 11 | String value() default ""; 12 | 13 | // 生成前端表单时选用的组件根据此字段生成。比如:ElInput,ELInputNumber 14 | ItemType type() default ItemType.AUTO; 15 | 16 | // 字段的展示顺序 17 | int order() default 9999; 18 | 19 | // 当类型为下拉框时,填写字典编号 20 | String dictEnName() default ""; 21 | } 22 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenFileField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenFileField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | } 15 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenImageField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenImageField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenKeyValueField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenKeyValueField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | } 15 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenNumberField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenNumberField { 9 | String label() default ""; 10 | 11 | String prop() default ""; 12 | 13 | int order() default 9999; 14 | } 15 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenTextAreaField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenTextAreaField { 9 | // 字段注释 10 | String label() default ""; 11 | 12 | String prop() default ""; 13 | 14 | int order() default 9999; 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenTextField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenTextField { 9 | // 字段注释 10 | String label() default ""; 11 | 12 | String prop() default ""; 13 | 14 | int order() default 9999; 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/GenValueField.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Inherited 7 | @Target({ElementType.METHOD, ElementType.FIELD}) 8 | public @interface GenValueField { 9 | // 字段注释 10 | String label() default ""; 11 | 12 | String prop() default ""; 13 | 14 | int order() default 9999; 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-core/src/main/java/io/qifan/infrastructure/generator/core/ItemType.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.core; 2 | 3 | import java.util.Arrays; 4 | 5 | public enum ItemType { 6 | AUTO(-2, "自动判断"), 7 | SELECTABLE(0, "下拉框"), 8 | INPUT_TEXT(1, "文本输入框"), 9 | INPUT_TEXT_AREA(2, "文本域"), 10 | INPUT_NUMBER(3, "数字输入框"), 11 | PICTURE(4, "图片"), 12 | DATETIME(5, "日期"), 13 | ASSOCIATION_SELECT(6, "关系选择"), 14 | VALUE_INPUT(7, "值列表"), 15 | KEY_VALUE_INPUT(8, "键值对"), 16 | BOOLEAN(9, "布尔值"), 17 | FILE(10, "文件"), 18 | NONE(-1, "不生成"); 19 | 20 | private final Integer code; 21 | private final String name; 22 | 23 | ItemType(Integer code, String name) { 24 | this.code = code; 25 | this.name = name; 26 | } 27 | 28 | public static ItemType nameOf(String name) { 29 | return Arrays.stream(ItemType.values()).filter(type -> type.getName().equals(name)) 30 | .findFirst() 31 | .orElseThrow(() -> new RuntimeException("枚举不存在")); 32 | } 33 | 34 | public static ItemType codeOf(Integer code) { 35 | return Arrays.stream(ItemType.values()).filter(type -> type.getCode().equals(code)) 36 | .findFirst() 37 | .orElseThrow(() -> new RuntimeException("枚举不存在")); 38 | } 39 | 40 | public Integer getCode() { 41 | return this.code; 42 | } 43 | 44 | public String getName() { 45 | return this.name; 46 | } 47 | } -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/Entity.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model; 2 | 3 | 4 | import io.qifan.infrastructure.generator.processor.model.common.ModelElement; 5 | import io.qifan.infrastructure.generator.processor.model.common.Type; 6 | import io.qifan.infrastructure.generator.processor.model.controller.ControllerForAdmin; 7 | import io.qifan.infrastructure.generator.processor.model.controller.ControllerForFront; 8 | import io.qifan.infrastructure.generator.processor.model.dto.Dto; 9 | import io.qifan.infrastructure.generator.processor.model.front.*; 10 | import io.qifan.infrastructure.generator.processor.model.repository.Repository; 11 | import io.qifan.infrastructure.generator.processor.model.service.Service; 12 | import lombok.Builder; 13 | import lombok.Data; 14 | import lombok.EqualsAndHashCode; 15 | 16 | import java.util.Set; 17 | 18 | @EqualsAndHashCode(callSuper = true) 19 | @Data 20 | @Builder 21 | public class Entity extends ModelElement { 22 | 23 | private Type type; 24 | private ControllerForAdmin controllerForAdmin; 25 | private ControllerForFront controllerForFront; 26 | private Dto dto; 27 | private Repository repository; 28 | private Service service; 29 | private View view; 30 | private Query query; 31 | private Store store; 32 | private Table table; 33 | private Details details; 34 | 35 | @Override 36 | public Set getImportTypes() { 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/common/Field.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.common; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.front.ItemField; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | import java.util.Set; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | @Builder 13 | public class Field extends ModelElement { 14 | private Type type; 15 | private String fieldName; 16 | private String description; 17 | private ItemField itemField; 18 | 19 | @Override 20 | public Set getImportTypes() { 21 | return type.getImportTypes(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/common/FileModel.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.common; 2 | 3 | 4 | import io.qifan.infrastructure.generator.processor.writer.FreeMarkerWritable; 5 | 6 | public abstract class FileModel extends FreeMarkerWritable { 7 | public abstract String getFileName(); 8 | } 9 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/common/ModelElement.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.common; 2 | 3 | 4 | import io.qifan.infrastructure.generator.processor.writer.FreeMarkerWritable; 5 | 6 | import java.util.Set; 7 | 8 | public abstract class ModelElement extends FreeMarkerWritable { 9 | public abstract Set getImportTypes(); 10 | } 11 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/common/Parameter.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.common; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import java.util.Set; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | @Builder 12 | public class Parameter extends ModelElement { 13 | private Type type; 14 | private String variableName; 15 | 16 | @Override 17 | public Set getImportTypes() { 18 | return Set.of(type); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/common/ParameterType.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.common; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | @Getter 10 | @Setter 11 | public class ParameterType extends Type { 12 | private ParameterType parameterType; 13 | 14 | public ParameterType(Type type, ParameterType parameterType) { 15 | super(type.getTypeName(), type.getPackagePath()); 16 | this.parameterType = parameterType; 17 | } 18 | 19 | public String getCurrentTypeName() { 20 | return typeName; 21 | } 22 | 23 | @Override 24 | public String getTypeName() { 25 | String typeName = super.typeName; 26 | if (parameterType != null) { 27 | typeName = typeName + "<" + parameterType.getTypeName() + ">"; 28 | } 29 | return typeName; 30 | } 31 | 32 | @Override 33 | public Set getImportTypes() { 34 | HashSet types = new HashSet<>(super.getImportTypes()); 35 | if (parameterType != null) { 36 | types.addAll(parameterType.getImportTypes()); 37 | } 38 | return types; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/common/Type.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.common; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import org.springframework.util.StringUtils; 7 | 8 | import java.util.Set; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | @Builder 13 | public class Type extends ModelElement { 14 | protected String typeName; 15 | protected String packagePath; 16 | 17 | public String getTypePath() { 18 | return packagePath + "." + typeName; 19 | } 20 | 21 | public String getPackageDir() { 22 | return packagePath.replace(".", "/"); 23 | } 24 | 25 | public String getFileName() { 26 | return typeName + ".java"; 27 | } 28 | 29 | public String toFrontNameCase() { 30 | String regex = "([a-z])([A-Z]+)"; 31 | String replacement = "$1-$2"; 32 | return typeName.replaceAll(regex, replacement) 33 | .toLowerCase(); 34 | } 35 | 36 | public String getUncapitalizeTypeName() { 37 | return StringUtils.uncapitalize(typeName); 38 | } 39 | 40 | @Override 41 | public Set getImportTypes() { 42 | return Set.of(this); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/controller/Controller.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.controller; 2 | 3 | 4 | import io.qifan.infrastructure.generator.processor.model.common.ModelElement; 5 | import io.qifan.infrastructure.generator.processor.model.common.Type; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | import java.util.Set; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | @Builder 15 | public class Controller extends ModelElement { 16 | private String sourcePath; 17 | private Type type; 18 | private Type entityType; 19 | 20 | @Override 21 | public Set getImportTypes() { 22 | 23 | return Set.of(entityType); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/controller/ControllerForAdmin.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.controller; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.ModelElement; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.Set; 10 | 11 | @EqualsAndHashCode(callSuper = true) 12 | @Data 13 | @Builder 14 | public class ControllerForAdmin extends ModelElement { 15 | private String sourcePath; 16 | private Type type; 17 | private Type entityType; 18 | 19 | @Override 20 | public Set getImportTypes() { 21 | 22 | return Set.of(entityType); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/controller/ControllerForFront.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.controller; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.ModelElement; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.Set; 10 | 11 | @EqualsAndHashCode(callSuper = true) 12 | @Data 13 | @Builder 14 | public class ControllerForFront extends ModelElement { 15 | private String sourcePath; 16 | private Type type; 17 | private Type entityType; 18 | 19 | @Override 20 | public Set getImportTypes() { 21 | 22 | return Set.of(entityType); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/dto/Dto.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.dto; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.Field; 4 | import io.qifan.infrastructure.generator.processor.model.common.FileModel; 5 | import io.qifan.infrastructure.generator.processor.model.common.Type; 6 | import io.qifan.infrastructure.generator.processor.model.front.ItemField; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.EqualsAndHashCode; 10 | 11 | import java.util.List; 12 | 13 | @EqualsAndHashCode(callSuper = true) 14 | @Data 15 | @Builder 16 | public class Dto extends FileModel { 17 | 18 | private String sourcePath; 19 | private Type type; 20 | private Type entityType; 21 | private List fields; 22 | 23 | @Override 24 | public String getFileName() { 25 | return sourcePath + "/dto/" + entityType.getTypeName() + ".dto"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/Details.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.FileModel; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.List; 10 | 11 | @Builder 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class Details extends FileModel { 15 | private Type entityType; 16 | private List formItems; 17 | 18 | @Override 19 | public String getFileName() { 20 | return "/front/" + entityType.toFrontNameCase() + "/" + entityType.toFrontNameCase() 21 | + "-details-view.vue"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/FormItem.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | @EqualsAndHashCode(callSuper = true) 7 | @Data 8 | public class FormItem extends ItemField { 9 | public FormItem() { 10 | super(); 11 | } 12 | 13 | public FormItem(ItemField itemField) { 14 | super(itemField.getEntityType(), 15 | itemField.getAssociationType(), 16 | itemField.getLabel(), 17 | itemField.getProp(), 18 | itemField.getFieldName(), 19 | itemField.getDictEnName(), 20 | itemField.getItemType(), 21 | itemField.getNullable()); 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/Query.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.FileModel; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.List; 10 | 11 | @EqualsAndHashCode(callSuper = true) 12 | @Data 13 | @Builder 14 | public class Query extends FileModel { 15 | 16 | private Type entityType; 17 | private List queryItems; 18 | 19 | @Override 20 | public String getFileName() { 21 | return "/front/" + entityType.toFrontNameCase() + "/components/" + entityType.toFrontNameCase() + "-query.vue"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/QueryItem.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | @EqualsAndHashCode(callSuper = true) 7 | @Data 8 | public class QueryItem extends ItemField { 9 | public QueryItem() { 10 | super(); 11 | 12 | } 13 | 14 | public QueryItem(ItemField itemField) { 15 | super(itemField.getEntityType(), 16 | itemField.getAssociationType(), 17 | itemField.getLabel(), 18 | itemField.getProp(), 19 | itemField.getFieldName(), 20 | itemField.getDictEnName(), 21 | itemField.getItemType(), 22 | itemField.getNullable()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/Router.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.FileModel; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.List; 10 | 11 | @Builder 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class Router extends FileModel { 15 | List entityList; 16 | 17 | @Override 18 | public String getFileName() { 19 | return "/front/router.ts"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/Store.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.FileModel; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | @Builder 12 | public class Store extends FileModel { 13 | private Type entityType; 14 | 15 | @Override 16 | public String getFileName() { 17 | 18 | return "/front/" + entityType.toFrontNameCase() + "/" + entityType.toFrontNameCase() 19 | + ".ts"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/Table.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.FileModel; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.List; 10 | 11 | @EqualsAndHashCode(callSuper = true) 12 | @Data 13 | @Builder 14 | public class Table extends FileModel { 15 | 16 | private Type entityType; 17 | private List tableItems; 18 | 19 | @Override 20 | public String getFileName() { 21 | return "/front/" + entityType.toFrontNameCase() + "/components/" + entityType.toFrontNameCase() + "-table.vue"; 22 | } 23 | } -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/TableItem.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | @EqualsAndHashCode(callSuper = true) 7 | @Data 8 | public class TableItem extends ItemField { 9 | public TableItem() { 10 | super(); 11 | 12 | } 13 | 14 | public TableItem(ItemField itemField) { 15 | super(itemField.getEntityType(), 16 | itemField.getAssociationType(), 17 | itemField.getLabel(), 18 | itemField.getProp(), 19 | itemField.getFieldName(), 20 | itemField.getDictEnName(), 21 | itemField.getItemType(), 22 | itemField.getNullable()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/front/View.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.front; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.FileModel; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | @Builder 12 | public class View extends FileModel { 13 | 14 | private Type entityType; 15 | 16 | @Override 17 | public String getFileName() { 18 | return "/front/" + entityType.toFrontNameCase() + "/" + entityType.toFrontNameCase() + "-view.vue"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/repository/Repository.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.repository; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.common.ModelElement; 4 | import io.qifan.infrastructure.generator.processor.model.common.Type; 5 | import io.qifan.infrastructure.generator.processor.model.front.QueryItem; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | @EqualsAndHashCode(callSuper = true) 14 | @Data 15 | @Builder 16 | public class Repository extends ModelElement { 17 | private String sourcePath; 18 | private Type type; 19 | private Type entityType; 20 | private List fields; 21 | 22 | @Override 23 | public Set getImportTypes() { 24 | 25 | return Set.of(entityType); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/model/service/Service.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.model.service; 2 | 3 | 4 | import io.qifan.infrastructure.generator.processor.model.common.ModelElement; 5 | import io.qifan.infrastructure.generator.processor.model.common.Type; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | import java.util.Set; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | @Builder 15 | public class Service extends ModelElement { 16 | private String sourcePath; 17 | private Type type; 18 | private Type entityType; 19 | 20 | @Override 21 | public Set getImportTypes() { 22 | 23 | return Set.of(entityType); 24 | } 25 | } -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/processor/DefaultModelElementProcessorContext.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.processor; 2 | 3 | public record DefaultModelElementProcessorContext(Class typeElement, String outputPath) 4 | implements ModelElementProcessor.ProcessorContext { 5 | } 6 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/processor/ModelElementProcessor.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.processor; 2 | 3 | 4 | public interface ModelElementProcessor { 5 | 6 | 7 | R process(ProcessorContext context, P sourceModel); 8 | 9 | int getPriority(); 10 | 11 | interface ProcessorContext { 12 | 13 | Class typeElement(); 14 | 15 | String outputPath(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/processor/RouterCreateProcessor.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.processor; 2 | 3 | import io.qifan.infrastructure.generator.processor.model.front.Router; 4 | import io.qifan.infrastructure.generator.processor.utils.TypeUtils; 5 | import io.qifan.infrastructure.generator.processor.writer.ModelWriter; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | public class RouterCreateProcessor { 11 | public void porocess(Set> entities, String outputPath) { 12 | ModelWriter modelWriter = new ModelWriter(outputPath); 13 | Router router = Router.builder() 14 | .entityList(entities.stream().map(TypeUtils::getType) 15 | .toList()) 16 | .build(); 17 | modelWriter.writeModel(router, false); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/writer/FreeMarkerWritable.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.writer; 2 | 3 | import freemarker.template.TemplateException; 4 | 5 | import java.io.IOException; 6 | import java.io.Writer; 7 | 8 | public abstract class FreeMarkerWritable implements Writable { 9 | 10 | @Override 11 | public void write(Context context, Writer writer) { 12 | try { 13 | new FreeMarkerModelElementWriter().write(this, context, writer); 14 | } catch (IOException | TemplateException e) { 15 | throw new RuntimeException(e); 16 | } 17 | } 18 | 19 | protected String getTemplateName() { 20 | return getTemplateNameForClass(getClass()); 21 | } 22 | 23 | protected String getTemplateNameForClass(Class clazz) { 24 | return clazz.getName().replace('.', '/') + ".ftl"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/java/io/qifan/infrastructure/generator/processor/writer/Writable.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.generator.processor.writer; 2 | 3 | import java.io.Writer; 4 | 5 | public interface Writable { 6 | void write(Context context, Writer writer); 7 | 8 | interface Context { 9 | T get(Class type); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/resources/io/qifan/infrastructure/generator/processor/model/dto/Dto.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="io.qifan.infrastructure.generator.processor.model.dto.Dto" --> 2 | export ${entityType.typePath} 3 | 4 | input ${type.typeName}Input { 5 | #allScalars(${type.typeName}) 6 | id 7 | <#list getFields() as field> 8 | <#switch field.itemType.code> 9 | <#case 6> 10 | id(${field.fieldName}) 11 | 12 | 13 | } 14 | 15 | specification ${type.typeName}Spec { 16 | #allScalars 17 | <#list getFields() as field> 18 | <#switch field.itemType.code> 19 | <#case 1> 20 | like/i(${field.fieldName}) 21 | <#break> 22 | <#case 2> 23 | like/i(${field.fieldName}) 24 | <#break> 25 | <#case 5> 26 | ge(${field.fieldName}) 27 | le(${field.fieldName}) 28 | <#break> 29 | <#case 6> 30 | associatedIdEq(${field.fieldName}) 31 | <#break> 32 | 33 | 34 | associatedIdEq(creator) 35 | } -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/resources/io/qifan/infrastructure/generator/processor/model/front/Store.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="io.qifan.infrastructure.generator.processor.model.front.Store" --> 2 | <#assign uncapitalizeTypeName = entityType.getUncapitalizeTypeName()> 3 | 4 | import { api } from '@/utils/api-instance' 5 | export const ${uncapitalizeTypeName}QueryOptions = async (keyword: string, id: string) => { 6 | return ( 7 | await api.${uncapitalizeTypeName}ForAdminController.query({ body: { query: { name: keyword, id } } }) 8 | ).content 9 | } -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/resources/io/qifan/infrastructure/generator/processor/model/front/TableItem.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="io.qifan.infrastructure.generator.processor.model.front.TableItem" --> 2 | <#if getItemType().code!=-1> 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /uni-ai-backend/generator-processor/src/main/resources/io/qifan/infrastructure/generator/processor/model/service/Service.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="io.qifan.infrastructure.generator.processor.model.service.Service" --> 2 | package ${type.packagePath}; 3 | 4 | <#list importTypes as importType> 5 | import ${importType.getTypePath()}; 6 | 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | <#assign uncapitalizeTypeName = entityType.getUncapitalizeTypeName()> 12 | @Service 13 | @Slf4j 14 | @AllArgsConstructor 15 | @Transactional 16 | public class ${type.typeName} { 17 | private final ${entityType.typeName}Repository ${uncapitalizeTypeName}Repository; 18 | 19 | } -------------------------------------------------------------------------------- /uni-ai-backend/scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:17 2 | # 作者的信息,可以不填 3 | MAINTAINER http://www.jarcheng.top/ 4 | # 注意这里,这个地方访问的是build时指定的资源路径。而不是当前文件夹下的文件。 5 | # 将资源路径内的的jar包夹复制到镜像内并且重命名为app.jar。 6 | COPY ./target/server-0.1.12.jar app.jar 7 | # 镜像实例化,即启动容器后的运行命令,我们这边就是启动服务 8 | ENTRYPOINT ["java","-jar", "/app.jar"] -------------------------------------------------------------------------------- /uni-ai-backend/scripts/build.sh: -------------------------------------------------------------------------------- 1 | cd ../../uni-ai-admin 2 | npm run build-only 3 | cp -r ./dist ../uni-ai-backend/server/src/main/resources 4 | cd ../uni-ai-backend 5 | mvn -DskipTests=true package 6 | cd scripts 7 | docker build -t qifan7/uni-ai:0.1.12 -f Dockerfile ../server 8 | docker push qifan7/uni-ai:0.1.12 -------------------------------------------------------------------------------- /uni-ai-backend/scripts/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | name: uni-ai-compose 3 | services: 4 | mysql: 5 | # 镜像名称 6 | image: mysql:8.0.26 7 | # 相当于 --name 8 | container_name: mysql 9 | # 相当于多个 -e 10 | environment: 11 | MYSQL_ROOT_PASSWORD: 123456 12 | TZ: Asia/Shanghai 13 | MYSQL_DATABASE: uni_ai 14 | # 相当于 -p 15 | ports: 16 | - "3308:3306" 17 | # 相当于 -v 18 | volumes: 19 | - mysql-data:/var/lib/mysql 20 | # 容器启动后执行下面这个命令 21 | command: [ 'mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci' ] 22 | redis: 23 | image: redis/redis-stack:latest 24 | container_name: redis-stack 25 | restart: always 26 | ports: 27 | - "6381:6379" 28 | - "8001:8001" 29 | environment: 30 | REDIS_ARGS: --requirepass 123456 31 | volumes: 32 | - redis-data:/data 33 | uni-ai: 34 | image: qifan7/uni-ai:0.1.12 35 | container_name: uni-ai 36 | environment: 37 | spring.profiles.active: prod 38 | ports: 39 | - "8877:8877" 40 | depends_on: 41 | - mysql 42 | - redis 43 | volumes: 44 | mysql-data: { } 45 | redis-data: { } 46 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiCollection.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.collection.entity.AiCollection 2 | 3 | input AiCollectionCreateInput { 4 | #allScalars(AiCollection) 5 | id(embeddingModel) 6 | } 7 | input AiCollectionUpdateInput { 8 | #allScalars(AiCollection) 9 | id! 10 | id(embeddingModel) 11 | } 12 | 13 | specification AiCollectionSpec { 14 | #allScalars 15 | like/i(name) 16 | like/i(collectionName) 17 | like/i(id) 18 | ge(createdTime) 19 | le(createdTime) 20 | ge(editedTime) 21 | le(editedTime) 22 | id(creator) 23 | id(embeddingModel) 24 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiDocument.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.document.entity.AiDocument 2 | 3 | input AiDocumentCreateInput { 4 | #allScalars(AiDocument) 5 | id(aiCollection) 6 | -docIds 7 | } 8 | input AiDocumentUpdateInput { 9 | #allScalars(AiDocument) 10 | id! 11 | id(aiCollection) 12 | -docIds 13 | } 14 | 15 | specification AiDocumentSpec { 16 | #allScalars 17 | like/i(name) 18 | like/i(id) 19 | like/i(content) 20 | ge(editedTime) 21 | le(editedTime) 22 | ge(createdTime) 23 | le(createdTime) 24 | id(creator) 25 | id(aiCollection) 26 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiFactory.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.factory.entity.AiFactory 2 | 3 | input AiFactoryCreateInput { 4 | #allScalars(AiFactory) 5 | } 6 | input AiFactoryUpdateInput { 7 | #allScalars(AiFactory) 8 | id! 9 | } 10 | 11 | specification AiFactorySpec { 12 | #allScalars 13 | like/i(description) 14 | like/i(id) 15 | ge(createdTime) 16 | le(createdTime) 17 | ge(editedTime) 18 | le(editedTime) 19 | id(creator) 20 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiMessage.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.message.entity.AiMessage 2 | 3 | input AiMessageCreateInput { 4 | #allScalars(AiMessage) 5 | id(aiSession) 6 | } 7 | input AiMessageUpdateInput { 8 | #allScalars(AiMessage) 9 | id! 10 | id(aiSession) 11 | } 12 | //AiMessageView { 13 | // content 14 | // type 15 | //} 16 | 17 | specification AiMessageSpec { 18 | #allScalars 19 | like/i(id) 20 | ge(createdTime) 21 | le(createdTime) 22 | ge(editedTime) 23 | le(editedTime) 24 | id(creator) 25 | id(aiSession) 26 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiModel.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.model.entity.AiModel 2 | 3 | input AiModelCreateInput { 4 | #allScalars(AiModel) 5 | tagIds:Array 6 | } 7 | input AiModelUpdateInput { 8 | #allScalars(AiModel) 9 | id! 10 | tagIds:Array 11 | } 12 | 13 | specification AiModelSpec { 14 | #allScalars 15 | like/i(name) 16 | like/i(id) 17 | ge(createdTime) 18 | le(createdTime) 19 | ge(editedTime) 20 | le(editedTime) 21 | id(creator) 22 | flat(tags) { 23 | flat(aiTag) { 24 | valueIn(name) as tagNames 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiPlugin.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.plugin.entity.AiPlugin 2 | 3 | input AiPluginCreateInput { 4 | #allScalars(AiPlugin) 5 | } 6 | input AiPluginUpdateInput { 7 | #allScalars(AiPlugin) 8 | id! 9 | } 10 | 11 | specification AiPluginSpec { 12 | #allScalars 13 | like/i(name) 14 | like/i(description) 15 | like/i(id) 16 | ge(createdTime) 17 | le(createdTime) 18 | ge(editedTime) 19 | le(editedTime) 20 | id(creator) 21 | valueIn(name) as Names 22 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiRole.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.role.entity.AiRole 2 | 3 | input AiRoleCreateInput { 4 | #allScalars(AiRole) 5 | } 6 | input AiRoleUpdateInput { 7 | #allScalars(AiRole) 8 | id! 9 | } 10 | 11 | specification AiRoleSpec { 12 | #allScalars 13 | like/i(name) 14 | like/i(id) 15 | ge(createdTime) 16 | le(createdTime) 17 | ge(editedTime) 18 | le(editedTime) 19 | id(creator) 20 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiSession.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.session.entity.AiSession 2 | 3 | input AiSessionCreateInput { 4 | #allScalars(AiSession) 5 | } 6 | input AiSessionUpdateInput { 7 | #allScalars(AiSession) 8 | id! 9 | } 10 | 11 | specification AiSessionSpec { 12 | #allScalars 13 | like/i(name) 14 | like/i(id) 15 | ge(createdTime) 16 | le(createdTime) 17 | ge(editedTime) 18 | le(editedTime) 19 | id(creator) 20 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/ai/AiTag.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.ai.tag.root.entity.AiTag 2 | 3 | input AiTagCreateInput { 4 | #allScalars(AiTag) 5 | } 6 | input AiTagUpdateInput { 7 | #allScalars(AiTag) 8 | id! 9 | } 10 | 11 | specification AiTagSpec { 12 | #allScalars 13 | like/i(service) 14 | like/i(id) 15 | ge(editedTime) 16 | le(editedTime) 17 | ge(createdTime) 18 | le(createdTime) 19 | id(creator) 20 | valueIn(id) as ids 21 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/dict/Dict.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.dict.entity.Dict 2 | input DictInput { 3 | #allScalars(Dict) 4 | id? 5 | } 6 | 7 | specification DictSpec { 8 | #allScalars 9 | like/i(dictEnName) 10 | like/i(keyEnName) 11 | like/i(keyName) 12 | like/i(dictName) 13 | like/i(id) 14 | ge(editedTime) 15 | le(editedTime) 16 | ge(createdTime) 17 | le(createdTime) 18 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/menu/Menu.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.menu.entity.Menu 2 | input MenuInput { 3 | #allScalars(Menu) 4 | id? 5 | } 6 | 7 | specification MenuSpec { 8 | #allScalars 9 | like/i(name) 10 | like/i(path) 11 | like/i(id) 12 | ge(createdTime) 13 | le(createdTime) 14 | ge(editedTime) 15 | le(editedTime) 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/role/Role.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.role.entity.Role 2 | input RoleInput { 3 | #allScalars(Role) 4 | id? 5 | menuIds: Array 6 | } 7 | 8 | specification RoleSpec { 9 | #allScalars 10 | like/i(name) 11 | like/i(id) 12 | valueIn(id) as ids 13 | ge(editedTime) 14 | le(editedTime) 15 | ge(createdTime) 16 | le(createdTime) 17 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/user/User.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.user.root.entity.User 2 | 3 | input UserCreateInput { 4 | #allScalars(User) 5 | roleIds: Array 6 | } 7 | input UserUpdateInput { 8 | #allScalars(User) 9 | id! 10 | roleIds: Array 11 | } 12 | input UserInfoInput{ 13 | nickname 14 | gender 15 | avatar 16 | } 17 | input UserRegisterInput { 18 | phone 19 | password 20 | code: String 21 | } 22 | input UserLoginInput { 23 | password 24 | phone 25 | } 26 | input UserResetPasswordInput { 27 | password 28 | phone 29 | code: String 30 | } 31 | specification UserSpec { 32 | #allScalars 33 | like/i(id) 34 | like/i(phone) 35 | like/i(nickname) 36 | like/i(password) 37 | ge(createdTime) 38 | le(createdTime) 39 | ge(editedTime) 40 | le(editedTime) 41 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/user/UserWeChat.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.user.wechat.entity.UserWeChat 2 | input UserWeChatCreateInput { 3 | #allScalars(UserWeChat) 4 | } 5 | input UserWeChatUpdateInput { 6 | #allScalars(UserWeChat) 7 | id! 8 | } 9 | specification UserWeChatSpec { 10 | #allScalars 11 | like/i(id) 12 | like/i(openId) 13 | ge(editedTime) 14 | le(editedTime) 15 | ge(createdTime) 16 | le(createdTime) 17 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/wallet/Wallet.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.wallet.root.entity.Wallet 2 | 3 | input WalletCreateInput { 4 | #allScalars(Wallet) 5 | id? 6 | id(user) 7 | } 8 | input WalletUpdateInput { 9 | #allScalars(Wallet) 10 | id! 11 | id(user) 12 | } 13 | 14 | specification WalletSpec { 15 | #allScalars 16 | like/i(password) 17 | like/i(id) 18 | ge(createdTime) 19 | le(createdTime) 20 | ge(editedTime) 21 | le(editedTime) 22 | id(creator) 23 | flat(user) { 24 | id as userId 25 | like/i(phone) 26 | } 27 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/wallet/WalletItem.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.wallet.item.entity.WalletItem 2 | 3 | input WalletItemCreateInput { 4 | #allScalars(WalletItem) 5 | } 6 | input WalletItemUpdateInput { 7 | #allScalars(WalletItem) 8 | id! 9 | } 10 | 11 | specification WalletItemSpec { 12 | #allScalars 13 | like/i(name) 14 | like/i(id) 15 | ge(createdTime) 16 | le(createdTime) 17 | ge(editedTime) 18 | le(editedTime) 19 | id(creator) 20 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/wallet/WalletOrder.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.wallet.order.entity.WalletOrder 2 | 3 | input WalletOrderCreateInput { 4 | #allScalars(WalletOrder) 5 | id? 6 | id(user) 7 | } 8 | input WalletOrderUpdateInput { 9 | #allScalars(WalletOrder) 10 | id! 11 | id(user) 12 | } 13 | 14 | specification WalletOrderSpec { 15 | #allScalars 16 | ge(payTime) 17 | le(payTime) 18 | like/i(id) 19 | ge(createdTime) 20 | le(createdTime) 21 | ge(editedTime) 22 | le(editedTime) 23 | id(creator) 24 | id(user) 25 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/dto/wallet/WalletRecord.dto: -------------------------------------------------------------------------------- 1 | export io.qifan.server.wallet.record.entity.WalletRecord 2 | 3 | input WalletRecordCreateInput { 4 | #allScalars(WalletRecord) 5 | id(wallet) 6 | -balance 7 | } 8 | input WalletRecordUpdateInput { 9 | #allScalars(WalletRecord) 10 | id! 11 | id(wallet) 12 | -balance 13 | } 14 | 15 | specification WalletRecordSpec { 16 | #allScalars 17 | like/i(description) 18 | like/i(id) 19 | ge(createdTime) 20 | le(createdTime) 21 | ge(editedTime) 22 | le(editedTime) 23 | id(creator) 24 | id(wallet) 25 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ServerApplication.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server; 2 | 3 | import io.qifan.server.infrastructure.model.WxPayPropertiesExtension; 4 | import org.babyfish.jimmer.client.EnableImplicitApi; 5 | import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 9 | import org.springframework.scheduling.annotation.EnableAsync; 10 | 11 | @SpringBootApplication(exclude = {RedisVectorStoreAutoConfiguration.class}) 12 | @EnableImplicitApi 13 | @EnableConfigurationProperties(value = {WxPayPropertiesExtension.class}) 14 | @EnableAsync 15 | public class ServerApplication { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(ServerApplication.class, args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/collection/entity/AiCollection.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.collection.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.ai.model.entity.AiModel; 7 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 8 | import org.babyfish.jimmer.sql.Entity; 9 | import org.babyfish.jimmer.sql.IdView; 10 | import org.babyfish.jimmer.sql.ManyToOne; 11 | 12 | 13 | /** 14 | *

15 | * 知识库 16 | * 17 | *

18 | * 19 | * @author a1507 20 | * @date 2024-05-30 21 | */ 22 | @Entity 23 | @GenEntity 24 | public interface AiCollection extends BaseEntity { 25 | 26 | /** 27 | * 知识库名称 28 | */ 29 | @GenField(value = "中文名称", order = 0) 30 | String name(); 31 | 32 | @GenField(value = "英文名称", order = 1) 33 | String collectionName(); 34 | 35 | /** 36 | * 嵌入模型 37 | */ 38 | @GenField(value = "嵌入模型", order = 1, type = ItemType.ASSOCIATION_SELECT) 39 | @IdView 40 | String embeddingModelId(); 41 | 42 | @ManyToOne 43 | AiModel embeddingModel(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/collection/service/AiCollectionService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.collection.service; 2 | 3 | import io.qifan.server.ai.collection.repository.AiCollectionRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiCollectionService { 14 | private final AiCollectionRepository aiCollectionRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/document/entity/AiDocument.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.document.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.ai.collection.entity.AiCollection; 7 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 8 | import org.babyfish.jimmer.sql.*; 9 | 10 | import java.util.List; 11 | 12 | 13 | /** 14 | *

15 | * 知识库文档 16 | *

17 | */ 18 | @GenEntity 19 | @Entity 20 | public interface AiDocument extends BaseEntity { 21 | @GenField(value = "名称") 22 | String name(); 23 | 24 | @GenField(value = "内容") 25 | String content(); 26 | 27 | @GenField(value = "知识库", order = 1, type = ItemType.ASSOCIATION_SELECT) 28 | @IdView 29 | String aiCollectionId(); 30 | 31 | @ManyToOne 32 | @OnDissociate(DissociateAction.DELETE) 33 | AiCollection aiCollection(); 34 | 35 | @Serialized 36 | List docIds(); 37 | } 38 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/document/service/AiDocumentService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.document.service; 2 | 3 | import io.qifan.server.ai.document.repository.AiDocumentRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiDocumentService { 14 | private final AiDocumentRepository aiDocumentRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/factory/entity/AiFactory.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.factory.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.dict.model.DictConstants; 7 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 8 | import jakarta.validation.constraints.Null; 9 | import org.babyfish.jimmer.sql.Entity; 10 | import org.babyfish.jimmer.sql.Serialized; 11 | 12 | import java.util.Map; 13 | 14 | 15 | /** 16 | *

17 | * AI厂家 18 | *

19 | */ 20 | @GenEntity 21 | @Entity 22 | public interface AiFactory extends BaseEntity { 23 | 24 | /** 25 | * 厂家名称 26 | */ 27 | @GenField(value = "厂家名称", type = ItemType.SELECTABLE, dictEnName = DictConstants.AI_FACTORY_TYPE, order = 0) 28 | DictConstants.AiFactoryType name(); 29 | 30 | /** 31 | * 厂家描述 32 | */ 33 | @Null 34 | @GenField(value = "厂家描述", order = 1) 35 | String description(); 36 | 37 | /** 38 | * options 39 | */ 40 | @Null 41 | @Serialized 42 | Map options(); 43 | } 44 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/factory/service/AiFactoryService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.factory.service; 2 | 3 | import io.qifan.server.ai.factory.repository.AiFactoryRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiFactoryService { 14 | private final AiFactoryRepository aiFactoryRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/message/entity/AiMessage.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.message.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.ai.session.entity.AiSession; 7 | import io.qifan.server.dict.model.DictConstants; 8 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 9 | import org.babyfish.jimmer.sql.*; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | 15 | @Entity 16 | @Table(name = "ai_message") 17 | @GenEntity 18 | public interface AiMessage extends BaseEntity { 19 | 20 | /** 21 | * 消息类型(用户/助手/系统) 22 | */ 23 | @GenField(value = "消息类型", type = ItemType.SELECTABLE, dictEnName = DictConstants.AI_MESSAGE_TYPE, order = 0) 24 | DictConstants.AiMessageType type(); 25 | 26 | /** 27 | * 消息内容 28 | */ 29 | @Serialized 30 | @GenField(value = "消息内容", type = ItemType.INPUT_TEXT_AREA, order = 1) 31 | List> content(); 32 | 33 | /** 34 | * 会话id 35 | */ 36 | @GenField(value = "会话", type = ItemType.ASSOCIATION_SELECT, order = 2) 37 | @IdView 38 | String aiSessionId(); 39 | 40 | @ManyToOne 41 | @OnDissociate(DissociateAction.DELETE) 42 | AiSession aiSession(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/message/entity/dto/ChatMessageRequest.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.message.entity.dto; 2 | 3 | import io.qifan.server.ai.message.entity.model.ChatParams; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class ChatMessageRequest { 8 | AiMessageCreateInput message; 9 | ChatParams chatParams; 10 | } 11 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/message/entity/model/ChatParams.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.message.entity.model; 2 | 3 | import io.qifan.server.dict.model.DictConstants; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | @Data 10 | public class ChatParams { 11 | DictConstants.AiModelTag tag; 12 | String aiCollectionId; 13 | String aiModelId; 14 | String aiRoleId; 15 | List pluginNames; 16 | Map options; 17 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/model/entity/AiModel.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.model.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.ai.tag.model.entity.AiModelTagRel; 7 | import io.qifan.server.ai.tag.root.entity.AiTag; 8 | import io.qifan.server.dict.model.DictConstants; 9 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 10 | import jakarta.validation.constraints.Null; 11 | import org.babyfish.jimmer.sql.Entity; 12 | import org.babyfish.jimmer.sql.ManyToManyView; 13 | import org.babyfish.jimmer.sql.OneToMany; 14 | import org.babyfish.jimmer.sql.Serialized; 15 | 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * Entity for table "AI模型" 21 | */ 22 | @GenEntity 23 | @Entity 24 | public interface AiModel extends BaseEntity { 25 | /** 26 | * 模型 27 | */ 28 | @GenField(value = "模型", order = 0) 29 | String name(); 30 | 31 | /** 32 | * 厂家 33 | */ 34 | 35 | @GenField(value = "厂家", type = ItemType.SELECTABLE, dictEnName = DictConstants.AI_FACTORY_TYPE, order = 1) 36 | DictConstants.AiFactoryType factory(); 37 | 38 | @OneToMany(mappedBy = "aiModel") 39 | List tags(); 40 | 41 | @ManyToManyView(prop = "tags") 42 | List tagsView(); 43 | 44 | @Null 45 | @Serialized 46 | Map options(); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/model/service/AiModelService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.model.service; 2 | 3 | import io.qifan.server.ai.model.repository.AiModelRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiModelService { 14 | private final AiModelRepository aiModelRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/plugin/entity/AiPlugin.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.plugin.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 6 | import org.babyfish.jimmer.sql.Entity; 7 | 8 | 9 | /** 10 | *

11 | * AI插件 12 | *

13 | */ 14 | @GenEntity 15 | @Entity 16 | public interface AiPlugin extends BaseEntity { 17 | 18 | /** 19 | * 函数名称 20 | */ 21 | @GenField(value = "函数名称", order = 0) 22 | String name(); 23 | 24 | /** 25 | * 函数描述 26 | */ 27 | @GenField(value = "函数描述", order = 1) 28 | String description(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/plugin/entity/model/Parameter.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.plugin.entity.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | @JsonInclude(JsonInclude.Include.NON_NULL) 10 | @Data 11 | public class Parameter { 12 | String type; 13 | Map properties; 14 | List required; 15 | 16 | @Data 17 | public static class Property { 18 | String type; 19 | String description; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/plugin/service/AiPluginService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.plugin.service; 2 | 3 | import io.qifan.server.ai.plugin.repository.AiPluginRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiPluginService { 14 | private final AiPluginRepository aiPluginRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/plugin/service/function/FunctionRegistry.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.plugin.service.function; 2 | 3 | import org.springframework.ai.model.function.FunctionCallbackContext; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.annotation.Description; 8 | 9 | import java.util.function.Function; 10 | 11 | @Configuration 12 | public class FunctionRegistry { 13 | 14 | @Bean 15 | @Description(value = "执行符合SpringSpEL语法的表达式") 16 | public Function springSpELFunction() { 17 | return new SpringSpELService(); 18 | } 19 | 20 | @Bean 21 | public FunctionCallbackContext springAiFunctionManager(ApplicationContext context) { 22 | FunctionCallbackContext manager = new FunctionCallbackContext(); 23 | manager.setApplicationContext(context); 24 | return manager; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/plugin/service/function/SpringSpELService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.plugin.service.function; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.fasterxml.jackson.annotation.JsonPropertyDescription; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.expression.spel.standard.SpelExpressionParser; 7 | 8 | import java.util.function.Function; 9 | 10 | @Slf4j 11 | public class SpringSpELService implements Function { 12 | @Override 13 | public Response apply(Request request) { 14 | log.info("SpringSpELService apply request: {}", request); 15 | SpelExpressionParser parser = new SpelExpressionParser(); 16 | return new Response(parser.parseExpression(request.expression).getValue().toString()); 17 | } 18 | 19 | public record Request( 20 | @JsonProperty(required = true, value = "expression") @JsonPropertyDescription(value = "表达式字符串") String expression) { 21 | } 22 | 23 | public record Response(String result) { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/role/entity/AiRole.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.role.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.ai.message.entity.dto.AiMessageView; 7 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 8 | import jakarta.annotation.Nullable; 9 | import org.babyfish.jimmer.sql.Entity; 10 | import org.babyfish.jimmer.sql.Key; 11 | import org.babyfish.jimmer.sql.Serialized; 12 | import org.babyfish.jimmer.sql.Table; 13 | 14 | import java.util.List; 15 | 16 | 17 | @GenEntity 18 | @Entity 19 | @Table(name = "ai_role") 20 | public interface AiRole extends BaseEntity { 21 | 22 | /** 23 | * 角色名称 24 | */ 25 | @GenField(value = "角色名称", order = 0) 26 | @Key 27 | String name(); 28 | 29 | /** 30 | * 描述 31 | */ 32 | @GenField(value = "描述", order = 1) 33 | String description(); 34 | 35 | /** 36 | * 图标 37 | */ 38 | @Nullable 39 | @GenField(value = "图标", type = ItemType.PICTURE, order = 1) 40 | String icon(); 41 | 42 | /** 43 | * 预置提示词 44 | */ 45 | @GenField(value = "预置提示词", order = 2) 46 | @Serialized 47 | List prompts(); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/role/service/AiRoleService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.role.service; 2 | 3 | import io.qifan.server.ai.role.repository.AiRoleRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiRoleService { 14 | private final AiRoleRepository aiRoleRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/session/entity/AiSession.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.session.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.server.ai.message.entity.AiMessage; 6 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 7 | import org.babyfish.jimmer.sql.Entity; 8 | import org.babyfish.jimmer.sql.OneToMany; 9 | import org.babyfish.jimmer.sql.OrderedProp; 10 | import org.babyfish.jimmer.sql.Table; 11 | 12 | import java.util.List; 13 | 14 | @GenEntity 15 | @Entity 16 | @Table(name = "ai_session") 17 | public interface AiSession extends BaseEntity { 18 | 19 | /** 20 | * 会话名称 21 | */ 22 | @GenField(value = "会话名称", order = 0) 23 | String name(); 24 | 25 | 26 | @OneToMany(mappedBy = "aiSession", orderedProps = @OrderedProp(value = "createdTime")) 27 | List messages(); 28 | } 29 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/session/service/AiSessionService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.session.service; 2 | 3 | import io.qifan.server.ai.session.repository.AiSessionRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiSessionService { 14 | private final AiSessionRepository aiSessionRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/tag/model/entity/AiModelTagRel.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.tag.model.entity; 2 | 3 | import io.qifan.server.ai.model.entity.AiModel; 4 | import io.qifan.server.ai.tag.root.entity.AiTag; 5 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 6 | import org.babyfish.jimmer.sql.*; 7 | 8 | 9 | /** 10 | *

11 | * ai_model_tag_rel 12 | *

13 | */ 14 | @Entity 15 | @Table(name = "ai_model_tag_rel") 16 | public interface AiModelTagRel extends BaseEntity { 17 | 18 | /** 19 | * 标签 20 | */ 21 | @IdView 22 | String aiTagId(); 23 | 24 | @Key 25 | @ManyToOne 26 | AiTag aiTag(); 27 | 28 | /** 29 | * 模型 30 | */ 31 | @IdView 32 | String aiModelId(); 33 | 34 | @Key 35 | @ManyToOne 36 | AiModel aiModel(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/tag/model/repository/AiTagModelRelRepository.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.tag.model.repository; 2 | 3 | import io.qifan.server.ai.tag.model.entity.AiModelTagRel; 4 | import org.babyfish.jimmer.spring.repository.JRepository; 5 | 6 | public interface AiTagModelRelRepository extends JRepository { 7 | } 8 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/tag/root/entity/AiTag.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.tag.root.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.dict.model.DictConstants; 7 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 8 | import org.babyfish.jimmer.sql.Entity; 9 | import org.babyfish.jimmer.sql.Table; 10 | 11 | 12 | /** 13 | *

14 | * spring ai model标签 15 | *

16 | */ 17 | @GenEntity 18 | @Entity 19 | @Table(name = "ai_tag") 20 | public interface AiTag extends BaseEntity { 21 | 22 | /** 23 | * 标签 24 | */ 25 | @GenField(value = "标签", type = ItemType.SELECTABLE, dictEnName = DictConstants.AI_MODEL_TAG, order = 0) 26 | DictConstants.AiModelTag name(); 27 | 28 | 29 | /** 30 | * 厂家 31 | */ 32 | @GenField(value = "厂家", type = ItemType.SELECTABLE, dictEnName = DictConstants.AI_FACTORY_TYPE, order = 0) 33 | DictConstants.AiFactoryType factory(); 34 | 35 | /** 36 | * service 37 | */ 38 | @GenField(value = "service", order = 2) 39 | String service(); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/tag/root/service/AiTagService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.tag.root.service; 2 | 3 | import io.qifan.server.ai.tag.root.repository.AiTagRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class AiTagService { 14 | private final AiTagRepository aiTagRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/uni/chat/UniAiChatService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.uni.chat; 2 | 3 | import org.springframework.ai.chat.model.ChatModel; 4 | 5 | import java.util.Map; 6 | 7 | public interface UniAiChatService { 8 | ChatModel getChatModel(Map options); 9 | } 10 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/uni/embedding/UniAiEmbeddingService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.uni.embedding; 2 | 3 | import org.springframework.ai.embedding.EmbeddingModel; 4 | 5 | import java.util.Map; 6 | 7 | public interface UniAiEmbeddingService { 8 | EmbeddingModel getEmbeddingModel(Map options); 9 | } 10 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/uni/image/UniAiImageService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.uni.image; 2 | 3 | import org.springframework.ai.image.ImageModel; 4 | 5 | import java.util.Map; 6 | 7 | public interface UniAiImageService { 8 | ImageModel getImageMode(Map options); 9 | } 10 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/ai/uni/vector/UniAiVectorService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.ai.uni.vector; 2 | 3 | import org.springframework.ai.document.Document; 4 | import org.springframework.ai.vectorstore.VectorStore; 5 | 6 | import java.util.List; 7 | 8 | public interface UniAiVectorService { 9 | void embedding(List documents, String collectionId); 10 | 11 | List similaritySearch(String query, String collectionId); 12 | 13 | VectorStore getVectorStore(String collectionId); 14 | 15 | void deleteCollection(String collectionId); 16 | } 17 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/dict/entity/Dict.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.dict.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 6 | import org.babyfish.jimmer.sql.Entity; 7 | import org.babyfish.jimmer.sql.Key; 8 | 9 | @Entity 10 | @GenEntity 11 | public interface Dict extends BaseEntity { 12 | 13 | @GenField(value = "值编号", order = -1) 14 | @Key 15 | int keyId(); 16 | 17 | @GenField(value = "值名称", order = 0) 18 | String keyName(); 19 | 20 | @GenField(value = "值英文名称", order = 1) 21 | String keyEnName(); 22 | 23 | @GenField(value = "字典编号", order = 2) 24 | @Key 25 | int dictId(); 26 | 27 | @GenField(value = "字典名称", order = 3) 28 | String dictName(); 29 | 30 | @GenField(value = "字段英文名称", order = 4) 31 | String dictEnName(); 32 | 33 | @GenField(value = "排序号", order = 5) 34 | int orderNum(); 35 | 36 | @GenField(value = "是否可见", order = 6) 37 | boolean visible(); 38 | } 39 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/dict/model/DictGenContext.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.dict.model; 2 | 3 | import io.qifan.server.dict.entity.Dict; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | public class DictGenContext { 13 | 14 | private List dictTypes; 15 | private Map> dictMap; 16 | } 17 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/aop/NotRepeat.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.aop; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Target({ElementType.METHOD}) 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Documented 8 | public @interface NotRepeat { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.config; 2 | 3 | import org.springframework.boot.autoconfigure.AutoConfigureAfter; 4 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.data.redis.connection.RedisConnectionFactory; 8 | import org.springframework.data.redis.core.RedisTemplate; 9 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 10 | 11 | @AutoConfigureAfter(RedisAutoConfiguration.class) 12 | @Configuration 13 | public class RedisConfig { 14 | 15 | // redis-start会自动创建LettuceConnectionFactory ,也可以手动创建JedisConnectionFactory 16 | @Bean 17 | public RedisTemplate stringObjectRedisTemplate( 18 | RedisConnectionFactory redisConnectionFactory) { 19 | RedisTemplate stringObjectRedisTemplate = new RedisTemplate<>(); 20 | stringObjectRedisTemplate.setConnectionFactory(redisConnectionFactory); 21 | // 使用FastJson序列化object 22 | stringObjectRedisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); 23 | return stringObjectRedisTemplate; 24 | } 25 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Primary; 6 | import org.springframework.core.task.AsyncTaskExecutor; 7 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 8 | import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 10 | 11 | @Configuration 12 | public class WebConfig implements WebMvcConfigurer { 13 | @Primary 14 | @Bean(name = "asyncTaskExecutor") 15 | public AsyncTaskExecutor asyncTaskExecutor() { 16 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 17 | executor.setCorePoolSize(5); // 根据需求调整 18 | executor.setMaxPoolSize(10); 19 | executor.setQueueCapacity(25); 20 | executor.setThreadNamePrefix("MyApp-Async-"); 21 | executor.initialize(); 22 | return executor; 23 | } 24 | 25 | @Override 26 | public void configureAsyncSupport(AsyncSupportConfigurer configurer) { 27 | configurer.setTaskExecutor(asyncTaskExecutor()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/jimmer/BaseDateTime.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.jimmer; 2 | 3 | import org.babyfish.jimmer.sql.MappedSuperclass; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | @MappedSuperclass 8 | public interface BaseDateTime { 9 | 10 | LocalDateTime createdTime(); 11 | 12 | LocalDateTime editedTime(); 13 | } 14 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/jimmer/BaseDateTimeDraftInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.jimmer; 2 | 3 | import lombok.AllArgsConstructor; 4 | import org.babyfish.jimmer.sql.DraftInterceptor; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | @Component 11 | @AllArgsConstructor 12 | public class BaseDateTimeDraftInterceptor implements 13 | DraftInterceptor { 14 | 15 | 16 | @Override 17 | public void beforeSave(@NotNull BaseDateTimeDraft draft, BaseDateTime baseDateTime) { 18 | draft.setEditedTime(LocalDateTime.now()); 19 | if (baseDateTime == null) { 20 | draft.setCreatedTime(LocalDateTime.now()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/jimmer/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.jimmer; 2 | 3 | import io.qifan.server.user.root.entity.User; 4 | import org.babyfish.jimmer.sql.*; 5 | 6 | @MappedSuperclass 7 | public interface BaseEntity extends BaseDateTime { 8 | 9 | @Id 10 | @GeneratedValue(generatorType = UUIDIdGenerator.class) 11 | String id(); 12 | 13 | @ManyToOne 14 | @OnDissociate(DissociateAction.DELETE) 15 | User editor(); 16 | 17 | @ManyToOne 18 | @OnDissociate(DissociateAction.DELETE) 19 | User creator(); 20 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/jimmer/BaseEntityDraftInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.jimmer; 2 | 3 | import cn.dev33.satoken.stp.StpUtil; 4 | import lombok.AllArgsConstructor; 5 | import org.babyfish.jimmer.sql.DraftInterceptor; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @AllArgsConstructor 11 | public class BaseEntityDraftInterceptor implements DraftInterceptor { 12 | 13 | 14 | @Override 15 | public void beforeSave(@NotNull BaseEntityDraft draft, BaseEntity baseEntity) { 16 | draft.applyEditor(user -> { 17 | user.setId(StpUtil.getLoginIdAsString()); 18 | }); 19 | if (baseEntity == null) { 20 | draft.applyCreator(user -> { 21 | user.setId(StpUtil.getLoginIdAsString()); 22 | }); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/jimmer/JimmerConfig.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.jimmer; 2 | 3 | import org.babyfish.jimmer.sql.meta.DatabaseNamingStrategy; 4 | import org.babyfish.jimmer.sql.runtime.DefaultDatabaseNamingStrategy; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class JimmerConfig { 10 | 11 | @Bean 12 | public DatabaseNamingStrategy databaseNamingStrategy() { 13 | return DefaultDatabaseNamingStrategy.LOWER_CASE; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/jimmer/UUIDIdGenerator.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.jimmer; 2 | 3 | import cn.hutool.core.util.IdUtil; 4 | import org.babyfish.jimmer.sql.meta.UserIdGenerator; 5 | 6 | public class UUIDIdGenerator implements UserIdGenerator { 7 | 8 | public UUIDIdGenerator() { 9 | } 10 | 11 | public String generate(Class entityType) { 12 | return IdUtil.fastSimpleUUID(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/model/LoginDevice.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.model; 2 | 3 | 4 | public interface LoginDevice { 5 | 6 | // "微信小程序" 7 | String MP_WECHAT = "mp-wechat"; 8 | // "浏览器" 9 | String BROWSER = "browser"; 10 | } 11 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/infrastructure/model/WxPayPropertiesExtension.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.infrastructure.model; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | @ConfigurationProperties( 7 | prefix = "wx.pay" 8 | ) 9 | @Data 10 | public class WxPayPropertiesExtension { 11 | 12 | private String notifyUrl; 13 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/menu/entity/Menu.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.menu.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.dict.model.DictConstants; 7 | import io.qifan.server.dict.model.DictConstants.MenuType; 8 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 9 | import io.qifan.server.role.entity.RoleMenuRel; 10 | import jakarta.validation.constraints.Null; 11 | import org.babyfish.jimmer.sql.Entity; 12 | import org.babyfish.jimmer.sql.OneToMany; 13 | 14 | import java.util.List; 15 | 16 | @GenEntity 17 | @Entity 18 | public interface Menu extends BaseEntity { 19 | 20 | @GenField(value = "菜单名称", order = 0) 21 | String name(); 22 | 23 | @GenField(value = "父菜单Id", order = 1) 24 | @Null 25 | String parentId(); 26 | 27 | @GenField(value = "路由路径", order = 2) 28 | String path(); 29 | 30 | @GenField(value = "排序号", order = 3) 31 | Integer orderNum(); 32 | 33 | @GenField(value = "菜单类型", type = ItemType.SELECTABLE, dictEnName = DictConstants.MENU_TYPE, order = 4) 34 | MenuType menuType(); 35 | 36 | @GenField(value = "图标", type = ItemType.PICTURE, order = 5) 37 | @Null 38 | String icon(); 39 | 40 | @OneToMany(mappedBy = "menu") 41 | List roles(); 42 | 43 | 44 | @GenField(value = "是否可见") 45 | boolean visible(); 46 | } 47 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/oss/OSSRepository.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.oss; 2 | 3 | import cn.dev33.satoken.stp.StpUtil; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import io.qifan.server.dict.model.DictConstants; 6 | import lombok.AllArgsConstructor; 7 | import lombok.SneakyThrows; 8 | import org.springframework.data.redis.core.StringRedisTemplate; 9 | import org.springframework.stereotype.Repository; 10 | import org.springframework.util.StringUtils; 11 | 12 | import java.util.Map; 13 | 14 | @Repository 15 | @AllArgsConstructor 16 | public class OSSRepository { 17 | public static final String OSS_SETTING = "oss:"; 18 | private final StringRedisTemplate redisTemplate; 19 | private final ObjectMapper objectMapper; 20 | 21 | @SneakyThrows 22 | public void save(OSSSetting setting) { 23 | redisTemplate.opsForValue().set(OSS_SETTING + StpUtil.getLoginIdAsString(), objectMapper.writeValueAsString(setting)); 24 | } 25 | 26 | @SneakyThrows 27 | public OSSSetting get() { 28 | String value = redisTemplate.opsForValue().get(OSS_SETTING + StpUtil.getLoginIdAsString()); 29 | if (!StringUtils.hasText(value)) { 30 | return new OSSSetting().setType(DictConstants.OssType.ALI_YUN_OSS) 31 | .setOptions(Map.of()); 32 | } 33 | return objectMapper.readValue(value, OSSSetting.class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/oss/OSSSetting.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.oss; 2 | 3 | import io.qifan.server.dict.model.DictConstants; 4 | import lombok.Data; 5 | import lombok.experimental.Accessors; 6 | 7 | import java.util.Map; 8 | 9 | @Data 10 | @Accessors(chain = true) 11 | public class OSSSetting { 12 | DictConstants.OssType type; 13 | Map options; 14 | } 15 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/oss/UniAliYunOSSService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.oss; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import io.qifan.infrastructure.oss.OSSAutoConfiguration; 5 | import io.qifan.infrastructure.oss.aliyun.AliYunOSSProperties; 6 | import io.qifan.infrastructure.oss.service.OSSService; 7 | import lombok.AllArgsConstructor; 8 | import lombok.SneakyThrows; 9 | import org.springframework.ai.model.ModelOptionsUtils; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.Map; 13 | 14 | @Service(value = "ALI_YUN_OSS") 15 | @AllArgsConstructor 16 | public class UniAliYunOSSService implements UniOSSService { 17 | private final AliYunOSSProperties properties; 18 | private final ObjectMapper objectMapper; 19 | 20 | @SneakyThrows 21 | @Override 22 | public OSSService getOSSService(Map oss) { 23 | String valueAsString = objectMapper.writeValueAsString(oss); 24 | AliYunOSSProperties aliYunOSSProperties = objectMapper.readValue(valueAsString, AliYunOSSProperties.class); 25 | AliYunOSSProperties merge = ModelOptionsUtils.merge(aliYunOSSProperties, properties, AliYunOSSProperties.class); 26 | OSSAutoConfiguration.AliYunConfig aliYunConfig = new OSSAutoConfiguration.AliYunConfig(); 27 | return aliYunConfig.aliYunOSSService(merge); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/oss/UniOSSService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.oss; 2 | 3 | import io.qifan.infrastructure.oss.service.OSSService; 4 | 5 | import java.util.Map; 6 | 7 | public interface UniOSSService { 8 | OSSService getOSSService(Map oss); 9 | } 10 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/oss/UniTencentSSService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.oss; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import io.qifan.infrastructure.oss.OSSAutoConfiguration; 5 | import io.qifan.infrastructure.oss.service.OSSService; 6 | import io.qifan.infrastructure.oss.tencent.TencentOSSProperties; 7 | import lombok.AllArgsConstructor; 8 | import lombok.SneakyThrows; 9 | import org.springframework.ai.model.ModelOptionsUtils; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.Map; 13 | 14 | @Service(value = "TENCENT_OSS") 15 | @AllArgsConstructor 16 | public class UniTencentSSService implements UniOSSService { 17 | private final ObjectMapper objectMapper; 18 | private final TencentOSSProperties properties; 19 | 20 | @SneakyThrows 21 | @Override 22 | public OSSService getOSSService(Map oss) { 23 | String valueAsString = objectMapper.writeValueAsString(oss); 24 | TencentOSSProperties ossProperties = objectMapper.readValue(valueAsString, TencentOSSProperties.class); 25 | TencentOSSProperties merge = ModelOptionsUtils.merge(ossProperties, properties, TencentOSSProperties.class); 26 | OSSAutoConfiguration.TencentConfig tenantConfig = new OSSAutoConfiguration.TencentConfig(); 27 | return tenantConfig.tencentOSSService(merge); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/role/entity/Role.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.role.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 6 | import io.qifan.server.menu.entity.Menu; 7 | import io.qifan.server.user.root.entity.UserRoleRel; 8 | import org.babyfish.jimmer.sql.Entity; 9 | import org.babyfish.jimmer.sql.Key; 10 | import org.babyfish.jimmer.sql.ManyToManyView; 11 | import org.babyfish.jimmer.sql.OneToMany; 12 | 13 | import java.util.List; 14 | 15 | @GenEntity 16 | @Entity 17 | public interface Role extends BaseEntity { 18 | 19 | @GenField(value = "角色名称") 20 | @Key 21 | String name(); 22 | 23 | @OneToMany(mappedBy = "role") 24 | List users(); 25 | 26 | @OneToMany(mappedBy = "role") 27 | List menus(); 28 | 29 | @ManyToManyView(prop = "menus") 30 | List menusView(); 31 | } 32 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/role/entity/RoleMenuRel.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.role.entity; 2 | 3 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 4 | import io.qifan.server.menu.entity.Menu; 5 | import org.babyfish.jimmer.sql.*; 6 | 7 | @Entity 8 | public interface RoleMenuRel extends BaseEntity { 9 | 10 | @OnDissociate(DissociateAction.DELETE) 11 | @ManyToOne 12 | @Key 13 | Role role(); 14 | 15 | @OnDissociate(DissociateAction.DELETE) 16 | @ManyToOne 17 | @Key 18 | Menu menu(); 19 | } 20 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/setting/Setting.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.setting; 2 | 3 | import lombok.Data; 4 | 5 | import java.math.BigDecimal; 6 | 7 | @Data 8 | public class Setting { 9 | private BigDecimal ocrPrice; 10 | private BigDecimal tokenPrice; 11 | } 12 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/setting/SettingController.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.setting; 2 | 3 | import lombok.AllArgsConstructor; 4 | import org.springframework.web.bind.annotation.*; 5 | 6 | @RestController 7 | @RequestMapping("setting") 8 | @AllArgsConstructor 9 | public class SettingController { 10 | private final SettingRepository settingRepository; 11 | 12 | @GetMapping 13 | public Setting get() { 14 | return settingRepository.get(); 15 | } 16 | 17 | @PostMapping 18 | public void saveSetting(@RequestBody Setting setting) { 19 | settingRepository.save(setting); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/setting/SettingRepository.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.setting; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import lombok.AllArgsConstructor; 5 | import lombok.SneakyThrows; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | @AllArgsConstructor 11 | public class SettingRepository { 12 | public static final String KEY = "setting"; 13 | private final RedisTemplate redisTemplate; 14 | private final ObjectMapper objectMapper; 15 | 16 | @SneakyThrows 17 | public Setting get() { 18 | 19 | String o = redisTemplate.opsForValue().get(KEY); 20 | if (o == null) { 21 | return new Setting(); 22 | } 23 | return objectMapper.readValue(o, Setting.class); 24 | } 25 | 26 | @SneakyThrows 27 | public void save(Setting setting) { 28 | redisTemplate.opsForValue().set(KEY, objectMapper.writeValueAsString(setting)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/user/root/entity/UserRoleRel.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.user.root.entity; 2 | 3 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 4 | import io.qifan.server.role.entity.Role; 5 | import org.babyfish.jimmer.sql.*; 6 | 7 | @Entity 8 | public interface UserRoleRel extends BaseEntity { 9 | 10 | @ManyToOne 11 | @Key 12 | @OnDissociate(DissociateAction.DELETE) 13 | User user(); 14 | 15 | @OnDissociate(DissociateAction.DELETE) 16 | @ManyToOne 17 | @Key 18 | Role role(); 19 | } 20 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/user/root/repository/UserRoleRelRepository.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.user.root.repository; 2 | 3 | import io.qifan.server.user.root.entity.UserRoleRel; 4 | import org.babyfish.jimmer.spring.repository.JRepository; 5 | 6 | public interface UserRoleRelRepository extends JRepository { 7 | } 8 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/user/wechat/entity/UserWeChat.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.user.wechat.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.server.infrastructure.jimmer.BaseDateTime; 6 | import io.qifan.server.infrastructure.jimmer.UUIDIdGenerator; 7 | import io.qifan.server.user.root.entity.User; 8 | import org.babyfish.jimmer.sql.*; 9 | 10 | 11 | /** 12 | * Entity for table "user_wechat" 13 | */ 14 | @Entity 15 | @GenEntity 16 | public interface UserWeChat extends BaseDateTime { 17 | 18 | @Id 19 | @GeneratedValue(generatorType = UUIDIdGenerator.class) 20 | String id(); 21 | 22 | @Key 23 | @GenField(value = "openId", order = 0) 24 | String openId(); 25 | 26 | @OneToOne 27 | User user(); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/user/wechat/model/UserWeChatRegisterInput.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.user.wechat.model; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class UserWeChatRegisterInput { 7 | 8 | private String inviteCode; 9 | private String loginCode; 10 | private String phone; 11 | private String code; 12 | } 13 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/user/wechat/model/UserWeChatRegisterInputV2.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.user.wechat.model; 2 | 3 | import jakarta.validation.constraints.NotNull; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class UserWeChatRegisterInputV2 { 8 | @NotNull 9 | String phoneCode; 10 | @NotNull 11 | String loginCode; 12 | String inviteCode; 13 | } 14 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/wallet/item/entity/WalletItem.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.wallet.item.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 7 | import org.babyfish.jimmer.sql.Entity; 8 | import org.babyfish.jimmer.sql.Table; 9 | 10 | import java.math.BigDecimal; 11 | 12 | 13 | /** 14 | *

15 | * 钱包充值的可选项 16 | * 17 | *

18 | * 19 | * @author 起凡 20 | * @date 2024-04-27 21 | */ 22 | @Entity 23 | @Table(name = "wallet_item") 24 | @GenEntity 25 | public interface WalletItem extends BaseEntity { 26 | 27 | /** 28 | * 充值项名称 29 | */ 30 | @GenField(value = "充值项名称", order = 0) 31 | String name(); 32 | 33 | /** 34 | * 购买后得到的金额 35 | */ 36 | @GenField(value = "购买后得到的金额", type = ItemType.INPUT_NUMBER, order = 1) 37 | BigDecimal amount(); 38 | 39 | /** 40 | * 售卖价格 41 | */ 42 | @GenField(value = "售卖价格", type = ItemType.INPUT_NUMBER, order = 2) 43 | BigDecimal price(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/wallet/item/service/WalletItemService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.wallet.item.service; 2 | 3 | import io.qifan.server.wallet.item.repository.WalletItemRepository; 4 | import lombok.AllArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Slf4j 11 | @AllArgsConstructor 12 | @Transactional 13 | public class WalletItemService { 14 | private final WalletItemRepository walletItemRepository; 15 | 16 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/wallet/root/entity/Wallet.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.wallet.root.entity; 2 | 3 | import io.qifan.infrastructure.generator.core.GenEntity; 4 | import io.qifan.infrastructure.generator.core.GenField; 5 | import io.qifan.infrastructure.generator.core.ItemType; 6 | import io.qifan.server.infrastructure.jimmer.BaseEntity; 7 | import io.qifan.server.user.root.entity.User; 8 | import org.babyfish.jimmer.sql.*; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.math.BigDecimal; 12 | 13 | 14 | /** 15 | *

16 | * 用户钱包 17 | * 18 | *

19 | * 20 | * @author 起凡 21 | * @date 2024-04-27 22 | */ 23 | @Entity 24 | @Table(name = "wallet") 25 | @GenEntity 26 | public interface Wallet extends BaseEntity { 27 | 28 | /** 29 | * 余额 30 | */ 31 | @GenField(value = "余额", order = 0, type = ItemType.INPUT_NUMBER) 32 | BigDecimal balance(); 33 | 34 | /** 35 | * 钱包密码 36 | */ 37 | @Nullable 38 | @GenField(value = "钱包密码", order = 1) 39 | String password(); 40 | 41 | /** 42 | * 用户id 43 | */ 44 | @IdView 45 | String userId(); 46 | 47 | @Key 48 | @ManyToOne 49 | @OnDissociate(DissociateAction.DELETE) 50 | User user(); 51 | 52 | } 53 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/java/io/qifan/server/wallet/stats/WalletRecordStats.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server.wallet.stats; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class WalletRecordStats { 7 | String phone; 8 | 9 | String nickname; 10 | 11 | Integer num; 12 | } 13 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | data: 3 | redis: 4 | database: 0 5 | timeout: 10s 6 | lettuce: 7 | pool: 8 | # 连接池最大连接数 9 | max-active: 200 10 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 11 | max-wait: -1ms 12 | # 连接池中的最大空闲连接 13 | max-idle: 10 14 | # 连接池中的最小空闲连接 15 | min-idle: 0 16 | repositories: 17 | enabled: false 18 | password: 123456 19 | datasource: 20 | url: jdbc:mysql://localhost:3306/uni_ai 21 | username: root 22 | password: 123456 23 | driver-class-name: com.mysql.cj.jdbc.Driver 24 | security: 25 | enabled: true 26 | jimmer: 27 | dialect: org.babyfish.jimmer.sql.dialect.MySqlDialect 28 | show-sql: true 29 | pretty-sql: true 30 | client: 31 | ts: 32 | path: /ts.zip 33 | openapi: 34 | path: /openapi 35 | ui-path: /openapi-ui 36 | trigger-type: transaction_only 37 | # 微信支付回调 38 | wx: 39 | pay: 40 | notify-url: https://www.jarcheng.top/test-api -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | data: 3 | redis: 4 | database: 4 5 | host: redis 6 | timeout: 10s 7 | lettuce: 8 | pool: 9 | # 连接池最大连接数 10 | max-active: 200 11 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 12 | max-wait: -1ms 13 | # 连接池中的最大空闲连接 14 | max-idle: 10 15 | # 连接池中的最小空闲连接 16 | min-idle: 0 17 | password: 123456 18 | repositories: 19 | enabled: false 20 | datasource: 21 | url: jdbc:mysql://mysql:3306/uni_ai 22 | username: root 23 | password: 123456 24 | driver-class-name: com.mysql.cj.jdbc.Driver 25 | security: 26 | enabled: true 27 | jimmer: 28 | dialect: org.babyfish.jimmer.sql.dialect.MySqlDialect 29 | show-sql: true 30 | pretty-sql: true 31 | trigger-type: transaction_only 32 | # 微信支付回调 33 | wx: 34 | pay: 35 | notify-url: https://www.jarcheng.top/test-api 36 | 37 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/logback/logback-dev.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | UTF-8 8 | ${CONSOLE_LOG_PATTERN} 9 | 10 | 11 | 13 | 14 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/templates/dict-java.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="io.qifan.server.dict.model.DictGenContext" --> 2 | package io.qifan.server.dict.model; 3 | import lombok.Getter; 4 | import lombok.AllArgsConstructor; 5 | 6 | public class DictConstants { 7 | <#list getDictTypes() as type> 8 | public static final String ${getDictMap()[type][0].dictEnName()} = "${getDictMap()[type][0].dictEnName()}"; 9 | 10 | <#list getDictTypes() as type> 11 | @Getter 12 | @AllArgsConstructor 13 | public enum ${type}{ 14 | <#list getDictMap()[type] as dict> 15 | ${dict.keyEnName()}(${dict.keyId()?c}, "${dict.keyName()}", "${dict.keyEnName()}", ${dict.dictId()?c}, "${dict.dictName()}", "${dict.dictEnName()}", ${dict.orderNum()?c}), 16 | 17 | ; 18 | final int keyId; 19 | final String keyName; 20 | final String keyEnName; 21 | final int dictId; 22 | final String dictName; 23 | final String dictEnName; 24 | final int orderNum; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/templates/dict-ts.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="io.qifan.mall.server.dict.model.DictGenContext" --> 2 | 3 | export const DictConstants = { 4 | <#list getDictTypes() as type> 5 | ${getDictMap()[type][0].dictEnName()}: ${getDictMap()[type][0].dictId()?c}, 6 | 7 | } 8 | export const Dictionaries = { 9 | <#list getDictTypes() as type> 10 | ${type}: { 11 | <#list getDictMap()[type] as dict> 12 | ${dict.keyEnName()}: { 13 | keyId: ${dict.keyId()?c}, 14 | keyName: '${dict.keyName()}', 15 | keyEnName: '${dict.keyEnName()}', 16 | dictId: ${dict.dictId()?c}, 17 | dictName: '${dict.dictName()}', 18 | dictEnName: '${dict.dictEnName()}', 19 | orderNum: ${dict.orderNum()?c} 20 | }, 21 | 22 | }, 23 | 24 | } -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/wechat/apiclient_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | xxxxx 3 | -----END CERTIFICATE----- 4 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/main/resources/wechat/apiclient_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | xxxxx 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /uni-ai-backend/server/src/test/java/io/qifan/server/CodeGenerator.java: -------------------------------------------------------------------------------- 1 | package io.qifan.server; 2 | 3 | import io.qifan.infrastructure.generator.processor.QiFanGenerator; 4 | 5 | public class CodeGenerator { 6 | 7 | public static void main(String[] args) { 8 | QiFanGenerator qiFanGenerator = new QiFanGenerator(); 9 | System.out.println("生成代码"); 10 | qiFanGenerator.process("io.qifan.server", "template"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-oss/src/main/java/io/qifan/infrastructure/oss/OSSProperties.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.oss; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | enum Provider { 7 | ALI_YUN, 8 | LOCAL, 9 | TENCENT; 10 | } 11 | 12 | @Data 13 | @ConfigurationProperties(prefix = "oss") 14 | public class OSSProperties { 15 | 16 | private Provider provider; 17 | } 18 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-oss/src/main/java/io/qifan/infrastructure/oss/aliyun/AliYunOSSProperties.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.oss.aliyun; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | @Data 8 | @ConfigurationProperties(prefix = "oss.ali-yun") 9 | public class AliYunOSSProperties { 10 | @JsonProperty("endpoint") 11 | private String endpoint; 12 | @JsonProperty("bucketName") 13 | private String bucketName; 14 | @JsonProperty("accessKeyId") 15 | private String accessKeyId; 16 | @JsonProperty("accessKeySecret") 17 | private String accessKeySecret; 18 | } 19 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-oss/src/main/java/io/qifan/infrastructure/oss/local/LocalOSSProperties.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.oss.local; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | 7 | @Data 8 | @ConfigurationProperties(prefix = "oss.local") 9 | public class LocalOSSProperties { 10 | private String path; 11 | private String url; 12 | } 13 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-oss/src/main/java/io/qifan/infrastructure/oss/service/OSSService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.oss.service; 2 | 3 | import org.springframework.web.multipart.MultipartFile; 4 | 5 | import java.io.InputStream; 6 | 7 | public interface OSSService { 8 | String upload(MultipartFile multipartFile); 9 | 10 | String upload(String objectName, InputStream inputStream); 11 | Boolean delete(String objectName); 12 | } 13 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-oss/src/main/java/io/qifan/infrastructure/oss/tencent/TencentOSSProperties.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.oss.tencent; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | @Data 7 | @ConfigurationProperties(prefix = "oss.tencent") 8 | public class TencentOSSProperties { 9 | private String secretId; 10 | private String secretKey; 11 | private String region; 12 | private String bucket; 13 | } 14 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-oss/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | io.qifan.infrastructure.oss.OSSAutoConfiguration -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-security/src/main/java/io/qifan/infrastructure/security/AuthAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.security; 2 | 3 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Import; 6 | 7 | @Configuration 8 | @ConditionalOnProperty(prefix = "security", name = "enabled", havingValue = "true") 9 | public class AuthAutoConfiguration { 10 | @Configuration 11 | @Import(WebConfig.class) 12 | public static class SecurityConfig { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-security/src/main/java/io/qifan/infrastructure/security/SecurityProperties.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.security; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | @ConfigurationProperties(prefix = "security") 7 | @Data 8 | public class SecurityProperties { 9 | private Boolean enabled = true; 10 | } 11 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-security/src/main/java/io/qifan/infrastructure/security/WebConfig.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.security; 2 | 3 | 4 | import cn.dev33.satoken.interceptor.SaInterceptor; 5 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | @Configuration 11 | @EnableConfigurationProperties(SecurityProperties.class) 12 | public class WebConfig implements WebMvcConfigurer { 13 | 14 | 15 | @Override 16 | public void addInterceptors(InterceptorRegistry registry) { 17 | registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | io.qifan.infrastructure.security.AuthAutoConfiguration -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-sms/src/main/java/io/qifan/infrastructure/sms/DefaultSmsService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.sms; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.data.redis.core.StringRedisTemplate; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | @Service 11 | @AllArgsConstructor 12 | @Slf4j 13 | public class DefaultSmsService implements SmsService { 14 | private final StringRedisTemplate redisTemplate; 15 | 16 | @Override 17 | public String sendSms(String phone) { 18 | // if (redisTemplate.opsForValue().get(SMS_KEY + phone) != null) { 19 | // throw new BusinessException(ResultCode.TransferStatusError, "120秒内请勿重复获取验证码"); 20 | // } 21 | String code = SmsService.codeBuilder(); 22 | redisTemplate.opsForValue().set(SMS_KEY + phone, code, 2, TimeUnit.MINUTES); 23 | log.info("验证码:{}", code); 24 | return code; 25 | } 26 | 27 | @Override 28 | public boolean checkSms(String phone, String code) { 29 | boolean equals = code.equals(redisTemplate.opsForValue().get(SMS_KEY + phone)); 30 | if (equals) { 31 | redisTemplate.delete(SMS_KEY + phone); 32 | } 33 | return equals; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-sms/src/main/java/io/qifan/infrastructure/sms/SmsController.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.sms; 2 | 3 | import io.qifan.infrastructure.common.model.R; 4 | import lombok.AllArgsConstructor; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | @AllArgsConstructor 12 | @RequestMapping("sms") 13 | public class SmsController { 14 | private final SmsService smsService; 15 | 16 | @PostMapping("send") 17 | public R sendSms(@RequestParam String phone) { 18 | smsService.sendSms(phone); 19 | return R.ok(true); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-sms/src/main/java/io/qifan/infrastructure/sms/SmsProperties.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.sms; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | enum Provider { 7 | NONE, 8 | ALI_YUN; 9 | } 10 | 11 | @Data 12 | @ConfigurationProperties(prefix = "sms") 13 | public class SmsProperties { 14 | private Provider provider; 15 | } 16 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-sms/src/main/java/io/qifan/infrastructure/sms/SmsService.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.sms; 2 | 3 | import java.util.Random; 4 | 5 | public interface SmsService { 6 | String SMS_KEY = "sms."; 7 | 8 | static String codeBuilder() { 9 | StringBuilder code = new StringBuilder(); 10 | for (int i = 0; i < 4; i++) { 11 | code.append(new Random().nextInt(10)); 12 | } 13 | return code.toString(); 14 | } 15 | 16 | String sendSms(String phone); 17 | 18 | boolean checkSms(String phone, String code); 19 | } 20 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-sms/src/main/java/io/qifan/infrastructure/sms/aliyun/AliYunSmsProperties.java: -------------------------------------------------------------------------------- 1 | package io.qifan.infrastructure.sms.aliyun; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | @Data 7 | @ConfigurationProperties(prefix = "sms.ali-yun") 8 | public class AliYunSmsProperties { 9 | private String accessKeyId; 10 | private String accessKeySecret; 11 | private String signName; 12 | private String templateCode; 13 | } 14 | -------------------------------------------------------------------------------- /uni-ai-backend/spring-boot-starter-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | io.qifan.infrastructure.sms.SmsAutoConfiguration --------------------------------------------------------------------------------