feat: collaboration and statistics
This commit is contained in:
@@ -5,6 +5,7 @@ root = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
@@ -12,4 +13,3 @@ trim_trailing_whitespace = true
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# Common
|
||||
.DS_Store
|
||||
.idea/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.log
|
||||
*.swp
|
||||
|
||||
# Frontend workspace
|
||||
/frontend/**/node_modules/
|
||||
/frontend/**/.eslintcache
|
||||
/frontend/**/tsconfig.tsbuildinfo
|
||||
/frontend/**/*.local
|
||||
|
||||
# Frontend app
|
||||
/frontend/app/dist/
|
||||
/frontend/app/deploy_versions/
|
||||
/frontend/app/.temp/
|
||||
/frontend/app/.rn_temp/
|
||||
/frontend/app/.swc
|
||||
|
||||
# Frontend web
|
||||
/frontend/web/dist/
|
||||
/frontend/web/dist-ssr/
|
||||
/frontend/web/report.html
|
||||
/frontend/web/yarn.lock
|
||||
/frontend/web/npm-debug.log*
|
||||
/frontend/web/.pnpm-error.log*
|
||||
/frontend/web/.pnpm-debug.log
|
||||
/frontend/web/tests/**/coverage/
|
||||
/frontend/web/.vscode/launch.json
|
||||
|
||||
# Backend build tools
|
||||
/backend/.gradle/
|
||||
/backend/build/
|
||||
!/backend/gradle/wrapper/gradle-wrapper.jar
|
||||
/backend/**/target/
|
||||
!/backend/.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
# Backend IDE
|
||||
/backend/**/.apt_generated
|
||||
/backend/**/.classpath
|
||||
/backend/**/.factorypath
|
||||
/backend/**/.project
|
||||
/backend/**/.settings/
|
||||
/backend/**/.springBeans
|
||||
|
||||
# Backend JRebel
|
||||
/backend/**/rebel.xml
|
||||
|
||||
# Backend NetBeans
|
||||
/backend/nbproject/private/
|
||||
/backend/build/*
|
||||
/backend/nbbuild/
|
||||
/backend/dist/
|
||||
/backend/nbdist/
|
||||
/backend/.nb-gradle/
|
||||
|
||||
# Backend generated files
|
||||
/backend/**/*.xml.versionsBackup
|
||||
!/backend/*/build/*.java
|
||||
!/backend/*/build/*.html
|
||||
!/backend/*/build/*.xml
|
||||
|
||||
# Backend local configuration
|
||||
/backend/agileboot-admin/src/main/resources/application-prod.yml
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"EditorConfig.EditorConfig",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"stylelint.vscode-stylelint",
|
||||
"Vue.volar",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"mikestead.dotenv",
|
||||
"antfu.iconify"
|
||||
]
|
||||
}
|
||||
+26
-15
@@ -1,32 +1,43 @@
|
||||
{
|
||||
"editor.formatOnType": true,
|
||||
"editor.formatOnSave": true,
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.detectIndentation": false,
|
||||
"editor.tabSize": 2,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.guides.bracketPairs": "active",
|
||||
"files.autoSave": "afterDelay",
|
||||
"git.confirmSync": false,
|
||||
"workbench.startupEditor": "newUntitledFile",
|
||||
"editor.snippetSuggestions": "top",
|
||||
"editor.suggestSelection": "first",
|
||||
"editor.acceptSuggestionOnCommitCharacter": false,
|
||||
"css.lint.propertyIgnoredDueToDisplay": "ignore",
|
||||
"editor.quickSuggestions": {
|
||||
"other": true,
|
||||
"comments": true,
|
||||
"strings": true
|
||||
},
|
||||
"files.associations": {
|
||||
"editor.snippetSuggestions": "top"
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.stylelint": "explicit"
|
||||
},
|
||||
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "vue"],
|
||||
"stylelint.validate": ["css", "scss", "vue"],
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"iconify.excludes": ["el"],
|
||||
"cSpell.words": ["iconify", "Qrcode"]
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"css.lint.propertyIgnoredDueToDisplay": "ignore",
|
||||
"files.autoSave": "afterDelay",
|
||||
"git.confirmSync": false,
|
||||
"workbench.startupEditor": "newUntitledFile",
|
||||
"iconify.excludes": ["el"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Agent Rules
|
||||
|
||||
- 新增或修改代码前,必须阅读并遵循 `docs/clean-code-contract.md`。
|
||||
- 后端新增或修改业务功能前,必须阅读 `docs/backend-feature-development.md`。
|
||||
- 后端代码必须遵循 `Controller -> ApplicationService -> Model -> db Service/Mapper` 的组织方式。
|
||||
- 不要把业务规则写在 Controller。
|
||||
- 不要让 Controller 直接调用 Mapper。
|
||||
- 不要直接把 Entity 或 DO 返回给前端。
|
||||
- 复杂查询结果对象可以使用 `XxxDO`,放在 `db` 包下,并由 ApplicationService 转换为 DTO。
|
||||
- 字典类需求不要默认创建字典管理表;本项目现有字典数据使用 Enum 和缓存。
|
||||
- `frontend/web` 新增或修改业务功能前,必须阅读 `docs/web-feature-development.md`。
|
||||
- Web 前端接口必须通过 `@/utils/http` 封装调用,不要直接使用 Axios。
|
||||
- Web 列表页复杂状态和行为应放在 `utils/hook.tsx`,不要堆在 `index.vue`。
|
||||
- Web 页面私有组件放在当前模块的 `components/`,多模块复用组件提升到 `frontend/web/src/components`。
|
||||
- Web 字典展示优先使用 `useUserStoreHook().dictionaryList` 或 `dictionaryMap`,不要硬编码状态文本和值。
|
||||
@@ -34,8 +34,31 @@ cd backend
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
On a fresh Docker volume, Compose creates the MySQL database `agileboot_pure`.
|
||||
Import the SQL files under `backend/sql/` before starting the backend.
|
||||
The compose configuration mounts `backend/sql/agileboot.sql` into the MySQL
|
||||
container as `/docker-entrypoint-initdb.d/01-agileboot.sql`.
|
||||
The official MySQL image only runs files in `/docker-entrypoint-initdb.d` when
|
||||
the database directory is empty, during the first initialization of the
|
||||
`mysql_data` volume.
|
||||
|
||||
If MySQL has already been started before, the `mysql_data` volume already
|
||||
contains data and `docker compose up -d` will not import the SQL again. To
|
||||
reinitialize the local database, remove the volumes first:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
docker compose down -v
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Warning: `docker compose down -v` deletes the local MySQL and Redis volumes,
|
||||
including existing database data and Redis data.
|
||||
|
||||
If you do not want to delete the volumes, import the SQL manually:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
docker exec -i mysql-server mysql -uroot -proot123 agileboot_pure < sql/agileboot.sql
|
||||
```
|
||||
|
||||
### Install Frontend Dependencies
|
||||
|
||||
@@ -50,7 +73,7 @@ Start the backend:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
./mvnw -pl agileboot-admin -am spring-boot:run
|
||||
./mvnw -pl agileboot-admin spring-boot:run
|
||||
```
|
||||
|
||||
Start the web frontend:
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
---
|
||||
name: Bug 报告
|
||||
about: 创建BUG报告以改进项目
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**BUG描述**
|
||||
关于BUG清晰简洁的描述。
|
||||
|
||||
**复现步骤**
|
||||
详细的复现步骤。
|
||||
|
||||
|
||||
**正确的行为**
|
||||
你认为这个修复这个BUG后,正确的行为应该是什么。
|
||||
|
||||
|
||||
**详细截图**
|
||||
如果可以的话,请添加截图以帮助调查BUG.
|
||||
|
||||
**桌面端:**
|
||||
- 操作系统: [例如. iOS]
|
||||
- 浏览器及版本 [例如. chrome 11]
|
||||
- 项目版本 [例如. 1.6.0]
|
||||
|
||||
**手机端:**
|
||||
- 设备: [例如. iPhone6]
|
||||
- 操作系统: [例如. iOS8.1]
|
||||
- 浏览器及版本 [例如.safari 8]
|
||||
- 项目版本 [例如. 1.6.0]
|
||||
|
||||
**Additional context**
|
||||
任何其他你认为有助于排查错误的信息,或者你的猜测。
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: 功能建议
|
||||
about: 关于该项目的建议
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**您的功能请求是否与问题相关? 请描述。**
|
||||
清楚简明地描述问题所在。
|
||||
|
||||
**描述您想要的解决方案**
|
||||
对您所设想的问题的清晰简洁的描述。
|
||||
|
||||
**描述您考虑过的替代方案**
|
||||
对您考虑过的任何替代解决方案或功能的清晰简洁的描述。
|
||||
|
||||
**附加上下文**
|
||||
在此处添加有关功能请求的任何其他上下文或屏幕截图。
|
||||
Vendored
-116
@@ -1,116 +0,0 @@
|
||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
|
||||
|
||||
# 权限声明,确保 workflow 有权限写 checks 和 security-events
|
||||
permissions:
|
||||
contents: read
|
||||
checks: write
|
||||
security-events: write
|
||||
|
||||
name: Java CI with Maven
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'LICENSE'
|
||||
- '.gitignore'
|
||||
- '.gitattributes'
|
||||
- 'picture'
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: ['8', '17', '21']
|
||||
fail-fast: false
|
||||
|
||||
name: Build with Java ${{ matrix.java-version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK ${{ matrix.java-version }}
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java-version }}
|
||||
distribution: 'temurin'
|
||||
cache: 'maven'
|
||||
|
||||
# 优化Maven本地仓库缓存策略
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}-${{ matrix.java-version }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-m2-
|
||||
|
||||
# 编译和测试:去掉failOnWarning,避免因为警告导致失败
|
||||
- name: Build and Test with Maven
|
||||
run: |
|
||||
mvn -B verify --file pom.xml -Dmaven.test.failure.ignore=false -Dgpg.skip -Dmaven.javadoc.skip=false
|
||||
env:
|
||||
MAVEN_OPTS: -Xmx4g -XX:MaxMetaspaceSize=1g
|
||||
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
|
||||
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@v4
|
||||
if: success() || failure()
|
||||
with:
|
||||
report_paths: '**/target/surefire-reports/TEST-*.xml'
|
||||
detailed_summary: true
|
||||
include_passed: true
|
||||
fail_on_failure: true
|
||||
|
||||
- name: Run SonarQube Analysis
|
||||
if: matrix.java-version == '17' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if [[ ! -z "${{ secrets.SONAR_TOKEN }}" ]]; then
|
||||
mvn sonar:sonar \
|
||||
-Dsonar.projectKey=agileboot \
|
||||
-Dsonar.organization=${{ secrets.SONAR_ORGANIZATION || 'default' }} \
|
||||
-Dsonar.host.url=${{ secrets.SONAR_HOST_URL || 'https://sonarcloud.io' }} \
|
||||
-Dsonar.login=${{ secrets.SONAR_TOKEN }} \
|
||||
-Dsonar.java.source=${{ matrix.java-version }}
|
||||
else
|
||||
echo "Skipping SonarQube analysis - SONAR_TOKEN not configured"
|
||||
fi
|
||||
|
||||
# 上传构建产物,if-no-files-found 改为 warn
|
||||
- name: Upload Build Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: agileboot-artifacts-java-${{ matrix.java-version }}
|
||||
path: |
|
||||
**/target/*.jar
|
||||
!**/target/original-*.jar
|
||||
retention-days: 5
|
||||
if-no-files-found: warn
|
||||
|
||||
# # 只在 Java 17 版本上更新依赖图(权限和token已修复)
|
||||
# - name: Update dependency graph
|
||||
# uses: advanced-security/maven-dependency-submission-action@v4
|
||||
# if: matrix.java-version == '17' && success()
|
||||
# with:
|
||||
# token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# # 发送构建状态通知
|
||||
# - name: Notify Build Status
|
||||
# if: always()
|
||||
# uses: rtCamp/action-slack-notify@v2.2.1
|
||||
# env:
|
||||
# SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK || '' }}
|
||||
# SLACK_CHANNEL: build-notifications
|
||||
# SLACK_COLOR: ${{ job.status }}
|
||||
# SLACK_TITLE: Build Status for Java ${{ matrix.java-version }}
|
||||
# SLACK_MESSAGE: 'Build ${{ job.status }} on Java ${{ matrix.java-version }}'
|
||||
@@ -1,50 +0,0 @@
|
||||
######################################################################
|
||||
# Build Tools
|
||||
|
||||
.gradle
|
||||
/build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################################################################
|
||||
# IDE
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### JRebel ###
|
||||
rebel.xml
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/*
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
######################################################################
|
||||
# Others
|
||||
*.log
|
||||
*.xml.versionsBackup
|
||||
*.swp
|
||||
|
||||
!*/build/*.java
|
||||
!*/build/*.html
|
||||
!*/build/*.xml
|
||||
|
||||
/agileboot-admin/src/main/resources/application-prod.yml
|
||||
|
||||
@@ -148,7 +148,9 @@
|
||||
<option name="FOR_BRACE_FORCE" value="3" />
|
||||
<option name="WRAP_ON_TYPING" value="0" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JSON">
|
||||
@@ -564,4 +566,4 @@
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</code_scheme>
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package com.agileboot.admin.controller.collaboration;
|
||||
|
||||
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
|
||||
import com.agileboot.common.core.base.BaseController;
|
||||
import com.agileboot.common.core.dto.ResponseDTO;
|
||||
import com.agileboot.common.core.page.PageDTO;
|
||||
import com.agileboot.common.enums.common.BusinessTypeEnum;
|
||||
import com.agileboot.domain.collaboration.record.CollaborationRecordApplicationService;
|
||||
import com.agileboot.domain.collaboration.record.command.AddCollaborationRecordCommand;
|
||||
import com.agileboot.domain.collaboration.record.command.UpdateCollaborationRecordCommand;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationMonthlyStatisticsDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationOptionDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationRecordDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationRecordDetailDTO;
|
||||
import com.agileboot.domain.collaboration.record.query.CollaborationRecordQuery;
|
||||
import com.agileboot.domain.common.command.BulkOperationCommand;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Positive;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Tag(name = "合作记录API", description = "合作记录相关的增删查改和统计")
|
||||
@RestController
|
||||
@RequestMapping("/collaboration/record")
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
public class CollaborationRecordController extends BaseController {
|
||||
|
||||
private final CollaborationRecordApplicationService recordApplicationService;
|
||||
|
||||
@Operation(summary = "合作记录列表")
|
||||
@PreAuthorize("@permission.has('collaboration:record:list')")
|
||||
@GetMapping("/list")
|
||||
public ResponseDTO<PageDTO<CollaborationRecordDTO>> list(CollaborationRecordQuery query) {
|
||||
return ResponseDTO.ok(recordApplicationService.getRecordList(query));
|
||||
}
|
||||
|
||||
@Operation(summary = "合作记录详情")
|
||||
@PreAuthorize("@permission.has('collaboration:record:query')")
|
||||
@GetMapping("/{recordId}")
|
||||
public ResponseDTO<CollaborationRecordDetailDTO> getInfo(@PathVariable @Positive Long recordId) {
|
||||
return ResponseDTO.ok(recordApplicationService.getRecordInfo(recordId));
|
||||
}
|
||||
|
||||
@Operation(summary = "合作记录选项")
|
||||
@PreAuthorize("@permission.has('collaboration:record:list')")
|
||||
@GetMapping("/options")
|
||||
public ResponseDTO<List<CollaborationOptionDTO>> options() {
|
||||
return ResponseDTO.ok(recordApplicationService.getOptions());
|
||||
}
|
||||
|
||||
@Operation(summary = "合作记录月度统计")
|
||||
@PreAuthorize("@permission.has('collaboration:record:statistics')")
|
||||
@GetMapping("/monthly-statistics")
|
||||
public ResponseDTO<List<CollaborationMonthlyStatisticsDTO>> monthlyStatistics(@RequestParam Integer year) {
|
||||
return ResponseDTO.ok(recordApplicationService.getMonthlyStatistics(year));
|
||||
}
|
||||
|
||||
@Operation(summary = "新增合作记录")
|
||||
@PreAuthorize("@permission.has('collaboration:record:add')")
|
||||
@AccessLog(title = "合作记录", businessType = BusinessTypeEnum.ADD)
|
||||
@PostMapping
|
||||
public ResponseDTO<Void> add(@Valid @RequestBody AddCollaborationRecordCommand command) {
|
||||
recordApplicationService.addRecord(command);
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改合作记录")
|
||||
@PreAuthorize("@permission.has('collaboration:record:edit')")
|
||||
@AccessLog(title = "合作记录", businessType = BusinessTypeEnum.MODIFY)
|
||||
@PutMapping
|
||||
public ResponseDTO<Void> edit(@Valid @RequestBody UpdateCollaborationRecordCommand command) {
|
||||
recordApplicationService.updateRecord(command);
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除合作记录")
|
||||
@PreAuthorize("@permission.has('collaboration:record:remove')")
|
||||
@AccessLog(title = "合作记录", businessType = BusinessTypeEnum.DELETE)
|
||||
@DeleteMapping
|
||||
public ResponseDTO<Void> remove(@RequestParam @NotNull @NotEmpty List<Long> ids) {
|
||||
recordApplicationService.deleteRecord(new BulkOperationCommand<>(ids));
|
||||
return ResponseDTO.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,7 +50,7 @@ spring:
|
||||
datasource:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://localhost:3306/agileboot_pure?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://localhost:33061/todo_agileboot_pure?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: root123
|
||||
# 从库数据源
|
||||
@@ -64,7 +64,7 @@ spring:
|
||||
# 地址
|
||||
host: localhost
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
port: 63791
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
@@ -84,7 +84,7 @@ spring:
|
||||
|
||||
logging:
|
||||
file:
|
||||
path: D:/logs/agileboot-dev
|
||||
path: /home/agileboot/logs/agileboot-dev
|
||||
|
||||
|
||||
springdoc:
|
||||
@@ -98,8 +98,8 @@ springdoc:
|
||||
|
||||
# 项目相关配置
|
||||
agileboot:
|
||||
# 文件基路径 示例( Windows配置D:\agileboot,Linux配置 /home/agileboot)
|
||||
file-base-dir: D:\agileboot
|
||||
# 文件基路径 示例(Linux配置 /home/agileboot)
|
||||
file-base-dir: /home/agileboot
|
||||
# 前端url请求转发前缀
|
||||
api-prefix: /dev-api
|
||||
demo-enabled: false
|
||||
|
||||
+6
-9
@@ -6,14 +6,11 @@ import com.agileboot.common.config.AgileBootConfig;
|
||||
import com.agileboot.common.constant.Constants.UploadSubDir;
|
||||
import java.io.File;
|
||||
import javax.annotation.Resource;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@SpringBootTest(classes = AgileBootAdminApplication.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
public class AgileBootConfigTest {
|
||||
|
||||
@Resource
|
||||
@@ -21,7 +18,7 @@ public class AgileBootConfigTest {
|
||||
|
||||
@Test
|
||||
public void testConfig() {
|
||||
String fileBaseDir = "D:\\agileboot\\profile";
|
||||
String fileBaseDir = "/home/agileboot/profile";
|
||||
|
||||
Assertions.assertEquals("AgileBoot", config.getName());
|
||||
Assertions.assertEquals("1.8.0", config.getVersion());
|
||||
@@ -31,13 +28,13 @@ public class AgileBootConfigTest {
|
||||
Assertions.assertFalse(AgileBootConfig.isAddressEnabled());
|
||||
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
|
||||
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
|
||||
Assertions.assertEquals(fileBaseDir + "\\import",
|
||||
Assertions.assertEquals(fileBaseDir + "/import",
|
||||
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.IMPORT_PATH);
|
||||
Assertions.assertEquals(fileBaseDir + "\\avatar",
|
||||
Assertions.assertEquals(fileBaseDir + "/avatar",
|
||||
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.AVATAR_PATH);
|
||||
Assertions.assertEquals(fileBaseDir + "\\download",
|
||||
Assertions.assertEquals(fileBaseDir + "/download",
|
||||
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.DOWNLOAD_PATH);
|
||||
Assertions.assertEquals(fileBaseDir + "\\upload",
|
||||
Assertions.assertEquals(fileBaseDir + "/upload",
|
||||
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.UPLOAD_PATH);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -110,10 +110,10 @@ class FileUploadUtilsTest {
|
||||
@Test
|
||||
void getFileAbsolutePath() {
|
||||
AgileBootConfig agileBootConfig = new AgileBootConfig();
|
||||
agileBootConfig.setFileBaseDir("D:\\agileboot");
|
||||
agileBootConfig.setFileBaseDir("/home/agileboot");
|
||||
|
||||
String fileAbsolutePath = FileUploadUtils.getFileAbsolutePath(UploadSubDir.AVATAR_PATH, "test.jpg");
|
||||
|
||||
Assertions.assertEquals("D:\\agileboot\\profile\\avatar\\test.jpg", fileAbsolutePath);
|
||||
Assertions.assertEquals("/home/agileboot/profile/avatar/test.jpg", fileAbsolutePath);
|
||||
}
|
||||
}
|
||||
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
package com.agileboot.domain.collaboration.record;
|
||||
|
||||
import com.agileboot.common.core.page.PageDTO;
|
||||
import com.agileboot.domain.collaboration.record.command.AddCollaborationRecordCommand;
|
||||
import com.agileboot.domain.collaboration.record.command.CollaborationExpenditureCommand;
|
||||
import com.agileboot.domain.collaboration.record.command.CollaborationFileCommand;
|
||||
import com.agileboot.domain.collaboration.record.command.CollaborationSettlementCommand;
|
||||
import com.agileboot.domain.collaboration.record.command.CollaborationTaskCommand;
|
||||
import com.agileboot.domain.collaboration.record.command.UpdateCollaborationRecordCommand;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationExpenditureEntity;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationExpenditureService;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationFileEntity;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationFileService;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordEntity;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordService;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationSettlementEntity;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationSettlementService;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationTaskEntity;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationTaskService;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationExpenditureDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationFileDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationMonthlyStatisticsDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationOptionDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationRecordDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationRecordDetailDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationSettlementDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.CollaborationTaskDTO;
|
||||
import com.agileboot.domain.collaboration.record.dto.SettlementStatusDTO;
|
||||
import com.agileboot.domain.collaboration.record.enumtype.CollaborationOptionEnum;
|
||||
import com.agileboot.domain.collaboration.record.enumtype.SettlementStatusEnum;
|
||||
import com.agileboot.domain.collaboration.record.model.CollaborationRecordModel;
|
||||
import com.agileboot.domain.collaboration.record.model.CollaborationRecordModelFactory;
|
||||
import com.agileboot.domain.collaboration.record.query.CollaborationRecordQuery;
|
||||
import com.agileboot.domain.common.command.BulkOperationCommand;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CollaborationRecordApplicationService {
|
||||
|
||||
private static final String PURCHASE_FEE = "拍单费用";
|
||||
private static final String DELIVERY_FEE = "快递费用";
|
||||
private static final String REMUNERATION_FEE = "稿费";
|
||||
|
||||
private final CollaborationRecordModelFactory recordModelFactory;
|
||||
private final CollaborationRecordService recordService;
|
||||
private final CollaborationTaskService taskService;
|
||||
private final CollaborationExpenditureService expenditureService;
|
||||
private final CollaborationSettlementService settlementService;
|
||||
private final CollaborationFileService fileService;
|
||||
|
||||
public PageDTO<CollaborationRecordDTO> getRecordList(CollaborationRecordQuery query) {
|
||||
Page<CollaborationRecordEntity> page = recordService.page(query.toPage(), query.toQueryWrapper());
|
||||
List<CollaborationRecordDTO> records = page.getRecords().stream()
|
||||
.map(this::buildRecordDTO)
|
||||
.collect(Collectors.toList());
|
||||
return new PageDTO<>(records, page.getTotal());
|
||||
}
|
||||
|
||||
public CollaborationRecordDetailDTO getRecordInfo(Long recordId) {
|
||||
CollaborationRecordModel model = recordModelFactory.loadById(recordId);
|
||||
CollaborationRecordDetailDTO dto = new CollaborationRecordDetailDTO(model);
|
||||
fillDetailChildren(dto, recordId);
|
||||
fillRecordStats(dto, recordId);
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addRecord(AddCollaborationRecordCommand command) {
|
||||
CollaborationRecordModel model = recordModelFactory.create();
|
||||
model.loadFromAddCommand(command);
|
||||
model.saveRecord();
|
||||
saveChildren(model.getRecordId(), command);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateRecord(UpdateCollaborationRecordCommand command) {
|
||||
CollaborationRecordModel model = recordModelFactory.loadById(command.getRecordId());
|
||||
model.loadFromUpdateCommand(command);
|
||||
model.updateRecord();
|
||||
replaceChildren(command.getRecordId(), command);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteRecord(BulkOperationCommand<Long> command) {
|
||||
Set<Long> ids = command.getIds();
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
taskService.removeByRecordIds(ids);
|
||||
expenditureService.removeByRecordIds(ids);
|
||||
settlementService.removeByRecordIds(ids);
|
||||
fileService.removeByRecordIds(ids);
|
||||
recordService.removeBatchByIds(ids);
|
||||
}
|
||||
|
||||
public List<CollaborationOptionDTO> getOptions() {
|
||||
return Arrays.stream(CollaborationOptionEnum.values())
|
||||
.map(item -> new CollaborationOptionDTO(item.getType(), item.getLabel(), Arrays.asList(item.getValues())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<CollaborationMonthlyStatisticsDTO> getMonthlyStatistics(Integer year) {
|
||||
List<CollaborationMonthlyStatisticsDTO> statistics = new ArrayList<>();
|
||||
for (int month = 1; month <= 12; month++) {
|
||||
statistics.add(buildMonthlyStatistics(year, month));
|
||||
}
|
||||
return statistics;
|
||||
}
|
||||
|
||||
private CollaborationRecordDTO buildRecordDTO(CollaborationRecordEntity entity) {
|
||||
CollaborationRecordDTO dto = new CollaborationRecordDTO(entity);
|
||||
fillRecordStats(dto, entity.getRecordId());
|
||||
return dto;
|
||||
}
|
||||
|
||||
private void fillDetailChildren(CollaborationRecordDetailDTO dto, Long recordId) {
|
||||
dto.setTasks(taskService.listByRecordId(recordId).stream()
|
||||
.map(CollaborationTaskDTO::new)
|
||||
.collect(Collectors.toList()));
|
||||
dto.setExpenditures(expenditureService.listByRecordId(recordId).stream()
|
||||
.map(CollaborationExpenditureDTO::new)
|
||||
.collect(Collectors.toList()));
|
||||
dto.setSettlements(settlementService.listByRecordId(recordId).stream()
|
||||
.map(CollaborationSettlementDTO::new)
|
||||
.collect(Collectors.toList()));
|
||||
dto.setFiles(fileService.listByRecordId(recordId).stream()
|
||||
.map(CollaborationFileDTO::new)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private void fillRecordStats(CollaborationRecordDTO dto, Long recordId) {
|
||||
List<CollaborationTaskEntity> tasks = taskService.listByRecordId(recordId);
|
||||
List<CollaborationExpenditureEntity> expenditures = expenditureService.listByRecordId(recordId);
|
||||
List<CollaborationSettlementEntity> settlements = settlementService.listByRecordId(recordId);
|
||||
dto.setTasksNum(tasks.size());
|
||||
dto.setCompletedTasksNum((int) tasks.stream().filter(item -> item.getReleaseDate() != null).count());
|
||||
dto.setPurchaseSettlementStatus(getStatus(dto.getPurchasePrice(), settlements, PURCHASE_FEE));
|
||||
dto.setDeliverySettlementStatus(getStatus(sumExpenditure(expenditures, DELIVERY_FEE), settlements, DELIVERY_FEE));
|
||||
dto.setRemunerationSettlementStatus(getStatus(dto.getRemuneration(), settlements, REMUNERATION_FEE));
|
||||
}
|
||||
|
||||
private SettlementStatusDTO getStatus(
|
||||
BigDecimal expectedAmount, List<CollaborationSettlementEntity> settlements, String purpose) {
|
||||
List<CollaborationSettlementEntity> matched = filterSettlements(settlements, purpose);
|
||||
if (matched.isEmpty()) {
|
||||
return toStatusDTO(SettlementStatusEnum.NONE);
|
||||
}
|
||||
BigDecimal settledAmount = sumSettlement(matched);
|
||||
BigDecimal expected = defaultAmount(expectedAmount);
|
||||
if (isAllSettlementPending(matched)) {
|
||||
return toStatusDTO(SettlementStatusEnum.UNSETTLED);
|
||||
}
|
||||
if (isAllSettlementDue(matched) && settledAmount.compareTo(expected) >= 0) {
|
||||
return toStatusDTO(SettlementStatusEnum.SETTLED);
|
||||
}
|
||||
return toStatusDTO(SettlementStatusEnum.PARTIAL);
|
||||
}
|
||||
|
||||
private List<CollaborationSettlementEntity> filterSettlements(
|
||||
List<CollaborationSettlementEntity> settlements, String purpose) {
|
||||
if (settlements == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return settlements.stream()
|
||||
.filter(item -> purpose.equals(item.getPurpose()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private SettlementStatusDTO toStatusDTO(SettlementStatusEnum status) {
|
||||
return new SettlementStatusDTO(status.getValue(), status.getLabel());
|
||||
}
|
||||
|
||||
private boolean isAllSettlementDue(List<CollaborationSettlementEntity> settlements) {
|
||||
Date today = getTodayStart();
|
||||
return settlements.stream()
|
||||
.allMatch(item -> item.getSettleDate() != null && !item.getSettleDate().after(today));
|
||||
}
|
||||
|
||||
private boolean isAllSettlementPending(List<CollaborationSettlementEntity> settlements) {
|
||||
Date today = getTodayStart();
|
||||
return settlements.stream()
|
||||
.allMatch(item -> item.getSettleDate() == null || item.getSettleDate().after(today));
|
||||
}
|
||||
|
||||
private void replaceChildren(Long recordId, AddCollaborationRecordCommand command) {
|
||||
List<Long> ids = Collections.singletonList(recordId);
|
||||
taskService.removeByRecordIds(ids);
|
||||
expenditureService.removeByRecordIds(ids);
|
||||
settlementService.removeByRecordIds(ids);
|
||||
fileService.removeByRecordIds(ids);
|
||||
saveChildren(recordId, command);
|
||||
}
|
||||
|
||||
private void saveChildren(Long recordId, AddCollaborationRecordCommand command) {
|
||||
saveTasks(recordId, command.getTasks());
|
||||
saveExpenditures(recordId, command.getExpenditures());
|
||||
saveSettlements(recordId, command.getSettlements());
|
||||
saveFiles(recordId, command.getFiles());
|
||||
}
|
||||
|
||||
private void saveTasks(Long recordId, List<CollaborationTaskCommand> tasks) {
|
||||
List<CollaborationTaskEntity> entities = toTaskEntities(recordId, tasks);
|
||||
if (!entities.isEmpty()) {
|
||||
taskService.saveBatch(entities);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveExpenditures(Long recordId, List<CollaborationExpenditureCommand> expenditures) {
|
||||
List<CollaborationExpenditureEntity> entities = toExpenditureEntities(recordId, expenditures);
|
||||
if (!entities.isEmpty()) {
|
||||
expenditureService.saveBatch(entities);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveSettlements(Long recordId, List<CollaborationSettlementCommand> settlements) {
|
||||
List<CollaborationSettlementEntity> entities = toSettlementEntities(recordId, settlements);
|
||||
if (!entities.isEmpty()) {
|
||||
settlementService.saveBatch(entities);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveFiles(Long recordId, List<CollaborationFileCommand> files) {
|
||||
List<CollaborationFileEntity> entities = toFileEntities(recordId, files);
|
||||
if (!entities.isEmpty()) {
|
||||
fileService.saveBatch(entities);
|
||||
}
|
||||
}
|
||||
|
||||
private List<CollaborationTaskEntity> toTaskEntities(Long recordId, List<CollaborationTaskCommand> tasks) {
|
||||
List<CollaborationTaskEntity> entities = new ArrayList<>();
|
||||
if (tasks == null) {
|
||||
return entities;
|
||||
}
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
entities.add(toTaskEntity(recordId, tasks.get(i), i));
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
private CollaborationTaskEntity toTaskEntity(Long recordId, CollaborationTaskCommand command, int index) {
|
||||
CollaborationTaskEntity entity = new CollaborationTaskEntity();
|
||||
entity.setRecordId(recordId);
|
||||
entity.setReleaseDate(command.getReleaseDate());
|
||||
entity.setSortOrder(index);
|
||||
return entity;
|
||||
}
|
||||
|
||||
private List<CollaborationExpenditureEntity> toExpenditureEntities(
|
||||
Long recordId, List<CollaborationExpenditureCommand> expenditures) {
|
||||
if (expenditures == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return expenditures.stream()
|
||||
.map(item -> toExpenditureEntity(recordId, item))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private CollaborationExpenditureEntity toExpenditureEntity(Long recordId, CollaborationExpenditureCommand command) {
|
||||
CollaborationExpenditureEntity entity = new CollaborationExpenditureEntity();
|
||||
entity.setRecordId(recordId);
|
||||
entity.setSpendDate(command.getSpendDate());
|
||||
entity.setAmount(command.getAmount());
|
||||
entity.setPurpose(command.getPurpose());
|
||||
return entity;
|
||||
}
|
||||
|
||||
private List<CollaborationSettlementEntity> toSettlementEntities(
|
||||
Long recordId, List<CollaborationSettlementCommand> settlements) {
|
||||
if (settlements == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return settlements.stream()
|
||||
.map(item -> toSettlementEntity(recordId, item))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private CollaborationSettlementEntity toSettlementEntity(Long recordId, CollaborationSettlementCommand command) {
|
||||
CollaborationSettlementEntity entity = new CollaborationSettlementEntity();
|
||||
entity.setRecordId(recordId);
|
||||
entity.setSettleDate(command.getSettleDate());
|
||||
entity.setMethod(command.getMethod());
|
||||
entity.setIncome(command.getIncome());
|
||||
entity.setPurpose(command.getPurpose());
|
||||
return entity;
|
||||
}
|
||||
|
||||
private List<CollaborationFileEntity> toFileEntities(Long recordId, List<CollaborationFileCommand> files) {
|
||||
List<CollaborationFileEntity> entities = new ArrayList<>();
|
||||
if (files == null) {
|
||||
return entities;
|
||||
}
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
entities.add(toFileEntity(recordId, files.get(i), i));
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
private CollaborationFileEntity toFileEntity(Long recordId, CollaborationFileCommand command, int index) {
|
||||
CollaborationFileEntity entity = new CollaborationFileEntity();
|
||||
entity.setRecordId(recordId);
|
||||
entity.setFileType(command.getFileType());
|
||||
entity.setUrl(command.getUrl());
|
||||
entity.setFileName(command.getFileName());
|
||||
entity.setNewFileName(command.getNewFileName());
|
||||
entity.setOriginalFilename(command.getOriginalFilename());
|
||||
entity.setSortOrder(index);
|
||||
return entity;
|
||||
}
|
||||
|
||||
private CollaborationMonthlyStatisticsDTO buildMonthlyStatistics(Integer year, Integer month) {
|
||||
Date[] range = getMonthRange(year, month);
|
||||
BigDecimal purchasePrice = sumPurchasePrice(range);
|
||||
BigDecimal expenditureAmount = sumExpenditure(range);
|
||||
BigDecimal settledRemuneration = sumSettlement(range, REMUNERATION_FEE);
|
||||
BigDecimal settledTotal = sumSettlement(range, null);
|
||||
return new CollaborationMonthlyStatisticsDTO(month, purchasePrice, expenditureAmount,
|
||||
settledRemuneration, settledTotal);
|
||||
}
|
||||
|
||||
private BigDecimal sumPurchasePrice(Date[] range) {
|
||||
List<CollaborationRecordEntity> records = recordService.list(new QueryWrapper<CollaborationRecordEntity>()
|
||||
.ge("purchase_date", range[0])
|
||||
.le("purchase_date", range[1]));
|
||||
return records.stream()
|
||||
.map(CollaborationRecordEntity::getPurchasePrice)
|
||||
.map(this::defaultAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
private BigDecimal sumExpenditure(Date[] range) {
|
||||
List<CollaborationExpenditureEntity> expenditures = expenditureService.list(
|
||||
new QueryWrapper<CollaborationExpenditureEntity>().ge("spend_date", range[0]).le("spend_date", range[1]));
|
||||
return expenditures.stream()
|
||||
.map(CollaborationExpenditureEntity::getAmount)
|
||||
.map(this::defaultAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
private BigDecimal sumSettlement(Date[] range, String purpose) {
|
||||
QueryWrapper<CollaborationSettlementEntity> wrapper = new QueryWrapper<CollaborationSettlementEntity>()
|
||||
.ge("settle_date", range[0])
|
||||
.le("settle_date", range[1])
|
||||
.eq(purpose != null, "purpose", purpose);
|
||||
return sumSettlement(settlementService.list(wrapper));
|
||||
}
|
||||
|
||||
private BigDecimal sumExpenditure(List<CollaborationExpenditureEntity> expenditures, String purpose) {
|
||||
return expenditures.stream()
|
||||
.filter(item -> purpose.equals(item.getPurpose()))
|
||||
.map(CollaborationExpenditureEntity::getAmount)
|
||||
.map(this::defaultAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
private BigDecimal sumSettlement(List<CollaborationSettlementEntity> settlements) {
|
||||
return settlements.stream()
|
||||
.map(CollaborationSettlementEntity::getIncome)
|
||||
.map(this::defaultAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
private BigDecimal defaultAmount(BigDecimal amount) {
|
||||
return amount == null ? BigDecimal.ZERO : amount;
|
||||
}
|
||||
|
||||
private Date[] getMonthRange(Integer year, Integer month) {
|
||||
Calendar start = Calendar.getInstance();
|
||||
start.set(year, month - 1, 1, 0, 0, 0);
|
||||
start.set(Calendar.MILLISECOND, 0);
|
||||
Calendar end = (Calendar) start.clone();
|
||||
end.add(Calendar.MONTH, 1);
|
||||
end.add(Calendar.MILLISECOND, -1);
|
||||
return new Date[]{start.getTime(), end.getTime()};
|
||||
}
|
||||
|
||||
private Date getTodayStart() {
|
||||
Calendar today = Calendar.getInstance();
|
||||
today.set(Calendar.HOUR_OF_DAY, 0);
|
||||
today.set(Calendar.MINUTE, 0);
|
||||
today.set(Calendar.SECOND, 0);
|
||||
today.set(Calendar.MILLISECOND, 0);
|
||||
return today.getTime();
|
||||
}
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.agileboot.domain.collaboration.record.command;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.PositiveOrZero;
|
||||
import javax.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Data
|
||||
public class AddCollaborationRecordCommand {
|
||||
|
||||
@NotBlank(message = "品牌不能为空")
|
||||
@Size(max = 100, message = "品牌长度不能超过100个字符")
|
||||
protected String brand;
|
||||
|
||||
@NotBlank(message = "物品不能为空")
|
||||
@Size(max = 100, message = "物品长度不能超过100个字符")
|
||||
protected String goods;
|
||||
|
||||
@Size(max = 50, message = "合作平台长度不能超过50个字符")
|
||||
protected String cooperationPlatform;
|
||||
|
||||
@NotNull(message = "返图数量不能为空")
|
||||
@Min(value = 1, message = "返图数量至少为1")
|
||||
protected Integer imageReturnNum;
|
||||
|
||||
@Size(max = 30, message = "留存方式长度不能超过30个字符")
|
||||
protected String retainedMethod;
|
||||
|
||||
@Size(max = 30, message = "合作方式长度不能超过30个字符")
|
||||
protected String cooperatedMethod;
|
||||
|
||||
@Size(max = 30, message = "购入方式长度不能超过30个字符")
|
||||
protected String purchaseMethod;
|
||||
|
||||
@PositiveOrZero(message = "购入金额不能小于0")
|
||||
protected BigDecimal purchasePrice;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
protected Date purchaseDate;
|
||||
|
||||
@Size(max = 30, message = "购入平台长度不能超过30个字符")
|
||||
protected String purchasePlatform;
|
||||
|
||||
@NotNull(message = "预完成日期不能为空")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
protected Date deadline;
|
||||
|
||||
@PositiveOrZero(message = "稿费不能小于0")
|
||||
protected BigDecimal remuneration;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
protected Date completeDate;
|
||||
|
||||
@Size(max = 1000, message = "拍摄要求长度不能超过1000个字符")
|
||||
protected String requirements;
|
||||
|
||||
@Size(max = 1000, message = "备注长度不能超过1000个字符")
|
||||
protected String remark;
|
||||
|
||||
@Valid
|
||||
protected List<CollaborationTaskCommand> tasks = new ArrayList<>();
|
||||
|
||||
@Valid
|
||||
protected List<CollaborationExpenditureCommand> expenditures = new ArrayList<>();
|
||||
|
||||
@Valid
|
||||
protected List<CollaborationSettlementCommand> settlements = new ArrayList<>();
|
||||
|
||||
@Valid
|
||||
protected List<CollaborationFileCommand> files = new ArrayList<>();
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.agileboot.domain.collaboration.record.command;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import javax.validation.constraints.PositiveOrZero;
|
||||
import javax.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Data
|
||||
public class CollaborationExpenditureCommand {
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date spendDate;
|
||||
|
||||
@PositiveOrZero(message = "支出金额不能小于0")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Size(max = 30, message = "支出用途长度不能超过30个字符")
|
||||
private String purpose;
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.agileboot.domain.collaboration.record.command;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Data
|
||||
public class CollaborationFileCommand {
|
||||
|
||||
@NotBlank(message = "文件类型不能为空")
|
||||
@Size(max = 30, message = "文件类型长度不能超过30个字符")
|
||||
private String fileType;
|
||||
|
||||
@NotBlank(message = "文件地址不能为空")
|
||||
@Size(max = 500, message = "文件地址长度不能超过500个字符")
|
||||
private String url;
|
||||
|
||||
@Size(max = 300, message = "文件路径长度不能超过300个字符")
|
||||
private String fileName;
|
||||
|
||||
@Size(max = 200, message = "服务端文件名长度不能超过200个字符")
|
||||
private String newFileName;
|
||||
|
||||
@Size(max = 300, message = "原始文件名长度不能超过300个字符")
|
||||
private String originalFilename;
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.agileboot.domain.collaboration.record.command;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import javax.validation.constraints.PositiveOrZero;
|
||||
import javax.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Data
|
||||
public class CollaborationSettlementCommand {
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date settleDate;
|
||||
|
||||
@Size(max = 30, message = "结款方式长度不能超过30个字符")
|
||||
private String method;
|
||||
|
||||
@PositiveOrZero(message = "结款金额不能小于0")
|
||||
private BigDecimal income;
|
||||
|
||||
@Size(max = 30, message = "结款用途长度不能超过30个字符")
|
||||
private String purpose;
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.agileboot.domain.collaboration.record.command;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Data
|
||||
public class CollaborationTaskCommand {
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date releaseDate;
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.agileboot.domain.collaboration.record.command;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Positive;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class UpdateCollaborationRecordCommand extends AddCollaborationRecordCommand {
|
||||
|
||||
@NotNull(message = "合作记录ID不能为空")
|
||||
@Positive
|
||||
private Long recordId;
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.agileboot.common.core.base.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("collaboration_expenditure")
|
||||
@ApiModel(value = "CollaborationExpenditureEntity对象", description = "合作支出表")
|
||||
public class CollaborationExpenditureEntity extends BaseEntity<CollaborationExpenditureEntity> {
|
||||
|
||||
@TableId(value = "expenditure_id", type = IdType.AUTO)
|
||||
private Long expenditureId;
|
||||
|
||||
@TableField("record_id")
|
||||
private Long recordId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@TableField("spend_date")
|
||||
private Date spendDate;
|
||||
|
||||
@TableField("amount")
|
||||
private BigDecimal amount;
|
||||
|
||||
@TableField("purpose")
|
||||
private String purpose;
|
||||
|
||||
@Override
|
||||
public Serializable pkVal() {
|
||||
return this.expenditureId;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationExpenditureMapper extends BaseMapper<CollaborationExpenditureEntity> {
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationExpenditureService extends IService<CollaborationExpenditureEntity> {
|
||||
|
||||
List<CollaborationExpenditureEntity> listByRecordId(Long recordId);
|
||||
|
||||
void removeByRecordIds(Collection<Long> recordIds);
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Service
|
||||
public class CollaborationExpenditureServiceImpl
|
||||
extends ServiceImpl<CollaborationExpenditureMapper, CollaborationExpenditureEntity>
|
||||
implements CollaborationExpenditureService {
|
||||
|
||||
@Override
|
||||
public List<CollaborationExpenditureEntity> listByRecordId(Long recordId) {
|
||||
if (recordId == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return list(new QueryWrapper<CollaborationExpenditureEntity>()
|
||||
.eq("record_id", recordId)
|
||||
.orderByAsc("spend_date"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByRecordIds(Collection<Long> recordIds) {
|
||||
if (recordIds == null || recordIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
remove(new QueryWrapper<CollaborationExpenditureEntity>().in("record_id", recordIds));
|
||||
}
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.agileboot.common.core.base.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import java.io.Serializable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("collaboration_file")
|
||||
@ApiModel(value = "CollaborationFileEntity对象", description = "合作文件表")
|
||||
public class CollaborationFileEntity extends BaseEntity<CollaborationFileEntity> {
|
||||
|
||||
@TableId(value = "file_id", type = IdType.AUTO)
|
||||
private Long fileId;
|
||||
|
||||
@TableField("record_id")
|
||||
private Long recordId;
|
||||
|
||||
@TableField("file_type")
|
||||
private String fileType;
|
||||
|
||||
@TableField("url")
|
||||
private String url;
|
||||
|
||||
@TableField("file_name")
|
||||
private String fileName;
|
||||
|
||||
@TableField("new_file_name")
|
||||
private String newFileName;
|
||||
|
||||
@TableField("original_filename")
|
||||
private String originalFilename;
|
||||
|
||||
@TableField("sort_order")
|
||||
private Integer sortOrder;
|
||||
|
||||
@Override
|
||||
public Serializable pkVal() {
|
||||
return this.fileId;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationFileMapper extends BaseMapper<CollaborationFileEntity> {
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationFileService extends IService<CollaborationFileEntity> {
|
||||
|
||||
List<CollaborationFileEntity> listByRecordId(Long recordId);
|
||||
|
||||
void removeByRecordIds(Collection<Long> recordIds);
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Service
|
||||
public class CollaborationFileServiceImpl
|
||||
extends ServiceImpl<CollaborationFileMapper, CollaborationFileEntity>
|
||||
implements CollaborationFileService {
|
||||
|
||||
@Override
|
||||
public List<CollaborationFileEntity> listByRecordId(Long recordId) {
|
||||
if (recordId == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return list(new QueryWrapper<CollaborationFileEntity>()
|
||||
.eq("record_id", recordId)
|
||||
.orderByAsc("file_type", "sort_order"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByRecordIds(Collection<Long> recordIds) {
|
||||
if (recordIds == null || recordIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
remove(new QueryWrapper<CollaborationFileEntity>().in("record_id", recordIds));
|
||||
}
|
||||
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.agileboot.common.core.base.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("collaboration_record")
|
||||
@ApiModel(value = "CollaborationRecordEntity对象", description = "合作记录表")
|
||||
public class CollaborationRecordEntity extends BaseEntity<CollaborationRecordEntity> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("合作记录ID")
|
||||
@TableId(value = "record_id", type = IdType.AUTO)
|
||||
private Long recordId;
|
||||
|
||||
@ApiModelProperty("品牌")
|
||||
@TableField("brand")
|
||||
private String brand;
|
||||
|
||||
@ApiModelProperty("物品")
|
||||
@TableField("goods")
|
||||
private String goods;
|
||||
|
||||
@ApiModelProperty("合作平台")
|
||||
@TableField("cooperation_platform")
|
||||
private String cooperationPlatform;
|
||||
|
||||
@ApiModelProperty("返图数量")
|
||||
@TableField("image_return_num")
|
||||
private Integer imageReturnNum;
|
||||
|
||||
@ApiModelProperty("留存方式")
|
||||
@TableField("retained_method")
|
||||
private String retainedMethod;
|
||||
|
||||
@ApiModelProperty("合作方式")
|
||||
@TableField("cooperated_method")
|
||||
private String cooperatedMethod;
|
||||
|
||||
@ApiModelProperty("购入方式")
|
||||
@TableField("purchase_method")
|
||||
private String purchaseMethod;
|
||||
|
||||
@ApiModelProperty("购入金额")
|
||||
@TableField("purchase_price")
|
||||
private BigDecimal purchasePrice;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@ApiModelProperty("购入日期")
|
||||
@TableField("purchase_date")
|
||||
private Date purchaseDate;
|
||||
|
||||
@ApiModelProperty("购入平台")
|
||||
@TableField("purchase_platform")
|
||||
private String purchasePlatform;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@ApiModelProperty("预完成日期")
|
||||
@TableField("deadline")
|
||||
private Date deadline;
|
||||
|
||||
@ApiModelProperty("稿费")
|
||||
@TableField("remuneration")
|
||||
private BigDecimal remuneration;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@ApiModelProperty("完成日期")
|
||||
@TableField("complete_date")
|
||||
private Date completeDate;
|
||||
|
||||
@ApiModelProperty("拍摄要求")
|
||||
@TableField("requirements")
|
||||
private String requirements;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
@TableField("remark")
|
||||
private String remark;
|
||||
|
||||
@Override
|
||||
public Serializable pkVal() {
|
||||
return this.recordId;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationRecordMapper extends BaseMapper<CollaborationRecordEntity> {
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationRecordService extends IService<CollaborationRecordEntity> {
|
||||
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Service
|
||||
public class CollaborationRecordServiceImpl
|
||||
extends ServiceImpl<CollaborationRecordMapper, CollaborationRecordEntity>
|
||||
implements CollaborationRecordService {
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.agileboot.common.core.base.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("collaboration_settlement")
|
||||
@ApiModel(value = "CollaborationSettlementEntity对象", description = "合作结款表")
|
||||
public class CollaborationSettlementEntity extends BaseEntity<CollaborationSettlementEntity> {
|
||||
|
||||
@TableId(value = "settlement_id", type = IdType.AUTO)
|
||||
private Long settlementId;
|
||||
|
||||
@TableField("record_id")
|
||||
private Long recordId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@TableField("settle_date")
|
||||
private Date settleDate;
|
||||
|
||||
@TableField("method")
|
||||
private String method;
|
||||
|
||||
@TableField("income")
|
||||
private BigDecimal income;
|
||||
|
||||
@TableField("purpose")
|
||||
private String purpose;
|
||||
|
||||
@Override
|
||||
public Serializable pkVal() {
|
||||
return this.settlementId;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationSettlementMapper extends BaseMapper<CollaborationSettlementEntity> {
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationSettlementService extends IService<CollaborationSettlementEntity> {
|
||||
|
||||
List<CollaborationSettlementEntity> listByRecordId(Long recordId);
|
||||
|
||||
void removeByRecordIds(Collection<Long> recordIds);
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Service
|
||||
public class CollaborationSettlementServiceImpl
|
||||
extends ServiceImpl<CollaborationSettlementMapper, CollaborationSettlementEntity>
|
||||
implements CollaborationSettlementService {
|
||||
|
||||
@Override
|
||||
public List<CollaborationSettlementEntity> listByRecordId(Long recordId) {
|
||||
if (recordId == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return list(new QueryWrapper<CollaborationSettlementEntity>()
|
||||
.eq("record_id", recordId)
|
||||
.orderByAsc("settle_date"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByRecordIds(Collection<Long> recordIds) {
|
||||
if (recordIds == null || recordIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
remove(new QueryWrapper<CollaborationSettlementEntity>().in("record_id", recordIds));
|
||||
}
|
||||
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.agileboot.common.core.base.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("collaboration_task")
|
||||
@ApiModel(value = "CollaborationTaskEntity对象", description = "合作笔记任务表")
|
||||
public class CollaborationTaskEntity extends BaseEntity<CollaborationTaskEntity> {
|
||||
|
||||
@TableId(value = "task_id", type = IdType.AUTO)
|
||||
private Long taskId;
|
||||
|
||||
@TableField("record_id")
|
||||
private Long recordId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@TableField("release_date")
|
||||
private Date releaseDate;
|
||||
|
||||
@TableField("sort_order")
|
||||
private Integer sortOrder;
|
||||
|
||||
@Override
|
||||
public Serializable pkVal() {
|
||||
return this.taskId;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationTaskMapper extends BaseMapper<CollaborationTaskEntity> {
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public interface CollaborationTaskService extends IService<CollaborationTaskEntity> {
|
||||
|
||||
List<CollaborationTaskEntity> listByRecordId(Long recordId);
|
||||
|
||||
void removeByRecordIds(Collection<Long> recordIds);
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.agileboot.domain.collaboration.record.db;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Service
|
||||
public class CollaborationTaskServiceImpl
|
||||
extends ServiceImpl<CollaborationTaskMapper, CollaborationTaskEntity>
|
||||
implements CollaborationTaskService {
|
||||
|
||||
@Override
|
||||
public List<CollaborationTaskEntity> listByRecordId(Long recordId) {
|
||||
if (recordId == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return list(new QueryWrapper<CollaborationTaskEntity>()
|
||||
.eq("record_id", recordId)
|
||||
.orderByAsc("sort_order"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByRecordIds(Collection<Long> recordIds) {
|
||||
if (recordIds == null || recordIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
remove(new QueryWrapper<CollaborationTaskEntity>().in("record_id", recordIds));
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationExpenditureEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationExpenditureDTO {
|
||||
|
||||
public CollaborationExpenditureDTO(CollaborationExpenditureEntity entity) {
|
||||
if (entity != null) {
|
||||
BeanUtil.copyProperties(entity, this);
|
||||
}
|
||||
}
|
||||
|
||||
private Long expenditureId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date spendDate;
|
||||
|
||||
private BigDecimal amount;
|
||||
|
||||
private String purpose;
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationFileEntity;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationFileDTO {
|
||||
|
||||
public CollaborationFileDTO(CollaborationFileEntity entity) {
|
||||
if (entity != null) {
|
||||
BeanUtil.copyProperties(entity, this);
|
||||
}
|
||||
}
|
||||
|
||||
private Long fileId;
|
||||
|
||||
private String fileType;
|
||||
|
||||
private String url;
|
||||
|
||||
private String fileName;
|
||||
|
||||
private String newFileName;
|
||||
|
||||
private String originalFilename;
|
||||
|
||||
private Integer sortOrder;
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationMonthlyStatisticsDTO {
|
||||
|
||||
private Integer month;
|
||||
|
||||
private BigDecimal purchasePrice;
|
||||
|
||||
private BigDecimal expenditureAmount;
|
||||
|
||||
private BigDecimal settledRemuneration;
|
||||
|
||||
private BigDecimal settledTotal;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationOptionDTO {
|
||||
|
||||
private String type;
|
||||
|
||||
private String label;
|
||||
|
||||
private List<String> values;
|
||||
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationRecordDTO {
|
||||
|
||||
public CollaborationRecordDTO(CollaborationRecordEntity entity) {
|
||||
if (entity != null) {
|
||||
BeanUtil.copyProperties(entity, this);
|
||||
}
|
||||
}
|
||||
|
||||
private Long recordId;
|
||||
|
||||
private String brand;
|
||||
|
||||
private String goods;
|
||||
|
||||
private String cooperationPlatform;
|
||||
|
||||
private Integer imageReturnNum;
|
||||
|
||||
private String retainedMethod;
|
||||
|
||||
private String cooperatedMethod;
|
||||
|
||||
private String purchaseMethod;
|
||||
|
||||
private BigDecimal purchasePrice;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date purchaseDate;
|
||||
|
||||
private String purchasePlatform;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date deadline;
|
||||
|
||||
private BigDecimal remuneration;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date completeDate;
|
||||
|
||||
private String requirements;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Integer tasksNum;
|
||||
|
||||
private Integer completedTasksNum;
|
||||
|
||||
private SettlementStatusDTO purchaseSettlementStatus;
|
||||
|
||||
private SettlementStatusDTO deliverySettlementStatus;
|
||||
|
||||
private SettlementStatusDTO remunerationSettlementStatus;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordEntity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationRecordDetailDTO extends CollaborationRecordDTO {
|
||||
|
||||
public CollaborationRecordDetailDTO(CollaborationRecordEntity entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
private List<CollaborationTaskDTO> tasks = new ArrayList<>();
|
||||
|
||||
private List<CollaborationExpenditureDTO> expenditures = new ArrayList<>();
|
||||
|
||||
private List<CollaborationSettlementDTO> settlements = new ArrayList<>();
|
||||
|
||||
private List<CollaborationFileDTO> files = new ArrayList<>();
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationSettlementEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationSettlementDTO {
|
||||
|
||||
public CollaborationSettlementDTO(CollaborationSettlementEntity entity) {
|
||||
if (entity != null) {
|
||||
BeanUtil.copyProperties(entity, this);
|
||||
}
|
||||
}
|
||||
|
||||
private Long settlementId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date settleDate;
|
||||
|
||||
private String method;
|
||||
|
||||
private BigDecimal income;
|
||||
|
||||
private String purpose;
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationTaskEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class CollaborationTaskDTO {
|
||||
|
||||
public CollaborationTaskDTO(CollaborationTaskEntity entity) {
|
||||
if (entity != null) {
|
||||
BeanUtil.copyProperties(entity, this);
|
||||
}
|
||||
}
|
||||
|
||||
private Long taskId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date releaseDate;
|
||||
|
||||
private Integer sortOrder;
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.agileboot.domain.collaboration.record.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class SettlementStatusDTO {
|
||||
|
||||
private String status;
|
||||
|
||||
private String label;
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.agileboot.domain.collaboration.record.enumtype;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
public enum CollaborationFileTypeEnum {
|
||||
|
||||
GOODS_IMAGE,
|
||||
|
||||
ATTACHMENT
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.agileboot.domain.collaboration.record.enumtype;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Getter
|
||||
public enum CollaborationOptionEnum {
|
||||
|
||||
COOPERATION_PLATFORM("cooperationPlatform", "合作平台",
|
||||
new String[]{"小红书", "得物", "抖音", "淘宝", "京东", "微博", "B站", "其他"}),
|
||||
|
||||
RETAINED_METHOD("retainedMethod", "留存方式",
|
||||
new String[]{"寄拍", "送拍", "置换", "无需寄样"}),
|
||||
|
||||
COOPERATED_METHOD("cooperatedMethod", "合作方式",
|
||||
new String[]{"水下", "蒲公英"}),
|
||||
|
||||
PURCHASE_METHOD("purchaseMethod", "购入方式",
|
||||
new String[]{"拍单", "商家寄出"}),
|
||||
|
||||
PURCHASE_PLATFORM("purchasePlatform", "购入平台",
|
||||
new String[]{"淘宝", "小红书", "京东", "抖音"}),
|
||||
|
||||
EXPENDITURE_PURPOSE("expenditurePurpose", "支出用途",
|
||||
new String[]{"快递费用", "返点", "蒲公英扣税费用"}),
|
||||
|
||||
SETTLEMENT_METHOD("settlementMethod", "结款方式",
|
||||
new String[]{"微信", "支付宝", "蒲公英", "京灵平台"}),
|
||||
|
||||
SETTLEMENT_PURPOSE("settlementPurpose", "结款用途",
|
||||
new String[]{"稿费", "快递费用", "拍单费用", "蒲公英扣税费用"});
|
||||
|
||||
private final String type;
|
||||
private final String label;
|
||||
private final String[] values;
|
||||
|
||||
CollaborationOptionEnum(String type, String label, String[] values) {
|
||||
this.type = type;
|
||||
this.label = label;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.agileboot.domain.collaboration.record.enumtype;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Getter
|
||||
public enum SettlementStatusEnum {
|
||||
|
||||
NONE("NONE", "无结款项"),
|
||||
|
||||
SETTLED("SETTLED", "已结"),
|
||||
|
||||
UNSETTLED("UNSETTLED", "未结"),
|
||||
|
||||
PARTIAL("PARTIAL", "未结清");
|
||||
|
||||
private final String value;
|
||||
private final String label;
|
||||
|
||||
SettlementStatusEnum(String value, String label) {
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.agileboot.domain.collaboration.record.model;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.agileboot.common.exception.ApiException;
|
||||
import com.agileboot.common.exception.error.ErrorCode;
|
||||
import com.agileboot.domain.collaboration.record.command.AddCollaborationRecordCommand;
|
||||
import com.agileboot.domain.collaboration.record.command.UpdateCollaborationRecordCommand;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordEntity;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordService;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class CollaborationRecordModel extends CollaborationRecordEntity {
|
||||
|
||||
private CollaborationRecordService recordService;
|
||||
|
||||
public CollaborationRecordModel(CollaborationRecordService recordService) {
|
||||
this.recordService = recordService;
|
||||
}
|
||||
|
||||
public CollaborationRecordModel(CollaborationRecordEntity entity, CollaborationRecordService recordService) {
|
||||
if (entity != null) {
|
||||
BeanUtil.copyProperties(entity, this);
|
||||
}
|
||||
this.recordService = recordService;
|
||||
}
|
||||
|
||||
public void loadFromAddCommand(AddCollaborationRecordCommand command) {
|
||||
if (command == null) {
|
||||
return;
|
||||
}
|
||||
BeanUtil.copyProperties(command, this, "recordId");
|
||||
loadDefaultValues();
|
||||
}
|
||||
|
||||
public void loadFromUpdateCommand(UpdateCollaborationRecordCommand command) {
|
||||
if (command == null) {
|
||||
return;
|
||||
}
|
||||
loadFromAddCommand(command);
|
||||
}
|
||||
|
||||
public void checkRequiredFields() {
|
||||
if (StrUtil.isBlank(getBrand())) {
|
||||
throw new ApiException(ErrorCode.FAILED);
|
||||
}
|
||||
if (StrUtil.isBlank(getGoods())) {
|
||||
throw new ApiException(ErrorCode.FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveRecord() {
|
||||
recordService.save(this);
|
||||
}
|
||||
|
||||
public void updateRecord() {
|
||||
recordService.updateById(this);
|
||||
}
|
||||
|
||||
private void loadDefaultValues() {
|
||||
if (getImageReturnNum() == null) {
|
||||
setImageReturnNum(1);
|
||||
}
|
||||
if (StrUtil.isBlank(getRetainedMethod())) {
|
||||
setRetainedMethod("寄拍");
|
||||
}
|
||||
if (StrUtil.isBlank(getCooperatedMethod())) {
|
||||
setCooperatedMethod("水下");
|
||||
}
|
||||
if (StrUtil.isBlank(getPurchaseMethod())) {
|
||||
setPurchaseMethod("拍单");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.agileboot.domain.collaboration.record.model;
|
||||
|
||||
import com.agileboot.common.exception.ApiException;
|
||||
import com.agileboot.common.exception.error.ErrorCode.Business;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordEntity;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CollaborationRecordModelFactory {
|
||||
|
||||
private final CollaborationRecordService recordService;
|
||||
|
||||
public CollaborationRecordModel loadById(Long recordId) {
|
||||
CollaborationRecordEntity entity = recordService.getById(recordId);
|
||||
if (entity == null) {
|
||||
throw new ApiException(Business.COMMON_OBJECT_NOT_FOUND, recordId, "合作记录");
|
||||
}
|
||||
return new CollaborationRecordModel(entity, recordService);
|
||||
}
|
||||
|
||||
public CollaborationRecordModel create() {
|
||||
return new CollaborationRecordModel(recordService);
|
||||
}
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.agileboot.domain.collaboration.record.query;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.agileboot.common.core.page.AbstractPageQuery;
|
||||
import com.agileboot.common.utils.time.DatePickUtil;
|
||||
import com.agileboot.domain.collaboration.record.db.CollaborationRecordEntity;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* @author codex
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class CollaborationRecordQuery extends AbstractPageQuery<CollaborationRecordEntity> {
|
||||
|
||||
private String brand;
|
||||
|
||||
private String goods;
|
||||
|
||||
private String cooperationPlatform;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date purchaseBeginTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date purchaseEndTime;
|
||||
|
||||
@Override
|
||||
public QueryWrapper<CollaborationRecordEntity> addQueryCondition() {
|
||||
QueryWrapper<CollaborationRecordEntity> queryWrapper = new QueryWrapper<CollaborationRecordEntity>()
|
||||
.like(StrUtil.isNotEmpty(brand), "brand", brand)
|
||||
.like(StrUtil.isNotEmpty(goods), "goods", goods)
|
||||
.eq(StrUtil.isNotEmpty(cooperationPlatform), "cooperation_platform", cooperationPlatform)
|
||||
.ge(purchaseBeginTime != null, "purchase_date", DatePickUtil.getBeginOfTheDay(purchaseBeginTime))
|
||||
.le(purchaseEndTime != null, "purchase_date", DatePickUtil.getEndOfTheDay(purchaseEndTime));
|
||||
|
||||
if (StrUtil.isEmpty(this.getOrderColumn())) {
|
||||
this.setOrderColumn("deadline");
|
||||
this.setOrderDirection("descending");
|
||||
}
|
||||
this.setTimeRangeColumn("deadline");
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
@echo off
|
||||
|
||||
rem jar平级目录
|
||||
set AppName=agileboot-admin.jar
|
||||
|
||||
rem JVM参数
|
||||
set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
|
||||
|
||||
|
||||
ECHO.
|
||||
ECHO. [1] 启动%AppName%
|
||||
ECHO. [2] 关闭%AppName%
|
||||
ECHO. [3] 重启%AppName%
|
||||
ECHO. [4] 启动状态 %AppName%
|
||||
ECHO. [5] 退 出
|
||||
ECHO.
|
||||
|
||||
ECHO.请输入选择项目的序号:
|
||||
set /p ID=
|
||||
IF "%id%"=="1" GOTO start
|
||||
IF "%id%"=="2" GOTO stop
|
||||
IF "%id%"=="3" GOTO restart
|
||||
IF "%id%"=="4" GOTO status
|
||||
IF "%id%"=="5" EXIT
|
||||
PAUSE
|
||||
:start
|
||||
for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
|
||||
set pid=%%a
|
||||
set image_name=%%b
|
||||
)
|
||||
if defined pid (
|
||||
echo %%is running
|
||||
PAUSE
|
||||
)
|
||||
|
||||
start javaw %JVM_OPTS% -jar %AppName%
|
||||
|
||||
echo starting……
|
||||
echo Start %AppName% success...
|
||||
goto:eof
|
||||
|
||||
rem 函数stop通过jps命令查找pid并结束进程
|
||||
:stop
|
||||
for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
|
||||
set pid=%%a
|
||||
set image_name=%%b
|
||||
)
|
||||
if not defined pid (echo process %AppName% does not exists) else (
|
||||
echo prepare to kill %image_name%
|
||||
echo start kill %pid% ...
|
||||
rem 根据进程ID,kill进程
|
||||
taskkill /f /pid %pid%
|
||||
)
|
||||
goto:eof
|
||||
:restart
|
||||
call :stop
|
||||
call :start
|
||||
goto:eof
|
||||
:status
|
||||
for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
|
||||
set pid=%%a
|
||||
set image_name=%%b
|
||||
)
|
||||
if not defined pid (echo process %AppName% is dead ) else (
|
||||
echo %image_name% is running
|
||||
)
|
||||
goto:eof
|
||||
@@ -1,86 +0,0 @@
|
||||
#!/bin/sh
|
||||
# ./ag-admin.sh start 启动 stop 停止 restart 重启 status 状态
|
||||
AppName=agileboot-admin.jar
|
||||
|
||||
# JVM参数
|
||||
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
|
||||
APP_HOME=`pwd`
|
||||
LOG_PATH=$APP_HOME/logs/$AppName.log
|
||||
|
||||
if [ "$1" = "" ];
|
||||
then
|
||||
echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$AppName" = "" ];
|
||||
then
|
||||
echo -e "\033[0;31m 未输入应用名 \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function start()
|
||||
{
|
||||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
|
||||
|
||||
if [ x"$PID" != x"" ]; then
|
||||
echo "$AppName is running..."
|
||||
else
|
||||
nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 &
|
||||
echo "Start $AppName success..."
|
||||
fi
|
||||
}
|
||||
|
||||
function stop()
|
||||
{
|
||||
echo "Stop $AppName"
|
||||
|
||||
PID=""
|
||||
query(){
|
||||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
|
||||
}
|
||||
|
||||
query
|
||||
if [ x"$PID" != x"" ]; then
|
||||
kill -TERM $PID
|
||||
echo "$AppName (pid:$PID) exiting..."
|
||||
while [ x"$PID" != x"" ]
|
||||
do
|
||||
sleep 1
|
||||
query
|
||||
done
|
||||
echo "$AppName exited."
|
||||
else
|
||||
echo "$AppName already stopped."
|
||||
fi
|
||||
}
|
||||
|
||||
function restart()
|
||||
{
|
||||
stop
|
||||
sleep 2
|
||||
start
|
||||
}
|
||||
|
||||
function status()
|
||||
{
|
||||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l`
|
||||
if [ $PID != 0 ];then
|
||||
echo "$AppName is running..."
|
||||
else
|
||||
echo "$AppName is not running..."
|
||||
fi
|
||||
}
|
||||
|
||||
case $1 in
|
||||
start)
|
||||
start;;
|
||||
stop)
|
||||
stop;;
|
||||
restart)
|
||||
restart;;
|
||||
status)
|
||||
status;;
|
||||
*)
|
||||
|
||||
esac
|
||||
@@ -1,14 +0,0 @@
|
||||
@echo off
|
||||
echo.
|
||||
echo [信息] 使用Jar命令运行Web工程。
|
||||
echo.
|
||||
|
||||
cd %~dp0
|
||||
cd ../agileboot-admin/target
|
||||
|
||||
set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
|
||||
|
||||
java -jar %JAVA_OPTS% agileboot-admin.jar
|
||||
|
||||
cd bin
|
||||
pause
|
||||
+16
-12
@@ -1,34 +1,38 @@
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: mysql-server
|
||||
container_name: todo-mysql-server
|
||||
restart: always
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root123
|
||||
MYSQL_DATABASE: agileboot_pure
|
||||
MYSQL_DATABASE: todo_agileboot_pure
|
||||
ports:
|
||||
- "3306:3306"
|
||||
- "33061:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
- todo_mysql_data:/var/lib/mysql
|
||||
- ./sql/agileboot.sql:/docker-entrypoint-initdb.d/01-agileboot.sql:ro
|
||||
networks:
|
||||
- db-network
|
||||
- todo-db-network
|
||||
|
||||
redis:
|
||||
image: redis:7.2-alpine
|
||||
container_name: redis-server
|
||||
container_name: todo-redis-server
|
||||
restart: always
|
||||
command: redis-server --requirepass redis123
|
||||
ports:
|
||||
- "6379:6379"
|
||||
- "63791:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
- todo_redis_data:/data
|
||||
networks:
|
||||
- db-network
|
||||
- todo-db-network
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
redis_data:
|
||||
todo_mysql_data:
|
||||
todo_redis_data:
|
||||
|
||||
networks:
|
||||
db-network:
|
||||
todo-db-network:
|
||||
driver: bridge
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
SET NAMES utf8mb4;
|
||||
SET character_set_client = utf8mb4;
|
||||
SET character_set_connection = utf8mb4;
|
||||
SET character_set_results = utf8mb4;
|
||||
|
||||
create table sys_config
|
||||
(
|
||||
config_id int auto_increment comment '参数主键'
|
||||
@@ -101,68 +106,66 @@ create table sys_menu
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (1, '系统管理', 2, '', 0, '/system', 0, '', '{"title":"系统管理","icon":"ep:management","showParent":true,"rank":1}', 1, '系统管理目录', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:08:50', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (2, '系统监控', 2, '', 0, '/monitor', 0, '', '{"title":"系统监控","icon":"ep:monitor","showParent":true,"rank":3}', 1, '系统监控目录', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:09:15', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3, '系统工具', 2, '', 0, '/tool', 0, '', '{"title":"系统工具","icon":"ep:tools","showParent":true,"rank":2}', 1, '系统工具目录', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:09:03', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (4, 'AgileBoot官网', 3, 'AgileBootguanwangIframeRouter', 0, '/AgileBootguanwangIframeLink', 0, '', '{"title":"AgileBoot官网","icon":"ep:link","showParent":true,"frameSrc":"https://element-plus.org/zh-CN/","rank":8}', 1, 'Agileboot官网地址', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:09:40', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (5, '用户管理', 1, 'SystemUser', 1, '/system/user/index', 0, 'system:user:list', '{"title":"用户管理","icon":"ep:user-filled","showParent":true}', 1, '用户管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:16:13', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (6, '角色管理', 1, 'SystemRole', 1, '/system/role/index', 0, 'system:role:list', '{"title":"角色管理","icon":"ep:user","showParent":true}', 1, '角色管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:16:23', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (7, '菜单管理', 1, 'MenuManagement', 1, '/system/menu/index', 0, 'system:menu:list', '{"title":"菜单管理","icon":"ep:menu","showParent":true}', 1, '菜单管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:41', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (8, '部门管理', 1, 'Department', 1, '/system/dept/index', 0, 'system:dept:list', '{"title":"部门管理","icon":"fa-solid:code-branch","showParent":true}', 1, '部门管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:35', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (9, '岗位管理', 1, 'Post', 1, '/system/post/index', 0, 'system:post:list', '{"title":"岗位管理","icon":"ep:postcard","showParent":true}', 1, '岗位管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:11', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (10, '参数设置', 1, 'Config', 1, '/system/config/index', 0, 'system:config:list', '{"title":"参数设置","icon":"ep:setting","showParent":true}', 1, '参数设置菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:03', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (11, '通知公告', 1, 'SystemNotice', 1, '/system/notice/index', 0, 'system:notice:list', '{"title":"通知公告","icon":"ep:notification","showParent":true}', 1, '通知公告菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:14:56', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (12, '日志管理', 1, 'LogManagement', 1, '/system/logd', 0, '', '{"title":"日志管理","icon":"ep:document","showParent":true}', 1, '日志管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:14:47', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (13, '在线用户', 1, 'OnlineUser', 2, '/system/monitor/onlineUser/index', 0, 'monitor:online:list', '{"title":"在线用户","icon":"fa-solid:users","showParent":true}', 1, '在线用户菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:13:13', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (14, '数据监控', 1, 'DataMonitor', 2, '/system/monitor/druid/index', 0, 'monitor:druid:list', '{"title":"数据监控","icon":"fa:database","showParent":true,"frameSrc":"/druid/login.html","isFrameSrcInternal":true}', 1, '数据监控菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:13:25', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (15, '服务监控', 1, 'ServerInfo', 2, '/system/monitor/server/index', 0, 'monitor:server:list', '{"title":"服务监控","icon":"fa:server","showParent":true}', 1, '服务监控菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:13:34', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (16, '缓存监控', 1, 'CacheInfo', 2, '/system/monitor/cache/index', 0, 'monitor:cache:list', '{"title":"缓存监控","icon":"ep:reading","showParent":true}', 1, '缓存监控菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:12:59', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (17, '系统接口', 1, 'SystemAPI', 3, '/tool/swagger/index', 0, 'tool:swagger:list', '{"title":"系统接口","icon":"ep:document-remove","showParent":true,"frameSrc":"/swagger-ui/index.html","isFrameSrcInternal":true}', 1, '系统接口菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:14:01', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (18, '操作日志', 1, 'OperationLog', 12, '/system/log/operationLog/index', 0, 'monitor:operlog:list', '{"title":"操作日志"}', 1, '操作日志菜单', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (19, '登录日志', 1, 'LoginLog', 12, '/system/log/loginLog/index', 0, 'monitor:logininfor:list', '{"title":"登录日志"}', 1, '登录日志菜单', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (20, '用户查询', 0, ' ', 5, '', 1, 'system:user:query', '{"title":"用户查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (21, '用户新增', 0, ' ', 5, '', 1, 'system:user:add', '{"title":"用户新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (22, '用户修改', 0, ' ', 5, '', 1, 'system:user:edit', '{"title":"用户修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (23, '用户删除', 0, ' ', 5, '', 1, 'system:user:remove', '{"title":"用户删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (24, '用户导出', 0, ' ', 5, '', 1, 'system:user:export', '{"title":"用户导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (25, '用户导入', 0, ' ', 5, '', 1, 'system:user:import', '{"title":"用户导入"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (26, '重置密码', 0, ' ', 5, '', 1, 'system:user:resetPwd', '{"title":"重置密码"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (27, '角色查询', 0, ' ', 6, '', 1, 'system:role:query', '{"title":"角色查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (28, '角色新增', 0, ' ', 6, '', 1, 'system:role:add', '{"title":"角色新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (29, '角色修改', 0, ' ', 6, '', 1, 'system:role:edit', '{"title":"角色修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (30, '角色删除', 0, ' ', 6, '', 1, 'system:role:remove', '{"title":"角色删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (31, '角色导出', 0, ' ', 6, '', 1, 'system:role:export', '{"title":"角色导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (32, '菜单查询', 0, ' ', 7, '', 1, 'system:menu:query', '{"title":"菜单查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (33, '菜单新增', 0, ' ', 7, '', 1, 'system:menu:add', '{"title":"菜单新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (34, '菜单修改', 0, ' ', 7, '', 1, 'system:menu:edit', '{"title":"菜单修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (35, '菜单删除', 0, ' ', 7, '', 1, 'system:menu:remove', '{"title":"菜单删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (36, '部门查询', 0, ' ', 8, '', 1, 'system:dept:query', '{"title":"部门查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (37, '部门新增', 0, ' ', 8, '', 1, 'system:dept:add', '{"title":"部门新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (38, '部门修改', 0, ' ', 8, '', 1, 'system:dept:edit', '{"title":"部门修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (39, '部门删除', 0, ' ', 8, '', 1, 'system:dept:remove', '{"title":"部门删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (40, '岗位查询', 0, ' ', 9, '', 1, 'system:post:query', '{"title":"岗位查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (41, '岗位新增', 0, ' ', 9, '', 1, 'system:post:add', '{"title":"岗位新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (42, '岗位修改', 0, ' ', 9, '', 1, 'system:post:edit', '{"title":"岗位修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (43, '岗位删除', 0, ' ', 9, '', 1, 'system:post:remove', '{"title":"岗位删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (44, '岗位导出', 0, ' ', 9, '', 1, 'system:post:export', '{"title":"岗位导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (45, '参数查询', 0, ' ', 10, '', 1, 'system:config:query', '{"title":"参数查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (46, '参数新增', 0, ' ', 10, '', 1, 'system:config:add', '{"title":"参数新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (47, '参数修改', 0, ' ', 10, '', 1, 'system:config:edit', '{"title":"参数修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (48, '参数删除', 0, ' ', 10, '', 1, 'system:config:remove', '{"title":"参数删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (49, '参数导出', 0, ' ', 10, '', 1, 'system:config:export', '{"title":"参数导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (50, '公告查询', 0, ' ', 11, '', 1, 'system:notice:query', '{"title":"公告查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (51, '公告新增', 0, ' ', 11, '', 1, 'system:notice:add', '{"title":"公告新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (52, '公告修改', 0, ' ', 11, '', 1, 'system:notice:edit', '{"title":"公告修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (53, '公告删除', 0, ' ', 11, '', 1, 'system:notice:remove', '{"title":"公告删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (54, '操作查询', 0, ' ', 18, '', 1, 'monitor:operlog:query', '{"title":"操作查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (55, '操作删除', 0, ' ', 18, '', 1, 'monitor:operlog:remove', '{"title":"操作删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (56, '日志导出', 0, ' ', 18, '', 1, 'monitor:operlog:export', '{"title":"日志导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (57, '登录查询', 0, ' ', 19, '', 1, 'monitor:logininfor:query', '{"title":"登录查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (58, '登录删除', 0, ' ', 19, '', 1, 'monitor:logininfor:remove', '{"title":"登录删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (59, '日志导出', 0, ' ', 19, '', 1, 'monitor:logininfor:export', '{"title":"日志导出","rank":22}', 1, '', 0, '2022-05-21 08:30:54', 1, '2023-07-22 17:02:28', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (60, '在线查询', 0, ' ', 13, '', 1, 'monitor:online:query', '{"title":"在线查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (61, '批量强退', 0, ' ', 13, '', 1, 'monitor:online:batchLogout', '{"title":"批量强退"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (62, '单条强退', 0, ' ', 13, '', 1, 'monitor:online:forceLogout', '{"title":"单条强退"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (63, 'AgileBoot Github地址', 4, 'https://github.com/valarchie/AgileBoot-Back-End', 0, '/external', 0, '', '{"title":"AgileBoot Github地址","icon":"fa-solid:external-link-alt","showParent":true,"rank":9}', 1, 'Agileboot github地址', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:12:13', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (64, '首页', 2, '', 0, '/global', 0, '121212', '{"title":"首页","showParent":true,"rank":3}', 1, '', 1, '2023-07-24 22:36:03', 1, '2023-07-24 22:38:37', 1);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (65, '个人中心', 1, 'PersonalCenter', 2053, '/system/user/profile', 0, '434sdf', '{"title":"个人中心","showParent":true,"rank":3}', 1, '', 1, '2023-07-24 22:36:55', null, null, 1);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (4, '用户管理', 1, 'SystemUser', 1, '/system/user/index', 0, 'system:user:list', '{"title":"用户管理","icon":"ep:user-filled","showParent":true}', 1, '用户管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:16:13', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (5, '角色管理', 1, 'SystemRole', 1, '/system/role/index', 0, 'system:role:list', '{"title":"角色管理","icon":"ep:user","showParent":true}', 1, '角色管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:16:23', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (6, '菜单管理', 1, 'MenuManagement', 1, '/system/menu/index', 0, 'system:menu:list', '{"title":"菜单管理","icon":"ep:menu","showParent":true}', 1, '菜单管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:41', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (7, '部门管理', 1, 'Department', 1, '/system/dept/index', 0, 'system:dept:list', '{"title":"部门管理","icon":"fa-solid:code-branch","showParent":true}', 1, '部门管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:35', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (8, '岗位管理', 1, 'Post', 1, '/system/post/index', 0, 'system:post:list', '{"title":"岗位管理","icon":"ep:postcard","showParent":true}', 1, '岗位管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:11', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (9, '参数设置', 1, 'Config', 1, '/system/config/index', 0, 'system:config:list', '{"title":"参数设置","icon":"ep:setting","showParent":true}', 1, '参数设置菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:15:03', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (10, '通知公告', 1, 'SystemNotice', 1, '/system/notice/index', 0, 'system:notice:list', '{"title":"通知公告","icon":"ep:notification","showParent":true}', 1, '通知公告菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:14:56', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (11, '日志管理', 1, 'LogManagement', 1, '/system/logd', 0, '', '{"title":"日志管理","icon":"ep:document","showParent":true}', 1, '日志管理菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:14:47', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (12, '在线用户', 1, 'OnlineUser', 2, '/system/monitor/onlineUser/index', 0, 'monitor:online:list', '{"title":"在线用户","icon":"fa-solid:users","showParent":true}', 1, '在线用户菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:13:13', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (13, '数据监控', 1, 'DataMonitor', 2, '/system/monitor/druid/index', 0, 'monitor:druid:list', '{"title":"数据监控","icon":"fa:database","showParent":true,"frameSrc":"/druid/login.html","isFrameSrcInternal":true}', 1, '数据监控菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:13:25', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (14, '服务监控', 1, 'ServerInfo', 2, '/system/monitor/server/index', 0, 'monitor:server:list', '{"title":"服务监控","icon":"fa:server","showParent":true}', 1, '服务监控菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:13:34', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (15, '缓存监控', 1, 'CacheInfo', 2, '/system/monitor/cache/index', 0, 'monitor:cache:list', '{"title":"缓存监控","icon":"ep:reading","showParent":true}', 1, '缓存监控菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:12:59', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (16, '系统接口', 1, 'SystemAPI', 3, '/tool/swagger/index', 0, 'tool:swagger:list', '{"title":"系统接口","icon":"ep:document-remove","showParent":true,"frameSrc":"/swagger-ui/index.html","isFrameSrcInternal":true}', 1, '系统接口菜单', 0, '2022-05-21 08:30:54', 1, '2023-08-14 23:14:01', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (17, '操作日志', 1, 'OperationLog', 12, '/system/log/operationLog/index', 0, 'monitor:operlog:list', '{"title":"操作日志"}', 1, '操作日志菜单', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (18, '登录日志', 1, 'LoginLog', 12, '/system/log/loginLog/index', 0, 'monitor:logininfor:list', '{"title":"登录日志"}', 1, '登录日志菜单', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (19, '用户查询', 0, ' ', 5, '', 1, 'system:user:query', '{"title":"用户查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (20, '用户新增', 0, ' ', 5, '', 1, 'system:user:add', '{"title":"用户新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (21, '用户修改', 0, ' ', 5, '', 1, 'system:user:edit', '{"title":"用户修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (22, '用户删除', 0, ' ', 5, '', 1, 'system:user:remove', '{"title":"用户删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (23, '用户导出', 0, ' ', 5, '', 1, 'system:user:export', '{"title":"用户导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (24, '用户导入', 0, ' ', 5, '', 1, 'system:user:import', '{"title":"用户导入"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (25, '重置密码', 0, ' ', 5, '', 1, 'system:user:resetPwd', '{"title":"重置密码"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (26, '角色查询', 0, ' ', 6, '', 1, 'system:role:query', '{"title":"角色查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (27, '角色新增', 0, ' ', 6, '', 1, 'system:role:add', '{"title":"角色新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (28, '角色修改', 0, ' ', 6, '', 1, 'system:role:edit', '{"title":"角色修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (29, '角色删除', 0, ' ', 6, '', 1, 'system:role:remove', '{"title":"角色删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (30, '角色导出', 0, ' ', 6, '', 1, 'system:role:export', '{"title":"角色导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (31, '菜单查询', 0, ' ', 7, '', 1, 'system:menu:query', '{"title":"菜单查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (32, '菜单新增', 0, ' ', 7, '', 1, 'system:menu:add', '{"title":"菜单新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (33, '菜单修改', 0, ' ', 7, '', 1, 'system:menu:edit', '{"title":"菜单修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (34, '菜单删除', 0, ' ', 7, '', 1, 'system:menu:remove', '{"title":"菜单删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (35, '部门查询', 0, ' ', 8, '', 1, 'system:dept:query', '{"title":"部门查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (36, '部门新增', 0, ' ', 8, '', 1, 'system:dept:add', '{"title":"部门新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (37, '部门修改', 0, ' ', 8, '', 1, 'system:dept:edit', '{"title":"部门修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (38, '部门删除', 0, ' ', 8, '', 1, 'system:dept:remove', '{"title":"部门删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (39, '岗位查询', 0, ' ', 9, '', 1, 'system:post:query', '{"title":"岗位查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (40, '岗位新增', 0, ' ', 9, '', 1, 'system:post:add', '{"title":"岗位新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (41, '岗位修改', 0, ' ', 9, '', 1, 'system:post:edit', '{"title":"岗位修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (42, '岗位删除', 0, ' ', 9, '', 1, 'system:post:remove', '{"title":"岗位删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (43, '岗位导出', 0, ' ', 9, '', 1, 'system:post:export', '{"title":"岗位导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (44, '参数查询', 0, ' ', 10, '', 1, 'system:config:query', '{"title":"参数查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (45, '参数新增', 0, ' ', 10, '', 1, 'system:config:add', '{"title":"参数新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (46, '参数修改', 0, ' ', 10, '', 1, 'system:config:edit', '{"title":"参数修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (47, '参数删除', 0, ' ', 10, '', 1, 'system:config:remove', '{"title":"参数删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (48, '参数导出', 0, ' ', 10, '', 1, 'system:config:export', '{"title":"参数导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (49, '公告查询', 0, ' ', 11, '', 1, 'system:notice:query', '{"title":"公告查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (50, '公告新增', 0, ' ', 11, '', 1, 'system:notice:add', '{"title":"公告新增"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (51, '公告修改', 0, ' ', 11, '', 1, 'system:notice:edit', '{"title":"公告修改"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (52, '公告删除', 0, ' ', 11, '', 1, 'system:notice:remove', '{"title":"公告删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (53, '操作查询', 0, ' ', 18, '', 1, 'monitor:operlog:query', '{"title":"操作查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (54, '操作删除', 0, ' ', 18, '', 1, 'monitor:operlog:remove', '{"title":"操作删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (55, '日志导出', 0, ' ', 18, '', 1, 'monitor:operlog:export', '{"title":"日志导出"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (56, '登录查询', 0, ' ', 19, '', 1, 'monitor:logininfor:query', '{"title":"登录查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (57, '登录删除', 0, ' ', 19, '', 1, 'monitor:logininfor:remove', '{"title":"登录删除"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (58, '日志导出', 0, ' ', 19, '', 1, 'monitor:logininfor:export', '{"title":"日志导出","rank":22}', 1, '', 0, '2022-05-21 08:30:54', 1, '2023-07-22 17:02:28', 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (59, '在线查询', 0, ' ', 13, '', 1, 'monitor:online:query', '{"title":"在线查询"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (60, '批量强退', 0, ' ', 13, '', 1, 'monitor:online:batchLogout', '{"title":"批量强退"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (61, '单条强退', 0, ' ', 13, '', 1, 'monitor:online:forceLogout', '{"title":"单条强退"}', 1, '', 0, '2022-05-21 08:30:54', null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (62, '首页', 2, '', 0, '/global', 0, '121212', '{"title":"首页","showParent":true,"rank":3}', 1, '', 1, '2023-07-24 22:36:03', 1, '2023-07-24 22:38:37', 1);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (63, '个人中心', 1, 'PersonalCenter', 2053, '/system/user/profile', 0, '434sdf', '{"title":"个人中心","showParent":true,"rank":3}', 1, '', 1, '2023-07-24 22:36:55', null, null, 1);
|
||||
|
||||
create table sys_notice
|
||||
(
|
||||
@@ -357,6 +360,123 @@ create table sys_user
|
||||
comment '用户信息表';
|
||||
|
||||
INSERT INTO sys_user (user_id, post_id, role_id, dept_id, username, nickname, user_type, email, phone_number, sex, avatar, password, status, login_ip, login_date, is_admin, creator_id, create_time, updater_id, update_time, remark, deleted) VALUES (1, 1, 1, 4, 'admin', 'valarchie1', 0, 'agileboot@163.com', '15888888883', 0, '/profile/avatar/20230725164110_blob_6b7a989b1cdd4dd396665d2cfd2addc5.png', '$2a$10$o55UFZAtyWnDpRV6dvQe8.c/MjlFacC49ASj2usNXm9BY74SYI/uG', 1, '127.0.0.1', '2023-08-14 23:07:03', 1, null, '2022-05-21 08:30:54', 1, '2023-08-14 23:07:03', '管理员', 0);
|
||||
INSERT INTO sys_user (user_id, post_id, role_id, dept_id, username, nickname, user_type, email, phone_number, sex, avatar, password, status, login_ip, login_date, is_admin, creator_id, create_time, updater_id, update_time, remark, deleted) VALUES (2, 2, 2, 5, 'ag1', 'valarchie2', 0, 'agileboot1@qq.com', '15666666666', 1, '/profile/avatar/20230725114818_avatar_b5bf400732bb43369b4df58802049b22.png', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', 1, '127.0.0.1', '2022-05-21 08:30:54', 0, null, '2022-05-21 08:30:54', null, null, '测试员1', 0);
|
||||
INSERT INTO sys_user (user_id, post_id, role_id, dept_id, username, nickname, user_type, email, phone_number, sex, avatar, password, status, login_ip, login_date, is_admin, creator_id, create_time, updater_id, update_time, remark, deleted) VALUES (3, 2, 0, 5, 'ag2', 'valarchie3', 0, 'agileboot2@qq.com', '15666666667', 1, '/profile/avatar/20230725114818_avatar_b5bf400732bb43369b4df58802049b22.png', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', 1, '127.0.0.1', '2022-05-21 08:30:54', 0, null, '2022-05-21 08:30:54', null, null, '测试员2', 0);
|
||||
|
||||
create table collaboration_record
|
||||
(
|
||||
record_id bigint auto_increment comment '合作记录ID'
|
||||
primary key,
|
||||
brand varchar(100) not null comment '品牌',
|
||||
goods varchar(100) not null comment '物品',
|
||||
cooperation_platform varchar(50) null comment '合作平台',
|
||||
image_return_num int default 1 not null comment '返图数量',
|
||||
retained_method varchar(30) default '寄拍' not null comment '留存方式',
|
||||
cooperated_method varchar(30) default '水下' not null comment '合作方式',
|
||||
purchase_method varchar(30) default '拍单' not null comment '购入方式',
|
||||
purchase_price decimal(10, 2) null comment '购入金额',
|
||||
purchase_date date null comment '购入日期',
|
||||
purchase_platform varchar(30) null comment '购入平台',
|
||||
deadline date not null comment '预完成日期',
|
||||
remuneration decimal(10, 2) null comment '稿费',
|
||||
complete_date date null comment '完成日期',
|
||||
requirements varchar(1000) null comment '拍摄要求',
|
||||
remark varchar(1000) null comment '备注',
|
||||
creator_id bigint null comment '创建者ID',
|
||||
create_time datetime null comment '创建时间',
|
||||
updater_id bigint null comment '更新者ID',
|
||||
update_time datetime null comment '更新时间',
|
||||
deleted tinyint(1) default 0 not null comment '逻辑删除',
|
||||
index idx_collaboration_record_platform (cooperation_platform),
|
||||
index idx_collaboration_record_deadline (deadline),
|
||||
index idx_collaboration_record_purchase_date (purchase_date)
|
||||
)
|
||||
comment '合作记录表';
|
||||
|
||||
create table collaboration_task
|
||||
(
|
||||
task_id bigint auto_increment comment '笔记任务ID'
|
||||
primary key,
|
||||
record_id bigint not null comment '合作记录ID',
|
||||
release_date date null comment '发布日期',
|
||||
sort_order int default 0 not null comment '排序',
|
||||
creator_id bigint null comment '创建者ID',
|
||||
create_time datetime null comment '创建时间',
|
||||
updater_id bigint null comment '更新者ID',
|
||||
update_time datetime null comment '更新时间',
|
||||
deleted tinyint(1) default 0 not null comment '逻辑删除',
|
||||
index idx_collaboration_task_record_id (record_id)
|
||||
)
|
||||
comment '合作笔记任务表';
|
||||
|
||||
create table collaboration_expenditure
|
||||
(
|
||||
expenditure_id bigint auto_increment comment '支出ID'
|
||||
primary key,
|
||||
record_id bigint not null comment '合作记录ID',
|
||||
spend_date date null comment '支出日期',
|
||||
amount decimal(10, 2) null comment '支出金额',
|
||||
purpose varchar(30) null comment '支出用途',
|
||||
creator_id bigint null comment '创建者ID',
|
||||
create_time datetime null comment '创建时间',
|
||||
updater_id bigint null comment '更新者ID',
|
||||
update_time datetime null comment '更新时间',
|
||||
deleted tinyint(1) default 0 not null comment '逻辑删除',
|
||||
index idx_collaboration_expenditure_record_id (record_id),
|
||||
index idx_collaboration_expenditure_spend_date (spend_date)
|
||||
)
|
||||
comment '合作支出表';
|
||||
|
||||
create table collaboration_settlement
|
||||
(
|
||||
settlement_id bigint auto_increment comment '结款ID'
|
||||
primary key,
|
||||
record_id bigint not null comment '合作记录ID',
|
||||
settle_date date null comment '结款日期',
|
||||
method varchar(30) null comment '结款方式',
|
||||
income decimal(10, 2) null comment '结款金额',
|
||||
purpose varchar(30) null comment '结款用途',
|
||||
creator_id bigint null comment '创建者ID',
|
||||
create_time datetime null comment '创建时间',
|
||||
updater_id bigint null comment '更新者ID',
|
||||
update_time datetime null comment '更新时间',
|
||||
deleted tinyint(1) default 0 not null comment '逻辑删除',
|
||||
index idx_collaboration_settlement_record_id (record_id),
|
||||
index idx_collaboration_settlement_date (settle_date),
|
||||
index idx_collaboration_settlement_purpose (purpose)
|
||||
)
|
||||
comment '合作结款表';
|
||||
|
||||
create table collaboration_file
|
||||
(
|
||||
file_id bigint auto_increment comment '文件ID'
|
||||
primary key,
|
||||
record_id bigint not null comment '合作记录ID',
|
||||
file_type varchar(30) not null comment '文件类型:GOODS_IMAGE/ATTACHMENT',
|
||||
url varchar(500) not null comment '访问地址',
|
||||
file_name varchar(300) null comment '服务端相对路径',
|
||||
new_file_name varchar(200) null comment '服务端新文件名',
|
||||
original_filename varchar(300) null comment '原始文件名',
|
||||
sort_order int default 0 not null comment '排序',
|
||||
creator_id bigint null comment '创建者ID',
|
||||
create_time datetime null comment '创建时间',
|
||||
updater_id bigint null comment '更新者ID',
|
||||
update_time datetime null comment '更新时间',
|
||||
deleted tinyint(1) default 0 not null comment '逻辑删除',
|
||||
index idx_collaboration_file_record_id (record_id),
|
||||
index idx_collaboration_file_type (file_type)
|
||||
)
|
||||
comment '合作文件表';
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3000, '合作管理', 2, '', 0, '/collaboration', 0, '', '{"title":"合作管理","icon":"ep:connection","showParent":true,"rank":4}', 1, '合作管理目录', 0, now(), null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3001, '合作记录', 1, 'CollaborationRecord', 3000, '/collaboration/record/index', 0, 'collaboration:record:list', '{"title":"合作记录","icon":"ep:notebook","showParent":true}', 1, '合作记录菜单', 0, now(), null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3002, '月度统计', 1, 'CollaborationStatistics', 3000, '/collaboration/statistics/index', 0, 'collaboration:record:statistics', '{"title":"月度统计","icon":"ep:data-analysis","showParent":true}', 1, '月度统计菜单', 0, now(), null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3003, '合作查询', 0, ' ', 3001, '', 1, 'collaboration:record:query', '{"title":"合作查询"}', 1, '', 0, now(), null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3004, '合作新增', 0, ' ', 3001, '', 1, 'collaboration:record:add', '{"title":"合作新增"}', 1, '', 0, now(), null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3005, '合作修改', 0, ' ', 3001, '', 1, 'collaboration:record:edit', '{"title":"合作修改"}', 1, '', 0, now(), null, null, 0);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, menu_type, router_name, parent_id, path, is_button, permission, meta_info, status, remark, creator_id, create_time, updater_id, update_time, deleted) VALUES (3006, '合作删除', 0, ' ', 3001, '', 1, 'collaboration:record:remove', '{"title":"合作删除"}', 1, '', 0, now(), null, null, 0);
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 3000);
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 3001);
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 3002);
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 3003);
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 3004);
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 3005);
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES (2, 3006);
|
||||
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
Navicat MySQL Data Transfer
|
||||
|
||||
Source Server : Local-Mysql
|
||||
Source Server Version : 80029
|
||||
Source Host : localhost:33066
|
||||
Source Database : agileboot
|
||||
|
||||
Target Server Type : MYSQL
|
||||
Target Server Version : 80029
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 2022-10-07 16:05:40
|
||||
*/
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_config
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_config`;
|
||||
CREATE TABLE `sys_config` (
|
||||
`config_id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键',
|
||||
`config_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '配置名称',
|
||||
`config_key` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '配置键名',
|
||||
`config_options` varchar(1024) NOT NULL DEFAULT '' COMMENT '可选的选项',
|
||||
`config_value` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '配置值',
|
||||
`is_allow_change` tinyint(1) NOT NULL COMMENT '是否允许修改',
|
||||
`creator_id` bigint DEFAULT NULL COMMENT '创建者ID',
|
||||
`updater_id` bigint DEFAULT NULL COMMENT '更新者ID',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
|
||||
PRIMARY KEY (`config_id`),
|
||||
UNIQUE KEY `config_key_uniq_idx` (`config_key`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='参数配置表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_config
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_config` VALUES ('1', '主框架页-默认皮肤样式名称', 'sys.index.skinName', '["skin-blue","skin-green","skin-purple","skin-red","skin-yellow"]', 'skin-blue', '1', null, null, '2022-08-28 22:12:19', '2022-05-21 08:30:55', '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', '0');
|
||||
INSERT INTO `sys_config` VALUES ('2', '用户管理-账号初始密码', 'sys.user.initPassword', '', '1234567', '1', null, null, '2022-08-28 21:54:19', '2022-05-21 08:30:55', '初始化密码 123456', '0');
|
||||
INSERT INTO `sys_config` VALUES ('3', '主框架页-侧边栏主题', 'sys.index.sideTheme', '["theme-dark","theme-light"]', 'theme-dark', '1', null, null, '2022-08-28 22:12:15', '2022-08-20 08:30:55', '深色主题theme-dark,浅色主题theme-light', '0');
|
||||
INSERT INTO `sys_config` VALUES ('4', '账号自助-验证码开关', 'sys.account.captchaOnOff', '["true","false"]', 'false', '0', null, null, '2022-08-28 22:03:37', '2022-05-21 08:30:55', '是否开启验证码功能(true开启,false关闭)', '0');
|
||||
INSERT INTO `sys_config` VALUES ('5', '账号自助-是否开启用户注册功能', 'sys.account.registerUser', '["true","false"]', 'true', '0', null, '1', '2022-10-05 22:18:57', '2022-05-21 08:30:55', '是否开启注册用户功能(true开启,false关闭)', '0');
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_dept
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_dept`;
|
||||
CREATE TABLE `sys_dept` (
|
||||
`dept_id` bigint NOT NULL AUTO_INCREMENT COMMENT '部门id',
|
||||
`parent_id` bigint NOT NULL DEFAULT '0' COMMENT '父部门id',
|
||||
`ancestors` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '祖级列表',
|
||||
`dept_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '部门名称',
|
||||
`order_num` int NOT NULL DEFAULT '0' COMMENT '显示顺序',
|
||||
`leader_id` bigint DEFAULT NULL,
|
||||
`leader_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '负责人',
|
||||
`phone` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '联系电话',
|
||||
`email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '邮箱',
|
||||
`status` smallint NOT NULL DEFAULT '0' COMMENT '部门状态(0停用 1启用)',
|
||||
`creator_id` bigint DEFAULT NULL COMMENT '创建者ID',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updater_id` bigint DEFAULT NULL COMMENT '更新者ID',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
|
||||
PRIMARY KEY (`dept_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=203 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='部门表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_dept
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_dept` VALUES ('1', '0', '0', 'AgileBoot科技', '0', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('2', '1', '0,1', '深圳总公司', '1', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('3', '1', '0,1', '长沙分公司', '2', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('4', '2', '0,1,2', '研发部门', '1', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('5', '2', '0,1,2', '市场部门', '2', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('6', '2', '0,1,2', '测试部门', '3', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('7', '2', '0,1,2', '财务部门', '4', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('8', '2', '0,1,2', '运维部门', '5', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('9', '3', '0,1,3', '市场部门', '1', null, 'valarchie', '15888888888', 'valarchie@163.com', '1', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_dept` VALUES ('10', '3', '0,1,3', '财务部门', '2', null, 'valarchie', '15888888888', 'valarchie@163.com', '0', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_login_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_login_info`;
|
||||
CREATE TABLE `sys_login_info` (
|
||||
`info_id` bigint NOT NULL AUTO_INCREMENT COMMENT '访问ID',
|
||||
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户账号',
|
||||
`ip_address` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '登录IP地址',
|
||||
`login_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '登录地点',
|
||||
`browser` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '浏览器类型',
|
||||
`operation_system` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作系统',
|
||||
`status` smallint NOT NULL DEFAULT '0' COMMENT '登录状态(1成功 0失败)',
|
||||
`msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '提示消息',
|
||||
`login_time` datetime DEFAULT NULL COMMENT '访问时间',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
|
||||
PRIMARY KEY (`info_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=415 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统访问记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_login_info
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_menu
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_menu`;
|
||||
CREATE TABLE `sys_menu` (
|
||||
`menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
|
||||
`menu_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单名称',
|
||||
`parent_id` bigint NOT NULL DEFAULT '0' COMMENT '父菜单ID',
|
||||
`order_num` int NOT NULL DEFAULT '0' COMMENT '显示顺序',
|
||||
`path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '路由地址',
|
||||
`component` varchar(255) DEFAULT NULL COMMENT '组件路径',
|
||||
`query` varchar(255) DEFAULT NULL COMMENT '路由参数',
|
||||
`is_external` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否为外链(1是 0否)',
|
||||
`is_cache` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否缓存(1缓存 0不缓存)',
|
||||
`menu_type` smallint NOT NULL DEFAULT '0' COMMENT '菜单类型(M=1目录 C=2菜单 F=3按钮)',
|
||||
`is_visible` tinyint(1) NOT NULL DEFAULT '0' COMMENT '菜单状态(1显示 0隐藏)',
|
||||
`status` smallint NOT NULL DEFAULT '0' COMMENT '菜单状态(1启用 0停用)',
|
||||
`perms` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '权限标识',
|
||||
`icon` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '#' COMMENT '菜单图标',
|
||||
`creator_id` bigint DEFAULT NULL COMMENT '创建者ID',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updater_id` bigint DEFAULT NULL COMMENT '更新者ID',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`remark` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '备注',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
|
||||
PRIMARY KEY (`menu_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2007 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='菜单权限表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_menu
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_menu` VALUES ('1', '系统管理', '0', '1', 'system', null, '', '0', '1', '1', '1', '1', '', 'system', '0', '2022-05-21 08:30:54', null, null, '系统管理目录', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('2', '系统监控', '0', '2', 'monitor', null, '', '0', '1', '1', '1', '1', '', 'monitor', '0', '2022-05-21 08:30:54', null, null, '系统监控目录', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('3', '系统工具', '0', '3', 'tool', null, '', '0', '1', '1', '1', '1', '', 'tool', '0', '2022-05-21 08:30:54', null, null, '系统工具目录', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('4', 'AgileBoot官网', '0', '4', 'https://juejin.cn/column/7159946528827080734', null, '', '1', '1', '1', '1', '1', '', 'guide', '0', '2022-05-21 08:30:54', null, null, 'Agileboot官网地址', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('5', '用户管理', '1', '1', 'user', 'system/user/index', '', '0', '1', '2', '1', '1', 'system:user:list', 'user', '0', '2022-05-21 08:30:54', null, null, '用户管理菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('6', '角色管理', '1', '2', 'role', 'system/role/index', '', '0', '1', '2', '1', '1', 'system:role:list', 'peoples', '0', '2022-05-21 08:30:54', null, null, '角色管理菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('7', '菜单管理', '1', '3', 'menu', 'system/menu/index', '', '0', '1', '2', '1', '1', 'system:menu:list', 'tree-table', '0', '2022-05-21 08:30:54', null, null, '菜单管理菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('8', '部门管理', '1', '4', 'dept', 'system/dept/index', '', '0', '1', '2', '1', '1', 'system:dept:list', 'tree', '0', '2022-05-21 08:30:54', null, null, '部门管理菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('9', '岗位管理', '1', '5', 'post', 'system/post/index', '', '0', '1', '2', '1', '1', 'system:post:list', 'post', '0', '2022-05-21 08:30:54', null, null, '岗位管理菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('10', '参数设置', '1', '7', 'config', 'system/config/index', '', '0', '1', '2', '1', '1', 'system:config:list', 'edit', '0', '2022-05-21 08:30:54', null, null, '参数设置菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('11', '通知公告', '1', '8', 'notice', 'system/notice/index', '', '0', '1', '2', '1', '1', 'system:notice:list', 'message', '0', '2022-05-21 08:30:54', null, null, '通知公告菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('12', '日志管理', '1', '9', 'log', '', '', '0', '1', '1', '1', '1', '', 'log', '0', '2022-05-21 08:30:54', null, null, '日志管理菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('13', '在线用户', '2', '1', 'online', 'monitor/online/index', '', '0', '1', '2', '1', '1', 'monitor:online:list', 'online', '0', '2022-05-21 08:30:54', null, null, '在线用户菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('14', '数据监控', '2', '3', 'druid', 'monitor/druid/index', '', '0', '1', '2', '1', '1', 'monitor:druid:list', 'druid', '0', '2022-05-21 08:30:54', null, null, '数据监控菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('15', '服务监控', '2', '4', 'server', 'monitor/server/index', '', '0', '1', '2', '1', '1', 'monitor:server:list', 'server', '0', '2022-05-21 08:30:54', null, null, '服务监控菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('16', '缓存监控', '2', '5', 'cache', 'monitor/cache/index', '', '0', '1', '2', '1', '1', 'monitor:cache:list', 'redis', '0', '2022-05-21 08:30:54', null, null, '缓存监控菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('17', '系统接口', '3', '3', 'swagger', 'tool/swagger/index', '', '0', '1', '2', '1', '1', 'tool:swagger:list', 'swagger', '0', '2022-05-21 08:30:54', null, null, '系统接口菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('18', '操作日志', '12', '1', 'operlog', 'monitor/operlog/index', '', '0', '1', '2', '1', '1', 'monitor:operlog:list', 'form', '0', '2022-05-21 08:30:54', null, null, '操作日志菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('19', '登录日志', '12', '2', 'logininfor', 'monitor/logininfor/index', '', '0', '1', '2', '1', '1', 'monitor:logininfor:list', 'logininfor', '0', '2022-05-21 08:30:54', null, null, '登录日志菜单', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('20', '用户查询', '5', '1', '', '', '', '0', '1', '3', '1', '1', 'system:user:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('21', '用户新增', '5', '2', '', '', '', '0', '1', '3', '1', '1', 'system:user:add', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('22', '用户修改', '5', '3', '', '', '', '0', '1', '3', '1', '1', 'system:user:edit', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('23', '用户删除', '5', '4', '', '', '', '0', '1', '3', '1', '1', 'system:user:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('24', '用户导出', '5', '5', '', '', '', '0', '1', '3', '1', '1', 'system:user:export', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('25', '用户导入', '5', '6', '', '', '', '0', '1', '3', '1', '1', 'system:user:import', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('26', '重置密码', '5', '7', '', '', '', '0', '1', '3', '1', '1', 'system:user:resetPwd', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('27', '角色查询', '6', '1', '', '', '', '0', '1', '3', '1', '1', 'system:role:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('28', '角色新增', '6', '2', '', '', '', '0', '1', '3', '1', '1', 'system:role:add', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('29', '角色修改', '6', '3', '', '', '', '0', '1', '3', '1', '1', 'system:role:edit', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('30', '角色删除', '6', '4', '', '', '', '0', '1', '3', '1', '1', 'system:role:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('31', '角色导出', '6', '5', '', '', '', '0', '1', '3', '1', '1', 'system:role:export', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('32', '菜单查询', '7', '1', '', '', '', '0', '1', '3', '1', '1', 'system:menu:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('33', '菜单新增', '7', '2', '', '', '', '0', '1', '3', '1', '1', 'system:menu:add', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('34', '菜单修改', '7', '3', '', '', '', '0', '1', '3', '1', '1', 'system:menu:edit', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('35', '菜单删除', '7', '4', '', '', '', '0', '1', '3', '1', '1', 'system:menu:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('36', '部门查询', '8', '1', '', '', '', '0', '1', '3', '1', '1', 'system:dept:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('37', '部门新增', '8', '2', '', '', '', '0', '1', '3', '1', '1', 'system:dept:add', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('38', '部门修改', '8', '3', '', '', '', '0', '1', '3', '1', '1', 'system:dept:edit', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('39', '部门删除', '8', '4', '', '', '', '0', '1', '3', '1', '1', 'system:dept:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('40', '岗位查询', '9', '1', '', '', '', '0', '1', '3', '1', '1', 'system:post:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('41', '岗位新增', '9', '2', '', '', '', '0', '1', '3', '1', '1', 'system:post:add', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('42', '岗位修改', '9', '3', '', '', '', '0', '1', '3', '1', '1', 'system:post:edit', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('43', '岗位删除', '9', '4', '', '', '', '0', '1', '3', '1', '1', 'system:post:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('44', '岗位导出', '9', '5', '', '', '', '0', '1', '3', '1', '1', 'system:post:export', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('45', '参数查询', '10', '1', '#', '', '', '0', '1', '3', '1', '1', 'system:config:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('46', '参数新增', '10', '2', '#', '', '', '0', '1', '3', '1', '1', 'system:config:add', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('47', '参数修改', '10', '3', '#', '', '', '0', '1', '3', '1', '1', 'system:config:edit', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('48', '参数删除', '10', '4', '#', '', '', '0', '1', '3', '1', '1', 'system:config:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('49', '参数导出', '10', '5', '#', '', '', '0', '1', '3', '1', '1', 'system:config:export', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('50', '公告查询', '11', '1', '#', '', '', '0', '1', '3', '1', '1', 'system:notice:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('51', '公告新增', '11', '2', '#', '', '', '0', '1', '3', '1', '1', 'system:notice:add', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('52', '公告修改', '11', '3', '#', '', '', '0', '1', '3', '1', '1', 'system:notice:edit', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('53', '公告删除', '11', '4', '#', '', '', '0', '1', '3', '1', '1', 'system:notice:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('54', '操作查询', '18', '1', '#', '', '', '0', '1', '3', '1', '1', 'monitor:operlog:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('55', '操作删除', '18', '2', '#', '', '', '0', '1', '3', '1', '1', 'monitor:operlog:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('56', '日志导出', '18', '4', '#', '', '', '0', '1', '3', '1', '1', 'monitor:operlog:export', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('57', '登录查询', '19', '1', '#', '', '', '0', '1', '3', '1', '1', 'monitor:logininfor:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('58', '登录删除', '19', '2', '#', '', '', '0', '1', '3', '1', '1', 'monitor:logininfor:remove', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('59', '日志导出', '19', '3', '#', '', '', '0', '1', '3', '1', '1', 'monitor:logininfor:export', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('60', '在线查询', '13', '1', '#', '', '', '0', '1', '3', '1', '1', 'monitor:online:query', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('61', '批量强退', '13', '2', '#', '', '', '0', '1', '3', '1', '1', 'monitor:online:batchLogout', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
INSERT INTO `sys_menu` VALUES ('62', '单条强退', '13', '3', '#', '', '', '0', '1', '3', '1', '1', 'monitor:online:forceLogout', '#', '0', '2022-05-21 08:30:54', null, null, '', '0');
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_notice
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_notice`;
|
||||
CREATE TABLE `sys_notice` (
|
||||
`notice_id` int NOT NULL AUTO_INCREMENT COMMENT '公告ID',
|
||||
`notice_title` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '公告标题',
|
||||
`notice_type` smallint NOT NULL COMMENT '公告类型(1通知 2公告)',
|
||||
`notice_content` text COMMENT '公告内容',
|
||||
`status` smallint NOT NULL DEFAULT '0' COMMENT '公告状态(1正常 0关闭)',
|
||||
`creator_id` bigint NOT NULL COMMENT '创建者ID',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updater_id` bigint DEFAULT NULL COMMENT '更新者ID',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
|
||||
PRIMARY KEY (`notice_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='通知公告表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_notice
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_notice` VALUES ('1', '温馨提醒:2018-07-01 AgileBoot新版本发布啦', '2', '新版本内容~~~~~~~~~~', '1', '1', '2022-05-21 08:30:55', '1', '2022-08-29 20:12:37', '管理员', '0');
|
||||
INSERT INTO `sys_notice` VALUES ('2', '维护通知:2018-07-01 AgileBoot系统凌晨维护', '1', '维护内容', '1', '1', '2022-05-21 08:30:55', null, null, '管理员', '0');
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_operation_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_operation_log`;
|
||||
CREATE TABLE `sys_operation_log` (
|
||||
`operation_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键',
|
||||
`business_type` smallint NOT NULL DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)',
|
||||
`request_method` smallint NOT NULL DEFAULT '0' COMMENT '请求方式',
|
||||
`request_module` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '请求模块',
|
||||
`request_url` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '请求URL',
|
||||
`called_method` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '调用方法',
|
||||
`operator_type` smallint NOT NULL DEFAULT '0' COMMENT '操作类别(0其它 1后台用户 2手机端用户)',
|
||||
`user_id` bigint DEFAULT '0' COMMENT '用户ID',
|
||||
`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '操作人员',
|
||||
`operator_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '操作人员ip',
|
||||
`operator_location` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '操作地点',
|
||||
`dept_id` bigint DEFAULT '0' COMMENT '部门ID',
|
||||
`dept_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '部门名称',
|
||||
`operation_param` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '请求参数',
|
||||
`operation_result` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '返回参数',
|
||||
`status` smallint NOT NULL DEFAULT '1' COMMENT '操作状态(1正常 0异常)',
|
||||
`error_stack` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '错误消息',
|
||||
`operation_time` datetime NOT NULL COMMENT '操作时间',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
|
||||
PRIMARY KEY (`operation_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=379 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='操作日志记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_operation_log
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_post
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_post`;
|
||||
CREATE TABLE `sys_post` (
|
||||
`post_id` bigint NOT NULL AUTO_INCREMENT COMMENT '岗位ID',
|
||||
`post_code` varchar(64) NOT NULL COMMENT '岗位编码',
|
||||
`post_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '岗位名称',
|
||||
`post_sort` int NOT NULL COMMENT '显示顺序',
|
||||
`status` smallint NOT NULL COMMENT '状态(1正常 0停用)',
|
||||
`remark` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
||||
`creator_id` bigint DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updater_id` bigint DEFAULT NULL,
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',
|
||||
PRIMARY KEY (`post_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='岗位信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_post
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_post` VALUES ('1', 'ceo', '董事长', '1', '1', '', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_post` VALUES ('2', 'se', '项目经理', '2', '1', '', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_post` VALUES ('3', 'hr', '人力资源', '3', '1', '', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
INSERT INTO `sys_post` VALUES ('4', 'user', '普通员工', '5', '0', '', null, '2022-05-21 08:30:54', null, null, '0');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_role
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_role`;
|
||||
CREATE TABLE `sys_role` (
|
||||
`role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
|
||||
`role_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色名称',
|
||||
`role_key` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色权限字符串',
|
||||
`role_sort` int NOT NULL COMMENT '显示顺序',
|
||||
`data_scope` smallint DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3: 本部门数据权限 4: 本部门及以下数据权限 5: 本人权限)',
|
||||
`dept_id_set` varchar(1024) DEFAULT '' COMMENT '角色所拥有的部门数据权限',
|
||||
`status` smallint NOT NULL COMMENT '角色状态(1正常 0停用)',
|
||||
`creator_id` bigint DEFAULT NULL COMMENT '创建者ID',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updater_id` bigint DEFAULT NULL COMMENT '更新者ID',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`remark` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标志(0代表存在 1代表删除)',
|
||||
PRIMARY KEY (`role_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=111 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='角色信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_role
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_role` VALUES ('1', '超级管理员', 'admin', '1', '1', '', '1', null, '2022-05-21 08:30:54', null, null, '超级管理员', '0');
|
||||
INSERT INTO `sys_role` VALUES ('2', '普通角色', 'common', '3', '2', '', '1', null, '2022-05-21 08:30:54', null, null, '普通角色', '0');
|
||||
INSERT INTO `sys_role` VALUES ('3', '闲置角色', 'unused', '4', '2', '', '0', null, '2022-05-21 08:30:54', null, null, '未使用的角色', '0');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_role_menu
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_role_menu`;
|
||||
CREATE TABLE `sys_role_menu` (
|
||||
`role_id` bigint NOT NULL COMMENT '角色ID',
|
||||
`menu_id` bigint NOT NULL COMMENT '菜单ID',
|
||||
PRIMARY KEY (`role_id`,`menu_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='角色和菜单关联表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_role_menu
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '1');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '2');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '3');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '4');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '5');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '6');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '7');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '8');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '9');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '10');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '11');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '12');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '13');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '14');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '15');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '16');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '17');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '18');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '19');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '20');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '21');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '22');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '23');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '24');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '25');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '26');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '27');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '28');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '29');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '30');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '31');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '32');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '33');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '34');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '35');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '36');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '37');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '38');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '39');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '40');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '41');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '42');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '43');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '44');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '45');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '46');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '47');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '48');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '49');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '50');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '51');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '52');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '53');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '54');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '55');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '56');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '57');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '58');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '59');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '60');
|
||||
INSERT INTO `sys_role_menu` VALUES ('2', '61');
|
||||
-- roleId = 2的权限 特地少一个 方便测试
|
||||
INSERT INTO `sys_role_menu` VALUES ('3', '1');
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_user`;
|
||||
CREATE TABLE `sys_user` (
|
||||
`user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
|
||||
`post_id` bigint DEFAULT NULL COMMENT '职位id',
|
||||
`role_id` bigint DEFAULT NULL COMMENT '角色id',
|
||||
`dept_id` bigint DEFAULT NULL COMMENT '部门ID',
|
||||
`username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户账号',
|
||||
`nick_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户昵称',
|
||||
`user_type` smallint DEFAULT '0' COMMENT '用户类型(00系统用户)',
|
||||
`email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户邮箱',
|
||||
`phone_number` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '手机号码',
|
||||
`sex` smallint DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
|
||||
`avatar` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '头像地址',
|
||||
`password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密码',
|
||||
`status` smallint NOT NULL DEFAULT '0' COMMENT '帐号状态(1正常 2停用 3冻结)',
|
||||
`login_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '最后登录IP',
|
||||
`login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
|
||||
`is_admin` tinyint(1) NOT NULL DEFAULT '0' COMMENT '超级管理员标志(1是,0否)',
|
||||
`creator_id` bigint DEFAULT NULL COMMENT '更新者ID',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`updater_id` bigint DEFAULT NULL COMMENT '更新者ID',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`remark` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标志(0代表存在 1代表删除)',
|
||||
PRIMARY KEY (`user_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_user` VALUES ('1', '1', '1', '4', 'admin', 'valarchie1', '0', 'agileboot@163.com', '15888888889', '0', '', '$2a$10$rb1wRoEIkLbIknREEN1LH.FGs4g0oOS5t6l5LQ793nRaFO.SPHDHy', '1', '127.0.0.1', '2022-10-06 17:00:06', 1, null, '2022-05-21 08:30:54', '1', '2022-10-06 17:00:06', '管理员', '0');
|
||||
INSERT INTO `sys_user` VALUES ('2', '2', '2', '5', 'ag1', 'valarchie2', '0', 'agileboot1@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '1', '127.0.0.1', '2022-05-21 08:30:54', 0, null, '2022-05-21 08:30:54', null, null, '测试员1', '0');
|
||||
INSERT INTO `sys_user` VALUES ('3', '2', '0', '5', 'ag2', 'valarchie3', '0', 'agileboot2@qq.com', '15666666667', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '1', '127.0.0.1', '2022-05-21 08:30:54', 0, null, '2022-05-21 08:30:54', null, null, '测试员2', '0');
|
||||
@@ -0,0 +1,155 @@
|
||||
# 后端业务功能开发规范
|
||||
|
||||
本文是本项目后端新增或修改业务功能时的权威规范。开发后台管理端业务模块时,必须优先遵循本项目现有架构,而不是套用通用 Spring Boot 三层模板。
|
||||
|
||||
## 架构原则
|
||||
|
||||
后端业务代码按 `Controller -> ApplicationService -> Model -> db Service/Mapper` 组织。
|
||||
|
||||
优先参考这些现有模块:
|
||||
|
||||
- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/post`
|
||||
- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/user`
|
||||
- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/role`
|
||||
- `backend/agileboot-domain/src/main/java/com/agileboot/domain/system/notice`
|
||||
- `backend/agileboot-admin/src/main/java/com/agileboot/admin/controller/system`
|
||||
|
||||
不要让 Controller 直接调用 Mapper,不要把业务规则写在 Controller,也不要直接把 Entity 或 DO 返回给前端。
|
||||
|
||||
## 开发准备
|
||||
|
||||
开发新后端业务功能前,应先确认需求所属领域、涉及的数据表、接口范围、权限标识和相似模块。本文是后端业务功能开发的统一规范。
|
||||
|
||||
开始编码前必须先做一次相似模块调研,确认目标功能最接近 `post`、`user`、`role`、`notice` 还是其他模块,再按相似模块的命名、包路径、注解、分页、异常、权限、日志和测试风格实现。
|
||||
|
||||
## 目录结构
|
||||
|
||||
后台管理端入口放在 `agileboot-admin`:
|
||||
|
||||
```text
|
||||
backend/agileboot-admin/src/main/java/com/agileboot/admin/controller/<area>/
|
||||
└── XxxController.java
|
||||
```
|
||||
|
||||
业务代码放在 `agileboot-domain`:
|
||||
|
||||
```text
|
||||
backend/agileboot-domain/src/main/java/com/agileboot/domain/<area>/xxx/
|
||||
├── XxxApplicationService.java
|
||||
├── command/
|
||||
│ ├── AddXxxCommand.java
|
||||
│ └── UpdateXxxCommand.java
|
||||
├── query/
|
||||
│ └── XxxQuery.java
|
||||
├── dto/
|
||||
│ ├── XxxDTO.java
|
||||
│ └── XxxDetailDTO.java
|
||||
├── model/
|
||||
│ ├── XxxModel.java
|
||||
│ └── XxxModelFactory.java
|
||||
└── db/
|
||||
├── XxxEntity.java
|
||||
├── XxxDO.java
|
||||
├── XxxMapper.java
|
||||
├── XxxService.java
|
||||
└── XxxServiceImpl.java
|
||||
```
|
||||
|
||||
`XxxDO` 是可选文件。只有当查询结果包含 join、聚合、报表字段或其他不完全匹配 Entity 的字段时才创建。
|
||||
|
||||
如果业务属于已有领域,例如 `system`,放到现有领域下;如果是独立业务领域,创建新的 `<area>` 包名,例如 `business`。
|
||||
|
||||
## 各层职责
|
||||
|
||||
Controller 只负责 HTTP 层:
|
||||
|
||||
- 声明 `@RestController`、`@RequestMapping`、`@Validated`、Swagger 注解。
|
||||
- 接收 `Command`、`Query`、路径参数和请求参数。
|
||||
- 使用 `@PreAuthorize("@permission.has('xxx:yyy:zzz')")` 做权限控制。
|
||||
- 对新增、修改、删除、导出等操作使用 `@AccessLog`。
|
||||
- 调用 `XxxApplicationService`。
|
||||
- 使用 `ResponseDTO.ok(...)` 返回结果。
|
||||
|
||||
ApplicationService 负责编排业务用例:
|
||||
|
||||
- 分页查询、详情查询、导出查询、新增、修改、删除。
|
||||
- 创建或加载 `XxxModel`。
|
||||
- 调用领域模型完成业务校验和状态变化。
|
||||
- 调用 `db` 包中的 Service 完成查询和持久化。
|
||||
- 将 Entity 或 DO 转换为 DTO。
|
||||
- 分页结果使用 `PageDTO<T>`。
|
||||
|
||||
Model 承载业务规则:
|
||||
|
||||
- 从 `AddXxxCommand`、`UpdateXxxCommand` 加载字段。
|
||||
- 封装唯一性校验、状态校验、是否允许删除、业务状态流转等规则。
|
||||
- 需要数据库判断时,通过构造注入的 `XxxService` 查询。
|
||||
- 业务失败时抛出 `ApiException`,不要返回布尔值让上层解释。
|
||||
|
||||
ModelFactory 负责创建和加载模型:
|
||||
|
||||
- `create()` 返回带有依赖的空模型。
|
||||
- `loadById(id)` 从数据库加载 Entity,并包装为 Model。
|
||||
- 如果未找到必要数据,按项目现有异常风格处理。
|
||||
|
||||
db 包只负责持久化:
|
||||
|
||||
- `XxxEntity` 映射数据库表。
|
||||
- `XxxDO` 承载复杂查询结果,例如关联表字段、统计字段、报表字段。
|
||||
- `XxxMapper` 继承 MyBatis Plus `BaseMapper<XxxEntity>`。
|
||||
- `XxxService` 继承 `IService<XxxEntity>`,声明复用型查询方法。
|
||||
- `XxxServiceImpl` 继承 `ServiceImpl<XxxMapper, XxxEntity>`,实现唯一性检查、关联检查、复杂查询等。
|
||||
- 复杂 SQL 放到 mapper XML,简单条件优先使用 MyBatis Plus wrapper。
|
||||
|
||||
`XxxDO` 属于数据库查询结果对象,不是前端响应对象,也不是请求对象。Mapper 或 Service 可以返回 `XxxDO`,但 ApplicationService 必须转换为 `XxxDTO` 后再交给 Controller 返回。
|
||||
|
||||
Command、Query、DTO 的边界:
|
||||
|
||||
- `Command` 用于新增、修改等写请求,不要直接接收 Entity。
|
||||
- `Query` 用于列表、搜索、分页条件,并提供 `toPage()`、`toQueryWrapper()` 等项目已有风格的方法。
|
||||
- `DTO` 用于响应前端,不要直接暴露 Entity 或 DO。
|
||||
- 批量删除优先使用 `BulkOperationCommand<Long>`。
|
||||
|
||||
## 开发流程
|
||||
|
||||
1. 检索并阅读一个最相似的现有模块,确认命名、包路径、注解、分页、异常、测试风格。
|
||||
2. 确认数据库表结构,保持主键、软删除、审计字段、字段命名与现有表一致。
|
||||
3. 创建 `db` 包:`Entity`、`Mapper`、`Service`、`ServiceImpl`;如查询结果包含关联表字段、统计字段或报表字段,再增加 `XxxDO`。
|
||||
4. 创建 API 契约:`AddXxxCommand`、`UpdateXxxCommand`、`XxxQuery`、`XxxDTO`,需要详情时添加 `XxxDetailDTO`。
|
||||
5. 创建 `XxxModel` 和 `XxxModelFactory`,把业务校验放进 Model。
|
||||
6. 创建 `XxxApplicationService`,编排查询、新增、修改、删除、导出等用例。
|
||||
7. 创建 `XxxController`,加路由、权限、操作日志和统一响应。
|
||||
8. 如功能出现在后台菜单,补充权限标识、菜单 SQL 或清楚说明需要配置的权限码。
|
||||
9. 增加聚焦测试,至少覆盖核心业务校验和主要用例。
|
||||
10. 运行相关 Maven 测试或编译检查;如果不能运行,说明原因。
|
||||
|
||||
开发过程中如果发现本文未覆盖的模式,优先参考现有模块,而不是引入新的架构风格。确实需要新增模式时,应先更新本文,再按新规范实现。
|
||||
|
||||
## 权限、日志和错误
|
||||
|
||||
权限码必须和前端菜单或按钮权限保持一致,格式参考现有系统功能:
|
||||
|
||||
```java
|
||||
@PreAuthorize("@permission.has('system:post:add')")
|
||||
```
|
||||
|
||||
操作日志按业务动作选择类型:
|
||||
|
||||
```java
|
||||
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.ADD)
|
||||
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.MODIFY)
|
||||
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.DELETE)
|
||||
@AccessLog(title = "业务名称", businessType = BusinessTypeEnum.EXPORT)
|
||||
```
|
||||
|
||||
业务错误使用 `ApiException` 和 `ErrorCode.Business`。新增业务错误时,按现有错误码结构补充枚举或常量,不要在 Controller 中拼接错误响应。
|
||||
|
||||
## 验收清单
|
||||
|
||||
- 新代码目录结构与相似模块一致。
|
||||
- Controller 只有 HTTP 编排逻辑。
|
||||
- 业务校验位于 Model 或 ApplicationService,不散落在前端或 Controller。
|
||||
- 查询返回 DTO,分页返回 `PageDTO<T>`。
|
||||
- 写请求使用 Command。
|
||||
- 复杂查询结果对象使用 DO,并在 ApplicationService 转换为 DTO。
|
||||
- 权限、日志、异常、测试和现有项目风格一致。
|
||||
@@ -0,0 +1,275 @@
|
||||
# Clean Code 契约
|
||||
|
||||
本文约束新增和修改代码时的代码质量形态。它只关注函数设计、命名、控制结构、错误处理、注释、副作用、重复和可读性,不替代前后端各自的架构开发规范。
|
||||
|
||||
## 1. 函数设计
|
||||
|
||||
- 新增或修改的函数默认不超过 20 行,不含空行和注释。
|
||||
- 业务编排函数最多不超过 30 行;超过时必须拆分。
|
||||
- 函数参数不超过 3 个;超过 3 个必须改为对象参数。
|
||||
- 圈复杂度 <= 5。
|
||||
- 嵌套深度 <= 2。
|
||||
- 必须优先使用 guard clause 提前返回,避免主流程被多层 `if` 包裹。
|
||||
- 一个函数只做一件事,不混合校验、转换、查询、保存、渲染等多个职责。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
function submit(user, form, config, notify) {
|
||||
if (user) {
|
||||
if (form.valid) {
|
||||
if (config.enabled) {
|
||||
save(user, form);
|
||||
notify.success();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
function submit(options: SubmitOptions) {
|
||||
if (!options.user) return;
|
||||
if (!options.form.valid) return;
|
||||
if (!options.config.enabled) return;
|
||||
|
||||
save(options.user, options.form);
|
||||
options.notify.success();
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 命名
|
||||
|
||||
- 布尔变量必须以 `is`、`has`、`can`、`should` 开头。
|
||||
- 执行动作的函数使用动词开头,例如 `getUser`、`validateEmail`、`saveRole`。
|
||||
- 事件处理函数使用 `handle` 或 `on` 前缀,例如 `handleSubmit`、`onDialogClose`。
|
||||
- 有副作用的函数名必须体现动作,例如 `save`、`update`、`delete`、`load`、`fetch`、`sync`。
|
||||
- 避免无意义缩写。
|
||||
- 避免单字母变量,循环索引 `i` 除外。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
const visible = user.status === "enabled";
|
||||
|
||||
function userData() {
|
||||
return api.getUser();
|
||||
}
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
const isVisible = user.status === "enabled";
|
||||
|
||||
function getUserData() {
|
||||
return api.getUser();
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 控制结构
|
||||
|
||||
- 禁止深层 `if/else`。
|
||||
- 连续分支超过 3 个时,优先使用对象映射、`switch`、策略方法或枚举方法。
|
||||
- 简单数据转换优先使用 `map`、`filter`。
|
||||
- 不为了“函数式”强行使用难读的 `reduce`。
|
||||
- 当需要提前退出、复杂流程控制或显式循环更清晰时,允许使用 `for` / `for...of`。
|
||||
- 不允许在 `switch` 或长 `if/else` 中堆大量业务逻辑,复杂分支必须拆成独立函数。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
function getStatusLabel(status: string) {
|
||||
if (status === "enabled") return "启用";
|
||||
if (status === "disabled") return "禁用";
|
||||
if (status === "pending") return "待处理";
|
||||
if (status === "locked") return "锁定";
|
||||
return "未知";
|
||||
}
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
const statusLabels: Record<string, string> = {
|
||||
enabled: "启用",
|
||||
disabled: "禁用",
|
||||
pending: "待处理",
|
||||
locked: "锁定"
|
||||
};
|
||||
|
||||
function getStatusLabel(status: string) {
|
||||
return statusLabels[status] ?? "未知";
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 错误处理
|
||||
|
||||
- 禁止吞异常。
|
||||
- 禁止空 `catch`。
|
||||
- `catch` 后必须处理、记录、转换或重新抛出异常。
|
||||
- 外部调用必须有明确错误处理,包括网络、数据库、文件、缓存、第三方服务。
|
||||
- 不允许只打印错误但不中断、不反馈、不恢复状态。
|
||||
- 不允许把异常转换成无意义的 `null`、`false` 或空数组,除非调用方能明确区分该状态。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
async function loadUser() {
|
||||
try {
|
||||
return await api.getUser();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
async function loadUser() {
|
||||
try {
|
||||
return await api.getUser();
|
||||
} catch (error) {
|
||||
showErrorMessage("用户信息加载失败");
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 注释
|
||||
|
||||
- 禁止废话注释,例如 `i++ // 增加 i`。
|
||||
- 代码能清楚表达“做了什么”时,不写解释性注释。
|
||||
- 复杂算法、特殊兼容、业务规则例外必须说明“为什么这么做”。
|
||||
- 临时方案必须标明原因和后续处理方式,避免无上下文的 `TODO`。
|
||||
- 注释必须随代码更新,禁止保留过期注释。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
// 遍历用户
|
||||
users.forEach(user => {
|
||||
// 设置名称
|
||||
user.name = user.name.trim();
|
||||
});
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
// 后端历史数据可能包含首尾空格,提交前统一清理,避免唯一性校验误判。
|
||||
const normalizedUsers = users.map(user => ({
|
||||
...user,
|
||||
name: user.name.trim()
|
||||
}));
|
||||
```
|
||||
|
||||
## 6. 副作用
|
||||
|
||||
- 优先编写纯函数:相同输入应产生相同输出。
|
||||
- 数据转换、格式化、校验逻辑应尽量保持无副作用。
|
||||
- 修改外部状态的函数必须在命名中体现副作用。
|
||||
- 不在工具函数中偷偷修改入参、全局状态、缓存或组件状态。
|
||||
- 修改入参前必须显式说明原因;默认应返回新对象或新数组。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
function normalizeUser(user: User) {
|
||||
user.name = user.name.trim();
|
||||
return user;
|
||||
}
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
function normalizeUser(user: User) {
|
||||
return {
|
||||
...user,
|
||||
name: user.name.trim()
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 重复与抽象
|
||||
|
||||
- 禁止复制粘贴相同业务逻辑。
|
||||
- 出现第 2 次重复时可以接受局部重复。
|
||||
- 出现第 3 次重复时必须抽取公共函数、组件、常量或配置。
|
||||
- 不为了“预防未来变化”提前抽象。
|
||||
- 抽象必须基于已经出现的重复或明确稳定的业务概念。
|
||||
- 公共函数必须有清晰输入输出,不能依赖隐式上下文。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
const userStatus = row.status === 1 ? "启用" : "禁用";
|
||||
const roleStatus = role.status === 1 ? "启用" : "禁用";
|
||||
const postStatus = post.status === 1 ? "启用" : "禁用";
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
function getEnabledStatusLabel(status: number) {
|
||||
return status === 1 ? "启用" : "禁用";
|
||||
}
|
||||
|
||||
const userStatus = getEnabledStatusLabel(row.status);
|
||||
const roleStatus = getEnabledStatusLabel(role.status);
|
||||
const postStatus = getEnabledStatusLabel(post.status);
|
||||
```
|
||||
|
||||
## 8. 可读性
|
||||
|
||||
- 优先让主流程从上到下阅读。
|
||||
- 变量声明尽量靠近使用位置。
|
||||
- 避免长链式调用;链式调用过长时拆成中间变量。
|
||||
- 避免布尔表达式过长;复杂条件必须提取为语义明确的变量或函数。
|
||||
- 避免魔法值;业务含义明确的数字、字符串应提取为常量。
|
||||
- 不写“聪明但难懂”的代码。
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
if ((user.age > 18 && user.status === 1 && !user.deleted) || user.role === "admin") {
|
||||
allowAccess();
|
||||
}
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
const isActiveAdult = user.age > 18 && user.status === 1 && !user.deleted;
|
||||
const isAdmin = user.role === "admin";
|
||||
|
||||
if (isActiveAdult || isAdmin) {
|
||||
allowAccess();
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 自动化检查
|
||||
|
||||
完成代码后必须运行与改动相关的检查。
|
||||
|
||||
建议静态检查覆盖:
|
||||
|
||||
- 函数长度
|
||||
- 参数数量
|
||||
- 圈复杂度
|
||||
- 嵌套深度
|
||||
- 空 `catch`
|
||||
- 未使用变量
|
||||
- 重复分支
|
||||
- 基础命名规则
|
||||
|
||||
## 10. 例外规则
|
||||
|
||||
- 如果确实需要突破本契约,必须说明原因。
|
||||
- 例外只能针对具体代码点,不能作为整个模块放宽标准的理由。
|
||||
- 为了满足行数限制而机械拆分、降低可读性的改动不接受。
|
||||
- 可读性优先于形式主义,但必须能解释为什么更清晰。
|
||||
@@ -0,0 +1,198 @@
|
||||
# Web 前端业务功能开发规范
|
||||
|
||||
本文是 `frontend/web` 新增或修改前端业务功能时的权威规范。当前 Web 项目基于 Vue 3、Vite、Element Plus、Pure Admin、Pinia、Vue Router 和项目自有 `@/utils/http` 封装。开发时必须优先复用现有目录结构、组件和工具链。
|
||||
|
||||
本文只覆盖 `frontend/web`,不覆盖 `frontend/app`。
|
||||
|
||||
## 架构原则
|
||||
|
||||
前端业务模块按“页面结构 + API 类型封装 + 业务 hook + 表单/弹窗 + 页面私有组件”组织。
|
||||
|
||||
优先参考这些现有模块:
|
||||
|
||||
- `frontend/web/src/views/system/post`
|
||||
- `frontend/web/src/views/system/user`
|
||||
- `frontend/web/src/views/system/role`
|
||||
- `frontend/web/src/views/system/notice`
|
||||
- `frontend/web/src/views/login`
|
||||
- `frontend/web/src/api/system/post.ts`
|
||||
|
||||
不要绕过 `@/utils/http` 直接使用 Axios。不要在 `index.vue` 中堆积复杂列表逻辑。不要硬编码字典状态文本、值或标签样式。
|
||||
|
||||
## 开发准备
|
||||
|
||||
开发 `frontend/web` 业务功能前,应先确认页面所属业务域、后端接口、菜单路由、权限标识、字典依赖和相似页面。本文是 Web 前端业务功能开发的统一规范。
|
||||
|
||||
开始编码前必须先做一次相似模块调研,确认目标功能最接近 `system/post`、`system/user`、`system/role`、`system/notice`、`login` 还是其他模块,再按相似模块的页面结构、API 类型、hook、表单、字典、表格、分页、排序、删除、导出、权限和组件命名风格实现。
|
||||
|
||||
## 目录结构
|
||||
|
||||
业务页面放在 `frontend/web/src/views/<area>/<module>/`:
|
||||
|
||||
```text
|
||||
frontend/web/src/views/<area>/<module>/
|
||||
├── index.vue
|
||||
├── form.vue 或 xxx-form-modal.vue
|
||||
├── components/
|
||||
│ ├── private-panel.vue
|
||||
│ └── private-fragment.vue
|
||||
└── utils/
|
||||
├── hook.tsx
|
||||
├── rule.ts
|
||||
└── types.ts
|
||||
```
|
||||
|
||||
API 放在 `frontend/web/src/api/<area>/<module>.ts`:
|
||||
|
||||
```text
|
||||
frontend/web/src/api/<area>/<module>.ts
|
||||
```
|
||||
|
||||
`components/`、`rule.ts`、`types.ts` 按需创建,不要求每个模块都存在。
|
||||
|
||||
## 页面私有组件
|
||||
|
||||
只被某个页面或模块使用的组件,放在该模块目录下的 `components/`。现有示例是 `frontend/web/src/views/login/components`。
|
||||
|
||||
页面私有组件适合承载:
|
||||
|
||||
- 页面内局部展示组件。
|
||||
- 局部表单片段。
|
||||
- 局部抽屉、局部面板、局部弹窗。
|
||||
- 只服务当前页面流程的交互单元。
|
||||
|
||||
页面私有组件不应承载整个业务模块的主流程。主列表、主表单、主弹窗仍按现有模块风格放在 `index.vue`、`form.vue` 或 `xxx-form-modal.vue`。
|
||||
|
||||
如果组件开始被第二个业务模块复用,应提升到 `frontend/web/src/components`,不要继续放在某个页面私有目录中。只有在明确属于某个业务域且多个同域模块复用时,才考虑创建 `views/<area>/components`;当前项目还没有这个模式,新增前应谨慎。
|
||||
|
||||
页面私有组件的判断标准是“是否只服务当前页面或当前模块”。如果组件包含通用交互、通用展示、通用上传、通用选择器等能力,应优先设计为公共组件,而不是藏在某个业务页面目录下。
|
||||
|
||||
## 各文件职责
|
||||
|
||||
`index.vue` 负责页面结构:
|
||||
|
||||
- 搜索表单。
|
||||
- 表格和表格插槽。
|
||||
- 工具栏按钮。
|
||||
- 弹窗、抽屉、页面私有组件的挂载。
|
||||
- `defineOptions({ name })`,组件 name 应与菜单表中的 `router_name` 保持一致。
|
||||
|
||||
`utils/hook.tsx` 负责列表业务状态和行为:
|
||||
|
||||
- 查询参数、分页、排序、loading。
|
||||
- 表格列定义。
|
||||
- 列表查询、搜索、重置。
|
||||
- 删除、批量删除、导出。
|
||||
- 字典值渲染,例如 `el-tag`。
|
||||
|
||||
`form.vue` 或 `xxx-form-modal.vue` 负责新增/编辑:
|
||||
|
||||
- 接收 `v-model` 控制显示。
|
||||
- 接收 `type`、`row` 等必要 props。
|
||||
- 维护表单数据和校验状态。
|
||||
- 调用新增/修改 API。
|
||||
- 成功后关闭并向父组件发出 `success` 事件。
|
||||
|
||||
`utils/rule.ts` 负责复杂或可复用的表单校验规则。简单模块也可以把规则放在表单组件内,保持与现有代码一致。
|
||||
|
||||
`utils/types.ts` 只放页面私有类型。跨 API 复用的请求/响应类型优先放在对应 `src/api/<area>/<module>.ts`。
|
||||
|
||||
## API 规范
|
||||
|
||||
每个业务模块在 `src/api/<area>/<module>.ts` 中封装后端接口和 TypeScript 类型。
|
||||
|
||||
接口调用使用项目 HTTP 封装:
|
||||
|
||||
```ts
|
||||
http.request<ResponseData<T>>("get", "/path", { params });
|
||||
http.request<ResponseData<void>>("post", "/path", { data });
|
||||
```
|
||||
|
||||
文件下载使用:
|
||||
|
||||
```ts
|
||||
http.download("/path/excel", fileName, { params });
|
||||
```
|
||||
|
||||
类型命名优先遵循现有风格:
|
||||
|
||||
- `XxxListCommand`:列表查询参数。
|
||||
- `XxxPageResponse`:列表响应行。
|
||||
- `AddXxxCommand`:新增请求。
|
||||
- `UpdateXxxCommand`:修改请求。
|
||||
|
||||
删除接口如果后端接收 `ids` 查询参数,按现有写法把数组转成字符串,避免 Axios 序列化为 `ids[0]`、`ids[1]`。
|
||||
|
||||
## 列表、分页和排序
|
||||
|
||||
列表页优先使用 `PureTableBar + pure-table`。
|
||||
|
||||
分页使用 `PaginationProps`,并通过 `CommonUtils.fillPaginationParams()` 填充查询参数。
|
||||
|
||||
排序使用 Element Plus `Sort`,并通过 `CommonUtils.fillSortParams()` 传给后端。
|
||||
|
||||
时间范围查询使用 `beginTime`、`endTime`,优先复用现有 computed 写法处理 `el-date-picker` 的双向绑定。
|
||||
|
||||
批量操作必须维护 `multipleSelection`,并在空选择时给出提示。
|
||||
|
||||
## 字典和状态
|
||||
|
||||
字典来自登录配置并缓存在用户 store 中。
|
||||
|
||||
下拉选项使用:
|
||||
|
||||
```ts
|
||||
useUserStoreHook().dictionaryList["common.status"]
|
||||
```
|
||||
|
||||
表格状态渲染使用:
|
||||
|
||||
```ts
|
||||
useUserStoreHook().dictionaryMap["common.status"]
|
||||
```
|
||||
|
||||
不要在页面中硬编码状态 label、value、`el-tag` 类型。字典不存在或可能为空时,新增代码应避免直接访问导致运行时报错。
|
||||
|
||||
## 交互和组件
|
||||
|
||||
按钮图标优先使用 `useRenderIcon()` 和现有 iconify 图标。
|
||||
|
||||
新增/编辑弹窗优先复用 `VDialog` 或相似模块的弹窗写法。
|
||||
|
||||
单条删除使用 `el-popconfirm` 或模块现有风格。批量删除使用 `ElMessageBox.confirm` 时,必须处理取消分支并清理选择状态。
|
||||
|
||||
操作成功后刷新列表。弹窗通过 `v-model` 和 `success` 事件与父组件通信。
|
||||
|
||||
跨业务通用能力优先放在 `src/components` 或 `src/utils`;页面私有能力保持在页面目录内。
|
||||
|
||||
## 权限、路由和菜单
|
||||
|
||||
后台业务菜单主要依赖后端菜单和动态路由。新页面的组件 name 必须与菜单表中的 `router_name` 保持一致。
|
||||
|
||||
不要随意新增静态路由。只有登录页、重定向、个人中心等固定页面才参考 `src/router/modules` 中的静态路由模式。
|
||||
|
||||
如需要按钮权限,优先复用项目已有的 `ReAuth` 或 auth directive 模式,不要自行实现一套权限判断。
|
||||
|
||||
## 验证清单
|
||||
|
||||
前端改动后优先运行:
|
||||
|
||||
```bash
|
||||
pnpm --dir frontend/web typecheck
|
||||
pnpm --dir frontend/web lint
|
||||
```
|
||||
|
||||
如果依赖未安装或环境不允许运行,说明原因。
|
||||
|
||||
如果只修改文档,不需要运行前端 typecheck 或 lint;如果修改了 TypeScript、Vue、样式或路由/API 文件,应优先运行上述检查。
|
||||
|
||||
业务页面至少检查:
|
||||
|
||||
- 列表加载。
|
||||
- 搜索和重置。
|
||||
- 分页和排序。
|
||||
- 新增和编辑。
|
||||
- 单条删除和批量删除。
|
||||
- 导出。
|
||||
- 字典下拉和表格状态展示。
|
||||
- 弹窗关闭、成功回调和列表刷新。
|
||||
@@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
tabWidth: 2,
|
||||
bracketSpacing: true,
|
||||
singleQuote: false,
|
||||
arrowParens: "avoid",
|
||||
trailingComma: "none"
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
dist/
|
||||
deploy_versions/
|
||||
.temp/
|
||||
.rn_temp/
|
||||
node_modules/
|
||||
.DS_Store
|
||||
.swc
|
||||
*.local
|
||||
Generated
+29
@@ -204,6 +204,9 @@ importers:
|
||||
nprogress:
|
||||
specifier: ^0.2.0
|
||||
version: 0.2.0
|
||||
path:
|
||||
specifier: ^0.12.7
|
||||
version: 0.12.7
|
||||
pinia:
|
||||
specifier: ^2.1.4
|
||||
version: 2.3.1(typescript@5.0.4)(vue@3.5.34(typescript@5.0.4))
|
||||
@@ -3995,6 +3998,9 @@ packages:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
|
||||
|
||||
inherits@2.0.3:
|
||||
resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==}
|
||||
|
||||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
@@ -4774,6 +4780,9 @@ packages:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path@0.12.7:
|
||||
resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==}
|
||||
|
||||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
@@ -5350,6 +5359,10 @@ packages:
|
||||
process-nextick-args@2.0.1:
|
||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||
|
||||
process@0.11.10:
|
||||
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
|
||||
promise-polyfill@7.1.2:
|
||||
resolution: {integrity: sha512-FuEc12/eKqqoRYIGBrUptCBRhobL19PS2U31vMNTfyck1FxPyMfgsXyW4Mav85y/ZN1hop3hOwRlUDok23oYfQ==}
|
||||
|
||||
@@ -6216,6 +6229,9 @@ packages:
|
||||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
util@0.10.4:
|
||||
resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==}
|
||||
|
||||
uuid@8.3.2:
|
||||
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
|
||||
hasBin: true
|
||||
@@ -10917,6 +10933,8 @@ snapshots:
|
||||
once: 1.4.0
|
||||
wrappy: 1.0.2
|
||||
|
||||
inherits@2.0.3: {}
|
||||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
ini@1.3.8: {}
|
||||
@@ -11649,6 +11667,11 @@ snapshots:
|
||||
|
||||
path-type@4.0.0: {}
|
||||
|
||||
path@0.12.7:
|
||||
dependencies:
|
||||
process: 0.11.10
|
||||
util: 0.10.4
|
||||
|
||||
pathe@2.0.3:
|
||||
optional: true
|
||||
|
||||
@@ -12160,6 +12183,8 @@ snapshots:
|
||||
|
||||
process-nextick-args@2.0.1: {}
|
||||
|
||||
process@0.11.10: {}
|
||||
|
||||
promise-polyfill@7.1.2: {}
|
||||
|
||||
property-expr@2.0.6: {}
|
||||
@@ -13164,6 +13189,10 @@ snapshots:
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
util@0.10.4:
|
||||
dependencies:
|
||||
inherits: 2.0.3
|
||||
|
||||
uuid@8.3.2: {}
|
||||
|
||||
validate-html-nesting@1.2.4: {}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
packages:
|
||||
- "web"
|
||||
- "app"
|
||||
|
||||
allowBuilds:
|
||||
'@parcel/watcher': set this to true or false
|
||||
'@swc/core': set this to true or false
|
||||
'@tarojs/binding': set this to true or false
|
||||
'@tarojs/cli': set this to true or false
|
||||
core-js: set this to true or false
|
||||
core-js-pure: set this to true or false
|
||||
esbuild: set this to true or false
|
||||
typeit: set this to true or false
|
||||
vue-demi: set this to true or false
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.eslintcache
|
||||
report.html
|
||||
|
||||
yarn.lock
|
||||
npm-debug.log*
|
||||
.pnpm-error.log*
|
||||
.pnpm-debug.log
|
||||
tests/**/coverage/
|
||||
|
||||
# 本机调试debug配置文件
|
||||
.vscode/launch.json
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
tsconfig.tsbuildinfo
|
||||
Vendored
-31
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"akamud.vscode-theme-onedark",
|
||||
"antfu.iconify",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"christian-kohler.npm-intellisense",
|
||||
"christian-kohler.path-intellisense",
|
||||
"Codeium.codeium",
|
||||
"csstools.postcss",
|
||||
"DavidAnson.vscode-markdownlint",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"donjayamanne.githistory",
|
||||
"dsznajder.es7-react-js-snippets",
|
||||
"eamodio.gitlens",
|
||||
"ecmel.vscode-html-css",
|
||||
"esbenp.prettier-vscode",
|
||||
"genieai.chatgpt-vscode",
|
||||
"hollowtree.vue-snippets",
|
||||
"lokalise.i18n-ally",
|
||||
"mhutchie.git-graph",
|
||||
"mikestead.dotenv",
|
||||
"pmneo.tsimporter",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"stylelint.vscode-stylelint",
|
||||
"syler.sass-indented",
|
||||
"sysoev.language-stylus",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"Vue.volar",
|
||||
"xabikos.JavaScriptSnippets"
|
||||
]
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"Vue3.0快速生成模板": {
|
||||
"scope": "vue",
|
||||
"prefix": "Vue3.0",
|
||||
"body": [
|
||||
"<template>",
|
||||
"\t<div>test</div>",
|
||||
"</template>\n",
|
||||
"<script lang='ts'>",
|
||||
"export default {",
|
||||
"\tsetup() {",
|
||||
"\t\treturn {}",
|
||||
"\t}",
|
||||
"}",
|
||||
"</script>\n",
|
||||
"<style lang='scss' scoped>\n",
|
||||
"</style>",
|
||||
"$2"
|
||||
],
|
||||
"description": "Vue3.0"
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"Vue3.2+快速生成模板": {
|
||||
"scope": "vue",
|
||||
"prefix": "Vue3.2+",
|
||||
"body": [
|
||||
"<script setup lang='ts'>",
|
||||
"</script>\n",
|
||||
"<template>",
|
||||
"\t<div>test</div>",
|
||||
"</template>\n",
|
||||
"<style lang='scss' scoped>\n",
|
||||
"</style>",
|
||||
"$2"
|
||||
],
|
||||
"description": "Vue3.2+"
|
||||
}
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"Vue3.3+defineOptions快速生成模板": {
|
||||
"scope": "vue",
|
||||
"prefix": "Vue3.3+",
|
||||
"body": [
|
||||
"<script setup lang='ts'>",
|
||||
"defineOptions({",
|
||||
"\tname: ''",
|
||||
"})",
|
||||
"</script>\n",
|
||||
"<template>",
|
||||
"\t<div>test</div>",
|
||||
"</template>\n",
|
||||
"<style lang='scss' scoped>\n",
|
||||
"</style>",
|
||||
"$2"
|
||||
],
|
||||
"description": "Vue3.3+defineOptions快速生成模板"
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
"jsencrypt": "^3.3.2",
|
||||
"mitt": "^3.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path": "^0.12.7",
|
||||
"pinia": "^2.1.4",
|
||||
"pinyin-pro": "^3.15.2",
|
||||
"cropperjs": "^1.5.13",
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
export type SettlementStatusValue =
|
||||
| "NONE"
|
||||
| "SETTLED"
|
||||
| "UNSETTLED"
|
||||
| "PARTIAL";
|
||||
export type CollaborationFileType = "GOODS_IMAGE" | "ATTACHMENT";
|
||||
|
||||
export interface SettlementStatusDTO {
|
||||
status: SettlementStatusValue;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface CollaborationRecordListCommand extends BasePageQuery {
|
||||
brand?: string;
|
||||
goods?: string;
|
||||
cooperationPlatform?: string;
|
||||
purchaseBeginTime?: string;
|
||||
purchaseEndTime?: string;
|
||||
}
|
||||
|
||||
export interface CollaborationTaskCommand {
|
||||
releaseDate?: string;
|
||||
}
|
||||
|
||||
export interface CollaborationExpenditureCommand {
|
||||
spendDate?: string;
|
||||
amount?: number;
|
||||
purpose?: string;
|
||||
}
|
||||
|
||||
export interface CollaborationSettlementCommand {
|
||||
settleDate?: string;
|
||||
method?: string;
|
||||
income?: number;
|
||||
purpose?: string;
|
||||
}
|
||||
|
||||
export interface CollaborationFileCommand {
|
||||
fileType: CollaborationFileType;
|
||||
url: string;
|
||||
fileName?: string;
|
||||
newFileName?: string;
|
||||
originalFilename?: string;
|
||||
}
|
||||
|
||||
export interface AddCollaborationRecordCommand {
|
||||
brand: string;
|
||||
goods: string;
|
||||
cooperationPlatform?: string;
|
||||
imageReturnNum: number;
|
||||
retainedMethod?: string;
|
||||
cooperatedMethod?: string;
|
||||
purchaseMethod?: string;
|
||||
purchasePrice?: number;
|
||||
purchaseDate?: string;
|
||||
purchasePlatform?: string;
|
||||
deadline?: string;
|
||||
remuneration?: number;
|
||||
completeDate?: string;
|
||||
requirements?: string;
|
||||
remark?: string;
|
||||
tasks: CollaborationTaskCommand[];
|
||||
expenditures: CollaborationExpenditureCommand[];
|
||||
settlements: CollaborationSettlementCommand[];
|
||||
files: CollaborationFileCommand[];
|
||||
}
|
||||
|
||||
export interface UpdateCollaborationRecordCommand
|
||||
extends AddCollaborationRecordCommand {
|
||||
recordId: number;
|
||||
}
|
||||
|
||||
export interface CollaborationRecordPageResponse {
|
||||
recordId: number;
|
||||
brand: string;
|
||||
goods: string;
|
||||
cooperationPlatform?: string;
|
||||
imageReturnNum: number;
|
||||
retainedMethod?: string;
|
||||
cooperatedMethod?: string;
|
||||
purchaseMethod?: string;
|
||||
purchasePrice?: number;
|
||||
purchaseDate?: string;
|
||||
purchasePlatform?: string;
|
||||
deadline?: string;
|
||||
remuneration?: number;
|
||||
completeDate?: string;
|
||||
requirements?: string;
|
||||
remark?: string;
|
||||
tasksNum: number;
|
||||
completedTasksNum: number;
|
||||
purchaseSettlementStatus: SettlementStatusDTO;
|
||||
deliverySettlementStatus: SettlementStatusDTO;
|
||||
remunerationSettlementStatus: SettlementStatusDTO;
|
||||
createTime: string;
|
||||
}
|
||||
|
||||
export interface CollaborationRecordDetailResponse
|
||||
extends CollaborationRecordPageResponse {
|
||||
tasks: Array<
|
||||
CollaborationTaskCommand & { taskId?: number; sortOrder?: number }
|
||||
>;
|
||||
expenditures: Array<
|
||||
CollaborationExpenditureCommand & { expenditureId?: number }
|
||||
>;
|
||||
settlements: Array<
|
||||
CollaborationSettlementCommand & { settlementId?: number }
|
||||
>;
|
||||
files: Array<
|
||||
CollaborationFileCommand & { fileId?: number; sortOrder?: number }
|
||||
>;
|
||||
}
|
||||
|
||||
export interface CollaborationOptionResponse {
|
||||
type: string;
|
||||
label: string;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
export interface CollaborationMonthlyStatisticsResponse {
|
||||
month: number;
|
||||
purchasePrice: number;
|
||||
expenditureAmount: number;
|
||||
settledRemuneration: number;
|
||||
settledTotal: number;
|
||||
}
|
||||
|
||||
export interface UploadResponse {
|
||||
url: string;
|
||||
fileName: string;
|
||||
newFileName: string;
|
||||
originalFilename: string;
|
||||
}
|
||||
|
||||
export const getCollaborationRecordListApi = (
|
||||
params: CollaborationRecordListCommand
|
||||
) => {
|
||||
return http.request<ResponseData<PageDTO<CollaborationRecordPageResponse>>>(
|
||||
"get",
|
||||
"/collaboration/record/list",
|
||||
{ params }
|
||||
);
|
||||
};
|
||||
|
||||
export const getCollaborationRecordInfoApi = (recordId: number) => {
|
||||
return http.request<ResponseData<CollaborationRecordDetailResponse>>(
|
||||
"get",
|
||||
`/collaboration/record/${recordId}`
|
||||
);
|
||||
};
|
||||
|
||||
export const addCollaborationRecordApi = (
|
||||
data: AddCollaborationRecordCommand
|
||||
) => {
|
||||
return http.request<ResponseData<void>>("post", "/collaboration/record", {
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
export const updateCollaborationRecordApi = (
|
||||
data: UpdateCollaborationRecordCommand
|
||||
) => {
|
||||
return http.request<ResponseData<void>>("put", "/collaboration/record", {
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteCollaborationRecordApi = (data: Array<number>) => {
|
||||
return http.request<ResponseData<void>>("delete", "/collaboration/record", {
|
||||
params: {
|
||||
ids: data.toString()
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getCollaborationOptionsApi = () => {
|
||||
return http.request<ResponseData<CollaborationOptionResponse[]>>(
|
||||
"get",
|
||||
"/collaboration/record/options"
|
||||
);
|
||||
};
|
||||
|
||||
export const getCollaborationMonthlyStatisticsApi = (year: number) => {
|
||||
return http.request<ResponseData<CollaborationMonthlyStatisticsResponse[]>>(
|
||||
"get",
|
||||
"/collaboration/record/monthly-statistics",
|
||||
{
|
||||
params: { year }
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const uploadCollaborationFileApi = (data: FormData) => {
|
||||
return http.request<ResponseData<UploadResponse>>(
|
||||
"post",
|
||||
"/file/upload",
|
||||
{ data },
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data"
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -89,6 +89,7 @@ function handleClose(
|
||||
:key="index"
|
||||
v-bind="options"
|
||||
v-model="options.visible"
|
||||
:align-center="options.alignCenter ?? true"
|
||||
:fullscreen="fullscreen ? true : options?.fullscreen ? true : false"
|
||||
@close="handleClose(options, index)"
|
||||
@opened="eventsCallBack('open', options, index)"
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
class="header-btn"
|
||||
/>
|
||||
<el-button
|
||||
:icon="Close"
|
||||
:icon="closeIcon"
|
||||
link
|
||||
@click="handleCloseClick"
|
||||
class="header-btn"
|
||||
@@ -81,7 +81,8 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { ElDialog, ElButton, ElScrollbar } from "element-plus";
|
||||
import { DialogEmits, DialogProps } from "./dialog";
|
||||
import { Close } from "@element-plus/icons-vue";
|
||||
import Close from "@iconify-icons/ep/close";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
import FullScreenMaximize from "@/assets/svg/FullScreenMaximize.svg?component";
|
||||
import FullScreenMinimize from "@/assets/svg/FullScreenMinimize.svg?component";
|
||||
|
||||
@@ -96,6 +97,7 @@ const props = withDefaults(defineProps<DialogProps>(), {
|
||||
loading: false
|
||||
});
|
||||
const emits = defineEmits<DialogEmits>();
|
||||
const closeIcon = useRenderIcon(Close);
|
||||
|
||||
const visible = computed<boolean>({
|
||||
get: () => {
|
||||
@@ -107,7 +109,6 @@ const visible = computed<boolean>({
|
||||
const fullScreenState = ref(!!props.initFullScreen);
|
||||
const fullScreen = computed<boolean>({
|
||||
get: () => {
|
||||
console.log("fullScreen getter", props.fullScreen, fullScreenState.value);
|
||||
// 非受控模式,状态完全由组件内部控制
|
||||
if (props.fullScreen === undefined) {
|
||||
return fullScreenState.value;
|
||||
@@ -117,7 +118,6 @@ const fullScreen = computed<boolean>({
|
||||
},
|
||||
set: v => {
|
||||
fullScreenState.value = v;
|
||||
console.log("fullScreen setter", v, props.fullScreen);
|
||||
// 受控模式,将状态更新到父组件
|
||||
if (props.fullScreen !== undefined) {
|
||||
emits("update:fullScreen", v);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import path from "path";
|
||||
import { getConfig } from "@/config";
|
||||
import { menuType } from "../../types";
|
||||
import extraIcon from "./extraIcon.vue";
|
||||
@@ -174,10 +175,7 @@ function resolvePath(routePath) {
|
||||
return routePath || props.basePath;
|
||||
} else {
|
||||
// 使用path.posix.resolve替代path.resolve 避免windows环境下使用electron出现盘符问题
|
||||
const segments = `${props.basePath}/${routePath}`
|
||||
.split("/")
|
||||
.filter(Boolean);
|
||||
return `/${segments.join("/")}`;
|
||||
return path.posix.resolve(props.basePath, routePath);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -69,11 +69,38 @@
|
||||
}
|
||||
}
|
||||
|
||||
.el-overlay-dialog:has(.pure-dialog.el-dialog:not(.is-fullscreen)) {
|
||||
box-sizing: border-box;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pure-dialog {
|
||||
&.el-dialog:not(.is-fullscreen) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: min(88vh, calc(100vh - 48px));
|
||||
margin: auto !important;
|
||||
}
|
||||
|
||||
.pure-dialog-svg {
|
||||
color: var(--el-color-info);
|
||||
}
|
||||
|
||||
.el-dialog__header,
|
||||
.el-dialog__footer {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.el-dialog__headerbtn {
|
||||
top: 20px;
|
||||
right: 14px;
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
<script setup lang="ts">
|
||||
import { h, ref } from "vue";
|
||||
import { PureTableBar } from "@/components/RePureTableBar";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
import { addDialog } from "@/components/ReDialog";
|
||||
import { useCollaborationRecordHook } from "./utils/hook";
|
||||
import { CollaborationRecordPageResponse } from "@/api/collaboration/record";
|
||||
import RecordFormModal from "./record-form-modal.vue";
|
||||
|
||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||
import Delete from "@iconify-icons/ep/delete";
|
||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||
import Refresh from "@iconify-icons/ep/refresh";
|
||||
import Search from "@iconify-icons/ep/search";
|
||||
|
||||
defineOptions({
|
||||
name: "CollaborationRecord"
|
||||
});
|
||||
|
||||
const tableRef = ref();
|
||||
const searchFormRef = ref();
|
||||
|
||||
const {
|
||||
searchFormParams,
|
||||
pageLoading,
|
||||
columns,
|
||||
dataList,
|
||||
pagination,
|
||||
defaultSort,
|
||||
deadlineRange,
|
||||
purchaseRange,
|
||||
optionMap,
|
||||
multipleSelection,
|
||||
onSearch,
|
||||
onSortChanged,
|
||||
getRecordList,
|
||||
resetForm,
|
||||
handleDelete,
|
||||
handleBulkDelete
|
||||
} = useCollaborationRecordHook();
|
||||
|
||||
const recordFormRef = ref();
|
||||
|
||||
function openDialog(
|
||||
type: "add" | "update",
|
||||
row?: CollaborationRecordPageResponse
|
||||
) {
|
||||
addDialog({
|
||||
title: type === "add" ? "新增合作记录" : "编辑合作记录",
|
||||
props: {
|
||||
type,
|
||||
row,
|
||||
optionMap
|
||||
},
|
||||
width: "1180px",
|
||||
top: "6vh",
|
||||
draggable: true,
|
||||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () => h(RecordFormModal as any, { ref: recordFormRef }),
|
||||
beforeSure: async done => {
|
||||
const isSuccess = await recordFormRef.value.handleConfirm();
|
||||
if (isSuccess) {
|
||||
done();
|
||||
onSearch(tableRef);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<el-form
|
||||
ref="searchFormRef"
|
||||
:inline="true"
|
||||
:model="searchFormParams"
|
||||
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]"
|
||||
>
|
||||
<el-form-item label="品牌" prop="brand">
|
||||
<el-input
|
||||
v-model="searchFormParams.brand"
|
||||
placeholder="请输入品牌"
|
||||
clearable
|
||||
class="!w-[180px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="物品" prop="goods">
|
||||
<el-input
|
||||
v-model="searchFormParams.goods"
|
||||
placeholder="请输入物品"
|
||||
clearable
|
||||
class="!w-[180px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="合作平台" prop="cooperationPlatform">
|
||||
<el-select
|
||||
v-model="searchFormParams.cooperationPlatform"
|
||||
placeholder="请选择合作平台"
|
||||
clearable
|
||||
class="!w-[160px]"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in optionMap.cooperationPlatform"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="预完成日期">
|
||||
<el-date-picker
|
||||
v-model="deadlineRange"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
class="!w-[240px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="购入日期">
|
||||
<el-date-picker
|
||||
v-model="purchaseRange"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
class="!w-[240px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="useRenderIcon(Search)"
|
||||
:loading="pageLoading"
|
||||
@click="onSearch(tableRef)"
|
||||
>
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
:icon="useRenderIcon(Refresh)"
|
||||
@click="resetForm(searchFormRef, tableRef)"
|
||||
>
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<PureTableBar
|
||||
title="合作记录"
|
||||
:columns="columns"
|
||||
@refresh="onSearch(tableRef)"
|
||||
>
|
||||
<template #buttons>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="useRenderIcon(AddFill)"
|
||||
@click="openDialog('add')"
|
||||
>
|
||||
新增合作
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="useRenderIcon(Delete)"
|
||||
@click="handleBulkDelete(tableRef)"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
</template>
|
||||
<template v-slot="{ size, dynamicColumns }">
|
||||
<pure-table
|
||||
border
|
||||
ref="tableRef"
|
||||
align-whole="center"
|
||||
showOverflowTooltip
|
||||
table-layout="auto"
|
||||
:loading="pageLoading"
|
||||
:size="size"
|
||||
adaptive
|
||||
:data="dataList"
|
||||
:columns="dynamicColumns"
|
||||
:default-sort="defaultSort"
|
||||
:pagination="pagination"
|
||||
:paginationSmall="size === 'small'"
|
||||
:header-cell-style="{
|
||||
background: 'var(--el-table-row-hover-bg-color)',
|
||||
color: 'var(--el-text-color-primary)'
|
||||
}"
|
||||
@page-size-change="getRecordList"
|
||||
@page-current-change="getRecordList"
|
||||
@sort-change="onSortChanged"
|
||||
@selection-change="
|
||||
rows => (multipleSelection = rows.map(item => item.recordId))
|
||||
"
|
||||
>
|
||||
<template #operation="{ row }">
|
||||
<el-button
|
||||
class="reset-margin"
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:icon="useRenderIcon(EditPen)"
|
||||
@click="openDialog('update', row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-popconfirm
|
||||
:title="`是否确认删除编号为${row.recordId}的合作记录`"
|
||||
@confirm="handleDelete(row)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button
|
||||
class="reset-margin"
|
||||
link
|
||||
type="danger"
|
||||
:size="size"
|
||||
:icon="useRenderIcon(Delete)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
</PureTableBar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,558 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { ElMessage, FormInstance, FormRules } from "element-plus";
|
||||
import type {
|
||||
UploadFile,
|
||||
UploadRequestOptions,
|
||||
UploadUserFile
|
||||
} from "element-plus";
|
||||
import Plus from "@iconify-icons/ep/plus";
|
||||
import {
|
||||
AddCollaborationRecordCommand,
|
||||
CollaborationFileCommand,
|
||||
CollaborationFileType,
|
||||
CollaborationRecordPageResponse,
|
||||
UpdateCollaborationRecordCommand,
|
||||
addCollaborationRecordApi,
|
||||
getCollaborationRecordInfoApi,
|
||||
updateCollaborationRecordApi,
|
||||
uploadCollaborationFileApi
|
||||
} from "@/api/collaboration/record";
|
||||
|
||||
interface Props {
|
||||
type: "add" | "update";
|
||||
row?: CollaborationRecordPageResponse;
|
||||
optionMap: Record<string, string[]>;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const defaultFormData = (): AddCollaborationRecordCommand &
|
||||
Partial<UpdateCollaborationRecordCommand> => ({
|
||||
recordId: 0,
|
||||
brand: "",
|
||||
goods: "",
|
||||
cooperationPlatform: "小红书",
|
||||
imageReturnNum: 1,
|
||||
retainedMethod: "寄拍",
|
||||
cooperatedMethod: "水下",
|
||||
purchaseMethod: "拍单",
|
||||
purchasePrice: undefined,
|
||||
purchaseDate: "",
|
||||
purchasePlatform: "",
|
||||
deadline: "",
|
||||
remuneration: undefined,
|
||||
completeDate: "",
|
||||
requirements: "",
|
||||
remark: "",
|
||||
tasks: [{ releaseDate: "" }],
|
||||
expenditures: [],
|
||||
settlements: [],
|
||||
files: []
|
||||
});
|
||||
|
||||
const formData = reactive(defaultFormData());
|
||||
const formRef = ref<FormInstance>();
|
||||
const previewImageUrl = ref("");
|
||||
const isImagePreviewVisible = ref(false);
|
||||
|
||||
const rules: FormRules = {
|
||||
brand: [{ required: true, message: "品牌不能为空" }],
|
||||
goods: [{ required: true, message: "物品不能为空" }],
|
||||
cooperationPlatform: [{ required: true, message: "合作平台不能为空" }],
|
||||
imageReturnNum: [{ required: true, message: "返图数量不能为空" }],
|
||||
deadline: [{ required: true, message: "预完成日期不能为空" }]
|
||||
};
|
||||
|
||||
const goodsImages = computed(() =>
|
||||
formData.files.filter(item => item.fileType === "GOODS_IMAGE")
|
||||
);
|
||||
const attachments = computed(() =>
|
||||
formData.files.filter(item => item.fileType === "ATTACHMENT")
|
||||
);
|
||||
const goodsImageUploadFiles = computed<UploadUserFile[]>(() =>
|
||||
goodsImages.value.map(file => ({
|
||||
name: getFileName(file),
|
||||
url: getFileUrl(file)
|
||||
}))
|
||||
);
|
||||
const attachmentUploadFiles = computed<UploadUserFile[]>(() =>
|
||||
attachments.value.map(file => ({
|
||||
name: getFileName(file),
|
||||
url: getFileUrl(file)
|
||||
}))
|
||||
);
|
||||
|
||||
async function handleOpened() {
|
||||
resetFormData();
|
||||
if (props.type === "update" && props.row?.recordId) {
|
||||
await loadDetail(props.row.recordId);
|
||||
}
|
||||
}
|
||||
|
||||
function resetFormData() {
|
||||
Object.assign(formData, defaultFormData());
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
|
||||
async function loadDetail(recordId: number) {
|
||||
const { data } = await getCollaborationRecordInfoApi(recordId);
|
||||
Object.assign(formData, {
|
||||
...defaultFormData(),
|
||||
...data,
|
||||
tasks: data.tasks.length ? data.tasks : [{ releaseDate: "" }],
|
||||
expenditures: data.expenditures,
|
||||
settlements: data.settlements,
|
||||
files: data.files
|
||||
});
|
||||
}
|
||||
|
||||
function addTask() {
|
||||
formData.tasks.push({ releaseDate: "" });
|
||||
}
|
||||
|
||||
function removeTask(index: number) {
|
||||
formData.tasks.splice(index, 1);
|
||||
}
|
||||
|
||||
function addExpenditure() {
|
||||
formData.expenditures.push({
|
||||
spendDate: "",
|
||||
amount: undefined,
|
||||
purpose: ""
|
||||
});
|
||||
}
|
||||
|
||||
function removeExpenditure(index: number) {
|
||||
formData.expenditures.splice(index, 1);
|
||||
}
|
||||
|
||||
function addSettlement() {
|
||||
formData.settlements.push({
|
||||
settleDate: "",
|
||||
method: "",
|
||||
income: undefined,
|
||||
purpose: ""
|
||||
});
|
||||
}
|
||||
|
||||
function removeSettlement(index: number) {
|
||||
formData.settlements.splice(index, 1);
|
||||
}
|
||||
|
||||
async function handleUpload(
|
||||
option: UploadRequestOptions,
|
||||
fileType: CollaborationFileType
|
||||
) {
|
||||
const data = new FormData();
|
||||
data.append("file", option.file);
|
||||
const response = await uploadCollaborationFileApi(data);
|
||||
formData.files.push(toFileCommand(response.data, fileType));
|
||||
option.onSuccess(response.data);
|
||||
}
|
||||
|
||||
function toFileCommand(file, fileType: CollaborationFileType) {
|
||||
return {
|
||||
fileType,
|
||||
url: file.url,
|
||||
fileName: file.fileName,
|
||||
newFileName: file.newFileName,
|
||||
originalFilename: file.originalFilename
|
||||
};
|
||||
}
|
||||
|
||||
function removeFile(file: CollaborationFileCommand) {
|
||||
const index = formData.files.indexOf(file);
|
||||
if (index >= 0) {
|
||||
formData.files.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function handlePreviewImage(file: UploadFile) {
|
||||
if (!file.url) return;
|
||||
previewImageUrl.value = file.url;
|
||||
isImagePreviewVisible.value = true;
|
||||
}
|
||||
|
||||
function handleRemoveGoodsImage(file: UploadFile) {
|
||||
const target = goodsImages.value.find(item => getFileUrl(item) === file.url);
|
||||
if (target) {
|
||||
removeFile(target);
|
||||
}
|
||||
}
|
||||
|
||||
function handlePreviewAttachment(file: UploadFile) {
|
||||
if (!file.url) {
|
||||
ElMessage.warning("文件地址不存在");
|
||||
return;
|
||||
}
|
||||
window.open(file.url, "_blank", "noopener,noreferrer");
|
||||
}
|
||||
|
||||
function handleRemoveAttachment(file: UploadFile) {
|
||||
const target = attachments.value.find(item => getFileUrl(item) === file.url);
|
||||
if (target) {
|
||||
removeFile(target);
|
||||
}
|
||||
}
|
||||
|
||||
function getFileName(file: CollaborationFileCommand) {
|
||||
return file.originalFilename || file.newFileName || "未命名文件";
|
||||
}
|
||||
|
||||
function getFileUrl(file: CollaborationFileCommand) {
|
||||
if (file.url) return file.url;
|
||||
if (!file.fileName) return "";
|
||||
return `${import.meta.env.VITE_APP_BASE_API}${file.fileName}`;
|
||||
}
|
||||
|
||||
async function handleConfirm() {
|
||||
const isValid = await formRef.value?.validate().catch(() => false);
|
||||
if (!isValid) return false;
|
||||
return submitForm();
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
try {
|
||||
if (props.type === "add") {
|
||||
await addCollaborationRecordApi(formData);
|
||||
} else {
|
||||
await updateCollaborationRecordApi(
|
||||
formData as UpdateCollaborationRecordCommand
|
||||
);
|
||||
}
|
||||
ElMessage.success("提交成功");
|
||||
return true;
|
||||
} catch (e) {
|
||||
ElMessage.error((e as Error)?.message || "提交失败");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(handleOpened);
|
||||
|
||||
defineExpose({ handleConfirm });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
class="record-form"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="112px"
|
||||
>
|
||||
<el-tabs>
|
||||
<el-tab-pane label="基本信息">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="brand" label="品牌" required>
|
||||
<el-input v-model="formData.brand" placeholder="请输入品牌" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="goods" label="物品" required>
|
||||
<el-input v-model="formData.goods" placeholder="请输入物品" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="cooperationPlatform" label="合作平台" required>
|
||||
<el-select v-model="formData.cooperationPlatform" clearable>
|
||||
<el-option
|
||||
v-for="item in optionMap.cooperationPlatform"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="imageReturnNum" label="返图数量" required>
|
||||
<el-input-number
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
v-model="formData.imageReturnNum"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="留存方式">
|
||||
<el-select v-model="formData.retainedMethod">
|
||||
<el-option
|
||||
v-for="item in optionMap.retainedMethod"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="合作方式">
|
||||
<el-select v-model="formData.cooperatedMethod">
|
||||
<el-option
|
||||
v-for="item in optionMap.cooperatedMethod"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="购入方式">
|
||||
<el-select v-model="formData.purchaseMethod">
|
||||
<el-option
|
||||
v-for="item in optionMap.purchaseMethod"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="购入金额">
|
||||
<el-input-number
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
v-model="formData.purchasePrice"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="购入平台">
|
||||
<el-select v-model="formData.purchasePlatform" clearable>
|
||||
<el-option
|
||||
v-for="item in optionMap.purchasePlatform"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="购入日期">
|
||||
<el-date-picker
|
||||
v-model="formData.purchaseDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="date"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="deadline" label="预完成日期" required>
|
||||
<el-date-picker
|
||||
v-model="formData.deadline"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="date"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="稿费">
|
||||
<el-input-number
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
v-model="formData.remuneration"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="物品图片">
|
||||
<el-upload
|
||||
multiple
|
||||
accept="image/*"
|
||||
class="goods-image-upload"
|
||||
list-type="picture-card"
|
||||
:file-list="goodsImageUploadFiles"
|
||||
:http-request="option => handleUpload(option, 'GOODS_IMAGE')"
|
||||
:on-preview="handlePreviewImage"
|
||||
:on-remove="handleRemoveGoodsImage"
|
||||
>
|
||||
<IconifyIconOffline class="upload-plus" :icon="Plus" />
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="附件">
|
||||
<el-upload
|
||||
multiple
|
||||
class="attachment-upload"
|
||||
:file-list="attachmentUploadFiles"
|
||||
:http-request="option => handleUpload(option, 'ATTACHMENT')"
|
||||
:on-preview="handlePreviewAttachment"
|
||||
:on-remove="handleRemoveAttachment"
|
||||
>
|
||||
<el-button>上传附件</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="拍摄要求">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
v-model="formData.requirements"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" :rows="3" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="笔记任务">
|
||||
<el-button type="primary" plain @click="addTask">添加笔记</el-button>
|
||||
<div
|
||||
v-for="(item, index) in formData.tasks"
|
||||
:key="index"
|
||||
class="line-item"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="item.releaseDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="date"
|
||||
placeholder="发布日期"
|
||||
/>
|
||||
<el-button type="danger" link @click="removeTask(index)"
|
||||
>删除</el-button
|
||||
>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="支出信息">
|
||||
<el-button type="primary" plain @click="addExpenditure"
|
||||
>添加支出</el-button
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in formData.expenditures"
|
||||
:key="index"
|
||||
class="line-item"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="item.spendDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="date"
|
||||
placeholder="支出日期"
|
||||
/>
|
||||
<el-input-number
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
v-model="item.amount"
|
||||
placeholder="金额"
|
||||
/>
|
||||
<el-select v-model="item.purpose" placeholder="用途" clearable>
|
||||
<el-option
|
||||
v-for="option in optionMap.expenditurePurpose"
|
||||
:key="option"
|
||||
:label="option"
|
||||
:value="option"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button type="danger" link @click="removeExpenditure(index)"
|
||||
>删除</el-button
|
||||
>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="结款信息">
|
||||
<el-button type="primary" plain @click="addSettlement"
|
||||
>添加结款</el-button
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in formData.settlements"
|
||||
:key="index"
|
||||
class="line-item"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="item.settleDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="date"
|
||||
placeholder="结款日期"
|
||||
/>
|
||||
<el-select v-model="item.method" placeholder="方式" clearable>
|
||||
<el-option
|
||||
v-for="option in optionMap.settlementMethod"
|
||||
:key="option"
|
||||
:label="option"
|
||||
:value="option"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input-number
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
v-model="item.income"
|
||||
placeholder="金额"
|
||||
/>
|
||||
<el-select v-model="item.purpose" placeholder="用途" clearable>
|
||||
<el-option
|
||||
v-for="option in optionMap.settlementPurpose"
|
||||
:key="option"
|
||||
:label="option"
|
||||
:value="option"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button type="danger" link @click="removeSettlement(index)"
|
||||
>删除</el-button
|
||||
>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<el-dialog v-model="isImagePreviewVisible" append-to-body>
|
||||
<img class="preview-image" :src="previewImageUrl" alt="" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.line-item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.record-form {
|
||||
:deep(.el-row .el-select),
|
||||
:deep(.el-row .el-date-editor.el-input),
|
||||
:deep(.el-row .el-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-input-number .el-input__inner) {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-image-upload {
|
||||
:deep(.el-upload--picture-card),
|
||||
:deep(.el-upload-list--picture-card .el-upload-list__item) {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
line-height: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-plus {
|
||||
font-size: 24px;
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
|
||||
.attachment-upload {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.preview-image {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,241 @@
|
||||
import dayjs from "dayjs";
|
||||
import { message } from "@/utils/message";
|
||||
import { ElMessageBox, Sort } from "element-plus";
|
||||
import { computed, onMounted, reactive, ref, toRaw } from "vue";
|
||||
import { CommonUtils } from "@/utils/common";
|
||||
import { PaginationProps } from "@pureadmin/table";
|
||||
import {
|
||||
CollaborationOptionResponse,
|
||||
CollaborationRecordListCommand,
|
||||
CollaborationRecordPageResponse,
|
||||
deleteCollaborationRecordApi,
|
||||
getCollaborationOptionsApi,
|
||||
getCollaborationRecordListApi
|
||||
} from "@/api/collaboration/record";
|
||||
|
||||
const statusTypeMap = {
|
||||
NONE: "info",
|
||||
SETTLED: "success",
|
||||
UNSETTLED: "danger",
|
||||
PARTIAL: "warning"
|
||||
};
|
||||
|
||||
export function useCollaborationRecordHook() {
|
||||
const defaultSort: Sort = {
|
||||
prop: "deadline",
|
||||
order: "descending"
|
||||
};
|
||||
|
||||
const pagination: PaginationProps = {
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
background: true
|
||||
};
|
||||
|
||||
const searchFormParams = reactive<CollaborationRecordListCommand>({
|
||||
brand: "",
|
||||
goods: "",
|
||||
cooperationPlatform: undefined
|
||||
});
|
||||
|
||||
const deadlineRange = computed<[string, string] | null>({
|
||||
get: () => getRange(searchFormParams.beginTime, searchFormParams.endTime),
|
||||
set: v => fillRange(v, "beginTime", "endTime")
|
||||
});
|
||||
|
||||
const purchaseRange = computed<[string, string] | null>({
|
||||
get: () =>
|
||||
getRange(
|
||||
searchFormParams.purchaseBeginTime,
|
||||
searchFormParams.purchaseEndTime
|
||||
),
|
||||
set: v => fillRange(v, "purchaseBeginTime", "purchaseEndTime")
|
||||
});
|
||||
|
||||
const dataList = ref<CollaborationRecordPageResponse[]>([]);
|
||||
const optionMap = ref<Record<string, string[]>>({});
|
||||
const pageLoading = ref(true);
|
||||
const multipleSelection = ref<number[]>([]);
|
||||
const sortState = ref<Sort>(defaultSort);
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{ type: "selection", align: "left" },
|
||||
{ label: "品牌", prop: "brand", minWidth: 120 },
|
||||
{ label: "物品", prop: "goods", minWidth: 120 },
|
||||
{ label: "合作平台", prop: "cooperationPlatform", minWidth: 110 },
|
||||
{ label: "留存方式", prop: "retainedMethod", minWidth: 100 },
|
||||
{ label: "购入方式", prop: "purchaseMethod", minWidth: 100 },
|
||||
{
|
||||
label: "预完成日期",
|
||||
prop: "deadline",
|
||||
minWidth: 130,
|
||||
sortable: "custom",
|
||||
formatter: ({ deadline }) => formatDate(deadline)
|
||||
},
|
||||
{
|
||||
label: "任务进度",
|
||||
minWidth: 130,
|
||||
cellRenderer: ({ row }) => `${row.completedTasksNum}/${row.tasksNum}`
|
||||
},
|
||||
{
|
||||
label: "拍单费用",
|
||||
minWidth: 110,
|
||||
cellRenderer: ({ row, props }) =>
|
||||
renderStatus(row.purchaseSettlementStatus, props.size)
|
||||
},
|
||||
{
|
||||
label: "快递费用",
|
||||
minWidth: 110,
|
||||
cellRenderer: ({ row, props }) =>
|
||||
renderStatus(row.deliverySettlementStatus, props.size)
|
||||
},
|
||||
{
|
||||
label: "稿费",
|
||||
minWidth: 110,
|
||||
cellRenderer: ({ row, props }) =>
|
||||
renderStatus(row.remunerationSettlementStatus, props.size)
|
||||
},
|
||||
{
|
||||
label: "创建时间",
|
||||
prop: "createTime",
|
||||
minWidth: 160,
|
||||
sortable: "custom",
|
||||
formatter: ({ createTime }) => formatDateTime(createTime)
|
||||
},
|
||||
{ label: "操作", fixed: "right", width: 140, slot: "operation" }
|
||||
];
|
||||
|
||||
function getRange(start?: string, end?: string) {
|
||||
if (!start || !end) return null;
|
||||
return [start, end] as [string, string];
|
||||
}
|
||||
|
||||
function fillRange(v, startKey: string, endKey: string) {
|
||||
searchFormParams[startKey] = v?.length === 2 ? v[0] : undefined;
|
||||
searchFormParams[endKey] = v?.length === 2 ? v[1] : undefined;
|
||||
}
|
||||
|
||||
function formatDate(value?: string) {
|
||||
return value ? dayjs(value).format("YYYY-MM-DD") : "";
|
||||
}
|
||||
|
||||
function formatDateTime(value?: string) {
|
||||
return value ? dayjs(value).format("YYYY-MM-DD HH:mm:ss") : "";
|
||||
}
|
||||
|
||||
function renderStatus(status, size) {
|
||||
if (!status) return "";
|
||||
return (
|
||||
<el-tag size={size} type={statusTypeMap[status.status]} effect="plain">
|
||||
{status.label}
|
||||
</el-tag>
|
||||
);
|
||||
}
|
||||
|
||||
function onSortChanged(sort: Sort) {
|
||||
sortState.value = sort;
|
||||
pagination.currentPage = 1;
|
||||
getRecordList();
|
||||
}
|
||||
|
||||
async function onSearch(tableRef) {
|
||||
tableRef.getTableRef().sort("deadline", "descending");
|
||||
}
|
||||
|
||||
function resetForm(formEl, tableRef) {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
fillRange(null, "beginTime", "endTime");
|
||||
fillRange(null, "purchaseBeginTime", "purchaseEndTime");
|
||||
onSearch(tableRef);
|
||||
}
|
||||
|
||||
async function getRecordList() {
|
||||
pageLoading.value = true;
|
||||
CommonUtils.fillSortParams(searchFormParams, sortState.value);
|
||||
CommonUtils.fillPaginationParams(searchFormParams, pagination);
|
||||
const { data } = await getCollaborationRecordListApi(
|
||||
toRaw(searchFormParams)
|
||||
).finally(() => {
|
||||
pageLoading.value = false;
|
||||
});
|
||||
dataList.value = data.rows;
|
||||
pagination.total = data.total;
|
||||
}
|
||||
|
||||
async function getOptions() {
|
||||
const { data } = await getCollaborationOptionsApi();
|
||||
optionMap.value = data.reduce(
|
||||
(result, item: CollaborationOptionResponse) => {
|
||||
result[item.type] = item.values;
|
||||
return result;
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
async function handleDelete(row: CollaborationRecordPageResponse) {
|
||||
await deleteCollaborationRecordApi([row.recordId]);
|
||||
message(`您删除了编号为${row.recordId}的合作记录`, { type: "success" });
|
||||
getRecordList();
|
||||
}
|
||||
|
||||
async function handleBulkDelete(tableRef) {
|
||||
if (multipleSelection.value.length === 0) {
|
||||
message("请选择需要删除的数据", { type: "warning" });
|
||||
return;
|
||||
}
|
||||
confirmBulkDelete(tableRef);
|
||||
}
|
||||
|
||||
function confirmBulkDelete(tableRef) {
|
||||
ElMessageBox.confirm(
|
||||
`确认删除编号为[ ${multipleSelection.value} ]的合作记录吗?`,
|
||||
"系统提示",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
draggable: true
|
||||
}
|
||||
)
|
||||
.then(deleteSelectedRecords)
|
||||
.catch(() => {
|
||||
message("取消删除", { type: "info" });
|
||||
tableRef.getTableRef().clearSelection();
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteSelectedRecords() {
|
||||
await deleteCollaborationRecordApi(multipleSelection.value);
|
||||
message(`您删除了编号为[ ${multipleSelection.value} ]的合作记录`, {
|
||||
type: "success"
|
||||
});
|
||||
getRecordList();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getOptions();
|
||||
getRecordList();
|
||||
});
|
||||
|
||||
return {
|
||||
searchFormParams,
|
||||
pageLoading,
|
||||
columns,
|
||||
dataList,
|
||||
pagination,
|
||||
defaultSort,
|
||||
deadlineRange,
|
||||
purchaseRange,
|
||||
optionMap,
|
||||
multipleSelection,
|
||||
onSearch,
|
||||
onSortChanged,
|
||||
getRecordList,
|
||||
resetForm,
|
||||
handleDelete,
|
||||
handleBulkDelete
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import { useCollaborationStatisticsHook } from "./utils/hook";
|
||||
|
||||
defineOptions({
|
||||
name: "CollaborationStatistics"
|
||||
});
|
||||
|
||||
const { chartRef, selectedYear, yearOptions, getStatistics } =
|
||||
useCollaborationStatisticsHook();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>月度统计</span>
|
||||
<el-select
|
||||
v-model="selectedYear"
|
||||
class="!w-[140px]"
|
||||
@change="getStatistics"
|
||||
>
|
||||
<el-option
|
||||
v-for="year in yearOptions"
|
||||
:key="year"
|
||||
:label="`${year}年`"
|
||||
:value="year"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<div ref="chartRef" class="chart" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,84 @@
|
||||
import { onMounted, ref } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { getCollaborationMonthlyStatisticsApi } from "@/api/collaboration/record";
|
||||
|
||||
export function useCollaborationStatisticsHook() {
|
||||
const currentYear = new Date().getFullYear();
|
||||
const selectedYear = ref(currentYear);
|
||||
const yearOptions = Array.from(
|
||||
{ length: currentYear - 2012 },
|
||||
(_, index) => currentYear - index
|
||||
);
|
||||
const chartRef = ref<HTMLElement>();
|
||||
let chart: echarts.ECharts | undefined;
|
||||
|
||||
async function getStatistics() {
|
||||
const { data } = await getCollaborationMonthlyStatisticsApi(
|
||||
selectedYear.value
|
||||
);
|
||||
renderChart(data);
|
||||
}
|
||||
|
||||
function renderChart(data) {
|
||||
chart?.dispose();
|
||||
chart = echarts.init(chartRef.value);
|
||||
chart.setOption({
|
||||
tooltip: { trigger: "axis", axisPointer: { type: "shadow" } },
|
||||
legend: {
|
||||
data: ["拍单费用", "支出费用", "已结稿费", "已结总费用"],
|
||||
top: "2%",
|
||||
right: "0"
|
||||
},
|
||||
grid: { left: "0%", right: "0%", bottom: "0%", containLabel: true },
|
||||
xAxis: { type: "category", data: data.map(item => `${item.month}月`) },
|
||||
yAxis: { type: "value" },
|
||||
series: [
|
||||
buildSeries(
|
||||
"拍单费用",
|
||||
data.map(item => item.purchasePrice),
|
||||
"#ffbe00"
|
||||
),
|
||||
buildSeries(
|
||||
"支出费用",
|
||||
data.map(item => item.expenditureAmount),
|
||||
"#f56c6c"
|
||||
),
|
||||
buildSeries(
|
||||
"已结稿费",
|
||||
data.map(item => item.settledRemuneration),
|
||||
"#409eff"
|
||||
),
|
||||
buildSeries(
|
||||
"已结总费用",
|
||||
data.map(item => item.settledTotal),
|
||||
"#67c23a"
|
||||
)
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
function buildSeries(name: string, data: number[], color: string) {
|
||||
return {
|
||||
name,
|
||||
data,
|
||||
type: "bar",
|
||||
color
|
||||
};
|
||||
}
|
||||
|
||||
function resizeChart() {
|
||||
chart?.resize({ width: "auto" });
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getStatistics();
|
||||
window.addEventListener("resize", resizeChart);
|
||||
});
|
||||
|
||||
return {
|
||||
chartRef,
|
||||
selectedYear,
|
||||
yearOptions,
|
||||
getStatistics
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { h, ref } from "vue";
|
||||
import { usePostHook } from "./utils/hook";
|
||||
import { PureTableBar } from "@/components/RePureTableBar";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
import { addDialog } from "@/components/ReDialog";
|
||||
|
||||
import Delete from "@iconify-icons/ep/delete";
|
||||
import Search from "@iconify-icons/ep/search";
|
||||
@@ -12,8 +13,15 @@ import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { CommonUtils } from "@/utils/common";
|
||||
import PostFormModal from "@/views/system/post/post-form-modal.vue";
|
||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||
import { PostPageResponse } from "@/api/system/post";
|
||||
import {
|
||||
AddPostCommand,
|
||||
PostPageResponse,
|
||||
UpdatePostCommand,
|
||||
addPostApi,
|
||||
updatePostApi
|
||||
} from "@/api/system/post";
|
||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
/** 组件name最好和菜单表中的router_name一致 */
|
||||
defineOptions({
|
||||
@@ -43,13 +51,55 @@ const {
|
||||
handleBulkDelete
|
||||
} = usePostHook();
|
||||
|
||||
const opType = ref<"add" | "update">("add");
|
||||
const modalVisible = ref(false);
|
||||
const opRow = ref<PostPageResponse>();
|
||||
const postFormRef = ref();
|
||||
|
||||
function getPostFormData(row?: PostPageResponse) {
|
||||
return {
|
||||
postId: row?.postId ?? 0,
|
||||
postCode: row?.postCode ?? "",
|
||||
postName: row?.postName ?? "",
|
||||
postSort: row?.postSort ?? 1,
|
||||
remark: row?.remark ?? "",
|
||||
status: row?.status?.toString() ?? ""
|
||||
};
|
||||
}
|
||||
|
||||
async function submitPostForm(
|
||||
type: "add" | "update",
|
||||
formData: AddPostCommand & Partial<UpdatePostCommand>,
|
||||
done: () => void
|
||||
) {
|
||||
if (type === "add") {
|
||||
await addPostApi(formData);
|
||||
} else {
|
||||
await updatePostApi(formData as UpdatePostCommand);
|
||||
}
|
||||
ElMessage.success("提交成功");
|
||||
done();
|
||||
onSearch(tableRef);
|
||||
}
|
||||
|
||||
function openDialog(type: "add" | "update", row?: PostPageResponse) {
|
||||
opType.value = type;
|
||||
opRow.value = row;
|
||||
modalVisible.value = true;
|
||||
const formInline = getPostFormData(row);
|
||||
addDialog({
|
||||
title: type === "add" ? "新增岗位" : "更新岗位",
|
||||
props: { formInline },
|
||||
width: "40%",
|
||||
draggable: true,
|
||||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () => h(PostFormModal, { ref: postFormRef }),
|
||||
beforeSure: (done, { options }) => {
|
||||
const formRuleRef = postFormRef.value.getFormRuleRef();
|
||||
const formData = options.props.formInline as AddPostCommand &
|
||||
Partial<UpdatePostCommand>;
|
||||
formRuleRef.validate(valid => {
|
||||
if (valid) {
|
||||
submitPostForm(type, formData, () => done());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -205,13 +255,6 @@ function openDialog(type: "add" | "update", row?: PostPageResponse) {
|
||||
</pure-table>
|
||||
</template>
|
||||
</PureTableBar>
|
||||
|
||||
<post-form-modal
|
||||
v-model="modalVisible"
|
||||
:type="opType"
|
||||
:row="opRow"
|
||||
@success="onSearch"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,43 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import VDialog from "@/components/VDialog/VDialog.vue";
|
||||
import { computed, reactive, ref } from "vue";
|
||||
import {
|
||||
AddPostCommand,
|
||||
PostPageResponse,
|
||||
UpdatePostCommand,
|
||||
addPostApi,
|
||||
updatePostApi
|
||||
} from "@/api/system/post";
|
||||
import { ref } from "vue";
|
||||
import { AddPostCommand, UpdatePostCommand } from "@/api/system/post";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { ElMessage, FormInstance, FormRules } from "element-plus";
|
||||
import { FormInstance, FormRules } from "element-plus";
|
||||
|
||||
interface Props {
|
||||
type: "add" | "update";
|
||||
modelValue: boolean;
|
||||
row?: PostPageResponse;
|
||||
formInline: AddPostCommand & Partial<UpdatePostCommand>;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const emits = defineEmits<{
|
||||
(e: "update:modelValue", v: boolean): void;
|
||||
(e: "success"): void;
|
||||
}>();
|
||||
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set(v) {
|
||||
emits("update:modelValue", v);
|
||||
}
|
||||
});
|
||||
|
||||
const formData = reactive<AddPostCommand | UpdatePostCommand>({
|
||||
postId: 0,
|
||||
postCode: "",
|
||||
postName: "",
|
||||
postSort: 1,
|
||||
remark: "",
|
||||
status: ""
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
formInline: () => ({
|
||||
postId: 0,
|
||||
postCode: "",
|
||||
postName: "",
|
||||
postSort: 1,
|
||||
remark: "",
|
||||
status: ""
|
||||
})
|
||||
});
|
||||
const formData = ref(props.formInline);
|
||||
|
||||
const statusList = useUserStoreHook().dictionaryMap["common.status"];
|
||||
|
||||
@@ -62,70 +43,37 @@ const rules: FormRules = {
|
||||
]
|
||||
};
|
||||
const formRef = ref<FormInstance>();
|
||||
function handleOpened() {
|
||||
if (props.row) {
|
||||
Object.assign(formData, props.row);
|
||||
} else {
|
||||
formRef.value?.resetFields();
|
||||
}
|
||||
|
||||
function getFormRuleRef() {
|
||||
return formRef.value;
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
async function handleConfirm() {
|
||||
try {
|
||||
loading.value = true;
|
||||
if (props.type === "add") {
|
||||
await addPostApi(formData);
|
||||
} else if (props.type === "update") {
|
||||
await updatePostApi(formData as UpdatePostCommand);
|
||||
}
|
||||
ElMessage.info("提交成功");
|
||||
visible.value = false;
|
||||
emits("success");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error((e as Error)?.message || "提交失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
defineExpose({ getFormRuleRef });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog
|
||||
show-full-screen
|
||||
:fixed-body-height="false"
|
||||
use-body-scrolling
|
||||
:title="type === 'add' ? '新增岗位' : '更新岗位'"
|
||||
v-model="visible"
|
||||
:loading="loading"
|
||||
@confirm="handleConfirm"
|
||||
@cancel="visible = false"
|
||||
@opened="handleOpened"
|
||||
>
|
||||
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
|
||||
<el-form-item prop="postName" label="岗位名称" required inline-message>
|
||||
<el-input v-model="formData.postName" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="postCode" label="岗位编码" required>
|
||||
<el-input v-model="formData.postCode" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="postSort" label="岗位顺序" required>
|
||||
<el-input-number :min="1" v-model="formData.postSort" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" label="岗位状态">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="item in Object.keys(statusList)"
|
||||
:key="item"
|
||||
:label="statusList[item].value"
|
||||
>{{ statusList[item].label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
|
||||
<el-input type="textarea" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</v-dialog>
|
||||
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
|
||||
<el-form-item prop="postName" label="岗位名称" required inline-message>
|
||||
<el-input v-model="formData.postName" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="postCode" label="岗位编码" required>
|
||||
<el-input v-model="formData.postCode" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="postSort" label="岗位顺序" required>
|
||||
<el-input-number :min="1" v-model="formData.postSort" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" label="岗位状态">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="item in Object.keys(statusList)"
|
||||
:key="item"
|
||||
:label="statusList[item].value"
|
||||
>{{ statusList[item].label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
|
||||
<el-input type="textarea" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { h, ref } from "vue";
|
||||
import { useRole } from "./utils/hook";
|
||||
import { PureTableBar } from "@/components/RePureTableBar";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
import { addDialog } from "@/components/ReDialog";
|
||||
|
||||
import Delete from "@iconify-icons/ep/delete";
|
||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||
import Search from "@iconify-icons/ep/search";
|
||||
import Refresh from "@iconify-icons/ep/refresh";
|
||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||
import { getRoleInfoApi, RoleDTO } from "@/api/system/role";
|
||||
import {
|
||||
AddRoleCommand,
|
||||
RoleDTO,
|
||||
UpdateRoleCommand,
|
||||
addRoleApi,
|
||||
getRoleInfoApi,
|
||||
updateRoleApi
|
||||
} from "@/api/system/role";
|
||||
import RoleFormModal from "@/views/system/role/role-form-modal.vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
@@ -31,11 +39,37 @@ const {
|
||||
handleDelete
|
||||
} = useRole();
|
||||
|
||||
const opType = ref<"add" | "update">("add");
|
||||
const modalVisible = ref(false);
|
||||
const opRow = ref<RoleDTO>();
|
||||
const roleFormRef = ref();
|
||||
|
||||
function getRoleFormData(row?: RoleDTO) {
|
||||
return {
|
||||
roleId: row?.roleId ?? 0,
|
||||
dataScope: row?.dataScope?.toString() ?? "",
|
||||
menuIds: row?.selectedMenuList ?? [],
|
||||
remark: row?.remark ?? "",
|
||||
roleKey: row?.roleKey ?? "",
|
||||
roleName: row?.roleName ?? "",
|
||||
roleSort: row?.roleSort ?? 1,
|
||||
status: row?.status?.toString() ?? ""
|
||||
};
|
||||
}
|
||||
|
||||
async function submitRoleForm(
|
||||
type: "add" | "update",
|
||||
formData: AddRoleCommand & Partial<UpdateRoleCommand>,
|
||||
done: () => void
|
||||
) {
|
||||
if (type === "add") {
|
||||
await addRoleApi(formData);
|
||||
} else {
|
||||
await updateRoleApi(formData as UpdateRoleCommand);
|
||||
}
|
||||
ElMessage.success("提交成功");
|
||||
done();
|
||||
onSearch();
|
||||
}
|
||||
|
||||
async function openDialog(type: "add" | "update", row?: RoleDTO) {
|
||||
debugger;
|
||||
try {
|
||||
await getMenuTree();
|
||||
if (row) {
|
||||
@@ -46,10 +80,43 @@ async function openDialog(type: "add" | "update", row?: RoleDTO) {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error((e as Error)?.message || "加载菜单失败");
|
||||
return;
|
||||
}
|
||||
opType.value = type;
|
||||
opRow.value = row;
|
||||
modalVisible.value = true;
|
||||
const formInline = getRoleFormData(row);
|
||||
addDialog({
|
||||
title: type === "add" ? "新增角色" : "更新角色",
|
||||
props: {
|
||||
formInline,
|
||||
menuOptions: menuTree.value
|
||||
},
|
||||
width: "40%",
|
||||
draggable: true,
|
||||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () => h(RoleFormModal, { ref: roleFormRef }),
|
||||
beforeSure: (done, { options }) => {
|
||||
const formRuleRef = roleFormRef.value.getFormRuleRef();
|
||||
const formData = options.props.formInline as AddRoleCommand &
|
||||
Partial<UpdateRoleCommand>;
|
||||
formRuleRef.validate(valid => {
|
||||
if (valid) {
|
||||
submitRoleForm(type, formData, () => done());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleSelectionChange(rows: RoleDTO[]) {
|
||||
void rows;
|
||||
}
|
||||
|
||||
function handleSizeChange() {
|
||||
onSearch();
|
||||
}
|
||||
|
||||
function handleCurrentChange() {
|
||||
onSearch();
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
@@ -205,13 +272,6 @@ async function openDialog(type: "add" | "update", row?: RoleDTO) {
|
||||
</pure-table>
|
||||
</template>
|
||||
</PureTableBar>
|
||||
|
||||
<role-form-modal
|
||||
v-model="modalVisible"
|
||||
:type="opType"
|
||||
:row="opRow"
|
||||
:menu-options="menuTree"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,47 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import VDialog from "@/components/VDialog/VDialog.vue";
|
||||
import { computed, reactive, ref } from "vue";
|
||||
import { ref } from "vue";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { ElMessage, FormInstance, FormRules } from "element-plus";
|
||||
import {
|
||||
AddRoleCommand,
|
||||
RoleDTO,
|
||||
UpdateRoleCommand,
|
||||
addRoleApi,
|
||||
updateRoleApi
|
||||
} from "@/api/system/role";
|
||||
import { ElTree, FormInstance, FormRules } from "element-plus";
|
||||
import { AddRoleCommand, UpdateRoleCommand } from "@/api/system/role";
|
||||
import { MenuDTO } from "@/api/system/menu";
|
||||
|
||||
interface Props {
|
||||
type: "add" | "update";
|
||||
modelValue: boolean;
|
||||
row?: RoleDTO;
|
||||
formInline: AddRoleCommand & Partial<UpdateRoleCommand>;
|
||||
menuOptions: MenuDTO[];
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const emits = defineEmits<{
|
||||
(e: "update:modelValue", v: boolean): void;
|
||||
(e: "success"): void;
|
||||
}>();
|
||||
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set(v) {
|
||||
emits("update:modelValue", v);
|
||||
}
|
||||
});
|
||||
|
||||
const formData = reactive<AddRoleCommand | UpdateRoleCommand>({
|
||||
roleId: 0,
|
||||
dataScope: "",
|
||||
menuIds: [],
|
||||
remark: "",
|
||||
roleKey: "",
|
||||
roleName: "",
|
||||
roleSort: 1,
|
||||
status: ""
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
formInline: () => ({
|
||||
roleId: 0,
|
||||
dataScope: "",
|
||||
menuIds: [],
|
||||
remark: "",
|
||||
roleKey: "",
|
||||
roleName: "",
|
||||
roleSort: 1,
|
||||
status: ""
|
||||
}),
|
||||
menuOptions: () => []
|
||||
});
|
||||
const formData = ref(props.formInline);
|
||||
|
||||
const statusList = useUserStoreHook().dictionaryMap["common.status"];
|
||||
|
||||
@@ -66,93 +48,58 @@ const rules: FormRules = {
|
||||
]
|
||||
};
|
||||
const formRef = ref<FormInstance>();
|
||||
function handleOpened() {
|
||||
console.log("opened", props.row);
|
||||
if (props.row) {
|
||||
Object.assign(formData, props.row);
|
||||
formData.menuIds = props.row.selectedMenuList;
|
||||
} else {
|
||||
formRef.value?.resetFields();
|
||||
}
|
||||
}
|
||||
|
||||
const treeRef = ref<InstanceType<typeof ElTree>>();
|
||||
function handleCheckChange() {
|
||||
formData.menuIds = treeRef.value.getCheckedKeys(false) as number[];
|
||||
formData.value.menuIds = treeRef.value.getCheckedKeys(false) as number[];
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
async function handleConfirm() {
|
||||
try {
|
||||
loading.value = true;
|
||||
if (props.type === "add") {
|
||||
await addRoleApi(formData);
|
||||
} else if (props.type === "update") {
|
||||
await updateRoleApi(formData as UpdateRoleCommand);
|
||||
}
|
||||
ElMessage.info("提交成功");
|
||||
visible.value = false;
|
||||
emits("success");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error((e as Error)?.message || "提交失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
function getFormRuleRef() {
|
||||
return formRef.value;
|
||||
}
|
||||
|
||||
defineExpose({ getFormRuleRef });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog
|
||||
show-full-screen
|
||||
fixed-body-height
|
||||
use-body-scrolling
|
||||
:title="type === 'add' ? '新增角色' : '更新角色'"
|
||||
v-model="visible"
|
||||
:loading="loading"
|
||||
@confirm="handleConfirm"
|
||||
@cancel="visible = false"
|
||||
@opened="handleOpened"
|
||||
>
|
||||
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
|
||||
<el-form-item prop="roleName" label="角色名称" required inline-message>
|
||||
<el-input v-model="formData.roleName" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="roleKey" label="权限字符" required>
|
||||
<el-input v-model="formData.roleKey" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="roleSort" label="角色顺序" required>
|
||||
<el-input-number :min="1" v-model="formData.roleSort" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" label="角色状态">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="item in Object.keys(statusList)"
|
||||
:key="item"
|
||||
:label="statusList[item].value"
|
||||
>{{ statusList[item].label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单权限" prop="menuIds">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:props="{ label: 'menuName', children: 'children' }"
|
||||
:data="props.menuOptions"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
show-checkbox
|
||||
default-expand-all
|
||||
check-on-click-node
|
||||
:expand-on-click-node="false"
|
||||
:default-checked-keys="formData.menuIds"
|
||||
@check-change="handleCheckChange"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
|
||||
<el-input type="textarea" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</v-dialog>
|
||||
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
|
||||
<el-form-item prop="roleName" label="角色名称" required inline-message>
|
||||
<el-input v-model="formData.roleName" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="roleKey" label="权限字符" required>
|
||||
<el-input v-model="formData.roleKey" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="roleSort" label="角色顺序" required>
|
||||
<el-input-number :min="1" v-model="formData.roleSort" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" label="角色状态">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="item in Object.keys(statusList)"
|
||||
:key="item"
|
||||
:label="statusList[item].value"
|
||||
>{{ statusList[item].label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单权限" prop="menuIds">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:props="{ label: 'menuName', children: 'children' }"
|
||||
:data="props.menuOptions"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
show-checkbox
|
||||
default-expand-all
|
||||
check-on-click-node
|
||||
:expand-on-click-node="false"
|
||||
:default-checked-keys="formData.menuIds"
|
||||
@check-change="handleCheckChange"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
|
||||
<el-input type="textarea" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user