feat: 合作伙伴更新、反馈页面、新闻初始化语句、接口权限
28
.claude/settings.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"PostToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Edit|Write|Bash",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "code-review-graph update --skip-flows",
|
||||||
|
"timeout": 30
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SessionStart": [
|
||||||
|
{
|
||||||
|
"matcher": "",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "code-review-graph status",
|
||||||
|
"timeout": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -28,7 +28,16 @@
|
|||||||
"Bash(\"/d/Program Files/apache-maven/apache-maven-3.6.3/bin/mvn\" clean package -pl txw-mhzc-service-biz -am -DskipTests)",
|
"Bash(\"/d/Program Files/apache-maven/apache-maven-3.6.3/bin/mvn\" clean package -pl txw-mhzc-service-biz -am -DskipTests)",
|
||||||
"Bash(\"/d/Program Files/jdk8/bin/java\" -Xms256m -Xmx512m -Duser.timezone=Asia/Shanghai -jar target/txw-mhzc-service-biz.jar --spring.profiles.active=local)",
|
"Bash(\"/d/Program Files/jdk8/bin/java\" -Xms256m -Xmx512m -Duser.timezone=Asia/Shanghai -jar target/txw-mhzc-service-biz.jar --spring.profiles.active=local)",
|
||||||
"Bash(mvn compile *)",
|
"Bash(mvn compile *)",
|
||||||
"WebFetch(domain:www.figma.com)"
|
"WebFetch(domain:www.figma.com)",
|
||||||
|
"mcp__code-review-graph__get_architecture_overview_tool",
|
||||||
|
"mcp__code-review-graph__list_graph_stats_tool",
|
||||||
|
"mcp__code-review-graph__list_communities_tool",
|
||||||
|
"mcp__code-review-graph__build_or_update_graph_tool",
|
||||||
|
"mcp__code-review-graph__semantic_search_nodes_tool"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"enableAllProjectMcpServers": true,
|
||||||
|
"enabledMcpjsonServers": [
|
||||||
|
"code-review-graph"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
27
.claude/skills/debug-issue.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: Debug Issue
|
||||||
|
description: Systematically debug issues using graph-powered code navigation
|
||||||
|
---
|
||||||
|
|
||||||
|
## Debug Issue
|
||||||
|
|
||||||
|
Use the knowledge graph to systematically trace and debug issues.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
|
||||||
|
1. Use `semantic_search_nodes` to find code related to the issue.
|
||||||
|
2. Use `query_graph` with `callers_of` and `callees_of` to trace call chains.
|
||||||
|
3. Use `get_flow` to see full execution paths through suspected areas.
|
||||||
|
4. Run `detect_changes` to check if recent changes caused the issue.
|
||||||
|
5. Use `get_impact_radius` on suspected files to see what else is affected.
|
||||||
|
|
||||||
|
### Tips
|
||||||
|
|
||||||
|
- Check both callers and callees to understand the full context.
|
||||||
|
- Look at affected flows to find the entry point that triggers the bug.
|
||||||
|
- Recent changes are the most common source of new issues.
|
||||||
|
|
||||||
|
## Token Efficiency Rules
|
||||||
|
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
|
||||||
|
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
|
||||||
|
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
|
||||||
28
.claude/skills/explore-codebase.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
name: Explore Codebase
|
||||||
|
description: Navigate and understand codebase structure using the knowledge graph
|
||||||
|
---
|
||||||
|
|
||||||
|
## Explore Codebase
|
||||||
|
|
||||||
|
Use the code-review-graph MCP tools to explore and understand the codebase.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
|
||||||
|
1. Run `list_graph_stats` to see overall codebase metrics.
|
||||||
|
2. Run `get_architecture_overview` for high-level community structure.
|
||||||
|
3. Use `list_communities` to find major modules, then `get_community` for details.
|
||||||
|
4. Use `semantic_search_nodes` to find specific functions or classes.
|
||||||
|
5. Use `query_graph` with patterns like `callers_of`, `callees_of`, `imports_of` to trace relationships.
|
||||||
|
6. Use `list_flows` and `get_flow` to understand execution paths.
|
||||||
|
|
||||||
|
### Tips
|
||||||
|
|
||||||
|
- Start broad (stats, architecture) then narrow down to specific areas.
|
||||||
|
- Use `children_of` on a file to see all its functions and classes.
|
||||||
|
- Use `find_large_functions` to identify complex code.
|
||||||
|
|
||||||
|
## Token Efficiency Rules
|
||||||
|
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
|
||||||
|
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
|
||||||
|
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
|
||||||
28
.claude/skills/refactor-safely.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
name: Refactor Safely
|
||||||
|
description: Plan and execute safe refactoring using dependency analysis
|
||||||
|
---
|
||||||
|
|
||||||
|
## Refactor Safely
|
||||||
|
|
||||||
|
Use the knowledge graph to plan and execute refactoring with confidence.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
|
||||||
|
1. Use `refactor_tool` with mode="suggest" for community-driven refactoring suggestions.
|
||||||
|
2. Use `refactor_tool` with mode="dead_code" to find unreferenced code.
|
||||||
|
3. For renames, use `refactor_tool` with mode="rename" to preview all affected locations.
|
||||||
|
4. Use `apply_refactor_tool` with the refactor_id to apply renames.
|
||||||
|
5. After changes, run `detect_changes` to verify the refactoring impact.
|
||||||
|
|
||||||
|
### Safety Checks
|
||||||
|
|
||||||
|
- Always preview before applying (rename mode gives you an edit list).
|
||||||
|
- Check `get_impact_radius` before major refactors.
|
||||||
|
- Use `get_affected_flows` to ensure no critical paths are broken.
|
||||||
|
- Run `find_large_functions` to identify decomposition targets.
|
||||||
|
|
||||||
|
## Token Efficiency Rules
|
||||||
|
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
|
||||||
|
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
|
||||||
|
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
|
||||||
29
.claude/skills/review-changes.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Review Changes
|
||||||
|
description: Perform a structured code review using change detection and impact
|
||||||
|
---
|
||||||
|
|
||||||
|
## Review Changes
|
||||||
|
|
||||||
|
Perform a thorough, risk-aware code review using the knowledge graph.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
|
||||||
|
1. Run `detect_changes` to get risk-scored change analysis.
|
||||||
|
2. Run `get_affected_flows` to find impacted execution paths.
|
||||||
|
3. For each high-risk function, run `query_graph` with pattern="tests_for" to check test coverage.
|
||||||
|
4. Run `get_impact_radius` to understand the blast radius.
|
||||||
|
5. For any untested changes, suggest specific test cases.
|
||||||
|
|
||||||
|
### Output Format
|
||||||
|
|
||||||
|
Provide findings grouped by risk level (high/medium/low) with:
|
||||||
|
- What changed and why it matters
|
||||||
|
- Test coverage status
|
||||||
|
- Suggested improvements
|
||||||
|
- Overall merge recommendation
|
||||||
|
|
||||||
|
## Token Efficiency Rules
|
||||||
|
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
|
||||||
|
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
|
||||||
|
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
|
||||||
2
.gitignore
vendored
@ -59,3 +59,5 @@ ewm.png
|
|||||||
|
|
||||||
# 本地开发配置(包含敏感信息)
|
# 本地开发配置(包含敏感信息)
|
||||||
**/bootstrap-local.yml
|
**/bootstrap-local.yml
|
||||||
|
# Added by code-review-graph
|
||||||
|
.code-review-graph/
|
||||||
|
|||||||
12
.mcp.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"code-review-graph": {
|
||||||
|
"command": "uvx",
|
||||||
|
"args": [
|
||||||
|
"code-review-graph",
|
||||||
|
"serve"
|
||||||
|
],
|
||||||
|
"type": "stdio"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
CLAUDE.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<!-- code-review-graph MCP tools -->
|
||||||
|
## MCP Tools: code-review-graph
|
||||||
|
|
||||||
|
**IMPORTANT: This project has a knowledge graph. ALWAYS use the
|
||||||
|
code-review-graph MCP tools BEFORE using Grep/Glob/Read to explore
|
||||||
|
the codebase.** The graph is faster, cheaper (fewer tokens), and gives
|
||||||
|
you structural context (callers, dependents, test coverage) that file
|
||||||
|
scanning cannot.
|
||||||
|
|
||||||
|
### When to use graph tools FIRST
|
||||||
|
|
||||||
|
- **Exploring code**: `semantic_search_nodes` or `query_graph` instead of Grep
|
||||||
|
- **Understanding impact**: `get_impact_radius` instead of manually tracing imports
|
||||||
|
- **Code review**: `detect_changes` + `get_review_context` instead of reading entire files
|
||||||
|
- **Finding relationships**: `query_graph` with callers_of/callees_of/imports_of/tests_for
|
||||||
|
- **Architecture questions**: `get_architecture_overview` + `list_communities`
|
||||||
|
|
||||||
|
Fall back to Grep/Glob/Read **only** when the graph doesn't cover what you need.
|
||||||
|
|
||||||
|
### Key Tools
|
||||||
|
|
||||||
|
| Tool | Use when |
|
||||||
|
|------|----------|
|
||||||
|
| `detect_changes` | Reviewing code changes — gives risk-scored analysis |
|
||||||
|
| `get_review_context` | Need source snippets for review — token-efficient |
|
||||||
|
| `get_impact_radius` | Understanding blast radius of a change |
|
||||||
|
| `get_affected_flows` | Finding which execution paths are impacted |
|
||||||
|
| `query_graph` | Tracing callers, callees, imports, tests, dependencies |
|
||||||
|
| `semantic_search_nodes` | Finding functions/classes by name or keyword |
|
||||||
|
| `get_architecture_overview` | Understanding high-level codebase structure |
|
||||||
|
| `refactor_tool` | Planning renames, finding dead code |
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
|
||||||
|
1. The graph auto-updates on file changes (via hooks).
|
||||||
|
2. Use `detect_changes` for code review.
|
||||||
|
3. Use `get_affected_flows` to understand impact.
|
||||||
|
4. Use `query_graph` pattern="tests_for" to check coverage.
|
||||||
@ -109,46 +109,35 @@ pack_image() {
|
|||||||
MD5_FILE="${PACKAGE_FILE}.md5"
|
MD5_FILE="${PACKAGE_FILE}.md5"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> [1/4] 打包镜像 -> ${PACKAGE_FILE}"
|
echo ">>> [1/3] 打包镜像 -> ${PACKAGE_FILE}"
|
||||||
docker save -o "${PACKAGE_FILE}" "${IMAGE_NAME}"
|
docker save -o "${PACKAGE_FILE}" "${IMAGE_NAME}"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> [2/4] gzip 压缩 (最高压缩级别)"
|
echo ">>> [2/3] 生成校验文件"
|
||||||
GZIP_FILE="${PACKAGE_FILE}.gz"
|
|
||||||
gzip -9 -f "${PACKAGE_FILE}"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo ">>> [3/4] 生成校验文件"
|
|
||||||
md5sum "${GZIP_FILE}" > "${GZIP_FILE}.md5"
|
|
||||||
md5sum "${PACKAGE_FILE}" > "${MD5_FILE}"
|
md5sum "${PACKAGE_FILE}" > "${MD5_FILE}"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> [4/4] 打包完成"
|
echo ">>> [3/3] 打包完成"
|
||||||
ls -lh "${GZIP_FILE}" "${GZIP_FILE}.md5" "${MD5_FILE}"
|
ls -lh "${PACKAGE_FILE}" "${MD5_FILE}"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "============================================"
|
echo "============================================"
|
||||||
echo " 下一步操作提示"
|
echo " 下一步操作提示"
|
||||||
echo "============================================"
|
echo "============================================"
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> 1. 传输镜像到服务器 (推荐使用 .tar.gz 压缩包,体积更小)"
|
echo ">>> 1. 传输镜像到服务器"
|
||||||
echo ""
|
echo ""
|
||||||
echo " # 方式一: scp 传输压缩包"
|
echo " # 方式一: scp 传输"
|
||||||
echo " scp ${GZIP_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/"
|
|
||||||
echo " scp ${GZIP_FILE}.md5 ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/"
|
|
||||||
echo ""
|
|
||||||
echo " # 方式二: scp 传输原始 tar 包 (不压缩)"
|
|
||||||
echo " scp ${PACKAGE_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/"
|
echo " scp ${PACKAGE_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/"
|
||||||
echo " scp ${MD5_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/"
|
echo " scp ${MD5_FILE} ${SERVER_USER}@${SERVER_HOST}:/opt/txw/images/"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo " # 方式二: 手动复制后执行 (推荐生产环境先上传再解压)"
|
||||||
|
echo ""
|
||||||
echo ">>> 2. SSH 到服务器后,执行以下命令:"
|
echo ">>> 2. SSH 到服务器后,执行以下命令:"
|
||||||
echo ""
|
echo ""
|
||||||
echo " # 创建目录"
|
echo " # 创建目录"
|
||||||
echo " ssh ${SERVER_USER}@${SERVER_HOST} 'mkdir -p /opt/txw/images'"
|
echo " ssh ${SERVER_USER}@${SERVER_HOST} 'mkdir -p /opt/txw/images'"
|
||||||
echo ""
|
echo ""
|
||||||
echo " # 解压 (如果上传的是 .tar.gz)"
|
|
||||||
echo " ssh ${SERVER_USER}@${SERVER_HOST} 'gunzip /opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar.gz'"
|
|
||||||
echo ""
|
|
||||||
echo " # 加载镜像"
|
echo " # 加载镜像"
|
||||||
echo " ssh ${SERVER_USER}@${SERVER_HOST} 'docker load -i /opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar'"
|
echo " ssh ${SERVER_USER}@${SERVER_HOST} 'docker load -i /opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar'"
|
||||||
echo ""
|
echo ""
|
||||||
@ -167,17 +156,14 @@ pack_image() {
|
|||||||
echo " -p 8080:8080 \\"
|
echo " -p 8080:8080 \\"
|
||||||
echo " ${IMAGE_NAME}'"
|
echo " ${IMAGE_NAME}'"
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> 4. 一键执行脚本 (上传 .tar.gz 后 ssh 内执行)"
|
echo ">>> 4. 一键执行脚本 (上传后ssh内执行)"
|
||||||
echo ""
|
echo ""
|
||||||
echo " ssh ${SERVER_USER}@${SERVER_HOST} << 'EOF'"
|
echo " ssh ${SERVER_USER}@${SERVER_HOST} << 'EOF'"
|
||||||
echo " #!/bin/bash"
|
echo " #!/bin/bash"
|
||||||
echo " GZIP_PATH=\"/opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar.gz\""
|
echo " IMAGE_PATH=\"/opt/txw/images/${IMAGE_TYPE}-${VERSION}-${TIMESTAMP}.tar\""
|
||||||
echo " "
|
|
||||||
echo " # 解压"
|
|
||||||
echo " gunzip \${GZIP_PATH}"
|
|
||||||
echo " "
|
echo " "
|
||||||
echo " # 加载镜像"
|
echo " # 加载镜像"
|
||||||
echo " docker load -i \${GZIP_PATH%.gz}"
|
echo " docker load -i \${IMAGE_PATH}"
|
||||||
echo " "
|
echo " "
|
||||||
echo " # 停止并移除旧容器"
|
echo " # 停止并移除旧容器"
|
||||||
echo " docker stop ${SERVICE_NAME} 2>/dev/null || true"
|
echo " docker stop ${SERVICE_NAME} 2>/dev/null || true"
|
||||||
@ -193,9 +179,8 @@ pack_image() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo "============================================"
|
echo "============================================"
|
||||||
echo ""
|
echo ""
|
||||||
echo "[*] 打包文件: ${GZIP_FILE} (压缩后,推荐传输)"
|
echo "[*] 打包文件: ${PACKAGE_FILE}"
|
||||||
echo "[*] 原始文件: ${PACKAGE_FILE} (未压缩)"
|
echo "[*] 校验文件: ${MD5_FILE}"
|
||||||
echo "[*] 校验文件: ${GZIP_FILE}.md5 ${MD5_FILE}"
|
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1039
docs/SSO认证模块详解.md
Normal file
504
docs/企业认证模块详解.md
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
# 碳信网企业认证模块详解
|
||||||
|
|
||||||
|
> 本文档基于代码分析,详细说明企业认证/入驻功能的表结构、流程、API接口及模块关系。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、模块定位
|
||||||
|
|
||||||
|
企业认证模块分为**两套流程**:
|
||||||
|
1. **企业认证**(qyRz/qysp)- mhzc-web 使用,通过DID扫码认证
|
||||||
|
2. **企业入驻**(qyrz)- gxzx-web/yygl-web 使用,通过表单申请+审核
|
||||||
|
|
||||||
|
这两个流程最终都会在 `txw_mhzc_qyxxb` 表中创建企业信息记录。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、核心表结构
|
||||||
|
|
||||||
|
### 2.1 企业申请记录表
|
||||||
|
|
||||||
|
#### txw_mhzc_qyrzsqjlb(企业认证申请记录表)
|
||||||
|
```sql
|
||||||
|
CREATE TABLE txw_mhzc_qyrzsqjlb (
|
||||||
|
uuid VARCHAR(64) PRIMARY KEY, -- 申请记录UUID
|
||||||
|
qymc VARCHAR(256), -- 企业名称
|
||||||
|
nsrsbh VARCHAR(64), -- 统一社会信用代码
|
||||||
|
sqsm TEXT, -- 申请说明
|
||||||
|
lrruuid VARCHAR(64), -- 录入人UUID
|
||||||
|
lrrq DATETIME, -- 录入日期
|
||||||
|
shrsfid VARCHAR(64), -- 审核人UUID
|
||||||
|
shjg1 VARCHAR(10), -- 审核结果 (2待审核/3通过/4不通过/5已撤销)
|
||||||
|
shyj1 TEXT, -- 审核意见
|
||||||
|
shsj DATETIME, -- 审核时间
|
||||||
|
sjhm1 VARCHAR(32), -- 手机号码
|
||||||
|
dlzh VARCHAR(64), -- 登录账号
|
||||||
|
zsxm1 VARCHAR(64), -- 真实姓名
|
||||||
|
yh_uuid VARCHAR(64) -- 用户UUID
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### txw_gxzx_rzsqjlb(入驻申请记录表)
|
||||||
|
```sql
|
||||||
|
-- 表结构与 txw_mhzc_qyrzsqjlb 基本相同
|
||||||
|
CREATE TABLE txw_gxzx_rzsqjlb (
|
||||||
|
uuid VARCHAR(64) PRIMARY KEY,
|
||||||
|
qymc VARCHAR(256),
|
||||||
|
nsrsbh VARCHAR(64),
|
||||||
|
sqsm TEXT,
|
||||||
|
ywlx_dm VARCHAR(10), -- 业务类型代码 (01)
|
||||||
|
sqly TEXT, -- 申请来源
|
||||||
|
lrruuid VARCHAR(64),
|
||||||
|
lrrq DATETIME,
|
||||||
|
shrsfid VARCHAR(64),
|
||||||
|
shjg1 VARCHAR(10),
|
||||||
|
shyj1 TEXT,
|
||||||
|
shsj DATETIME,
|
||||||
|
sjhm1 VARCHAR(32),
|
||||||
|
dlzh VARCHAR(64),
|
||||||
|
zsxm1 VARCHAR(64),
|
||||||
|
yh_uuid VARCHAR(64)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 企业信息表
|
||||||
|
|
||||||
|
#### txw_mhzc_qyxxb(企业信息表)
|
||||||
|
```sql
|
||||||
|
CREATE TABLE txw_mhzc_qyxxb (
|
||||||
|
qyuuid VARCHAR(64) PRIMARY KEY, -- 企业UUID
|
||||||
|
qymc VARCHAR(256), -- 企业名称
|
||||||
|
nsrsbh VARCHAR(64), -- 统一社会信用代码
|
||||||
|
gxdtrzbz VARCHAR(10), -- 供需大厅入驻标志 (Y/N)
|
||||||
|
yxbz VARCHAR(10), -- 有效标志 (Y/N)
|
||||||
|
ywqd_dm VARCHAR(32), -- 业务渠道代码
|
||||||
|
lrrq DATETIME, -- 录入日期
|
||||||
|
xgrq DATETIME, -- 修改日期
|
||||||
|
sjcsdq VARCHAR(32), -- 数据产生地区
|
||||||
|
sjgsdq VARCHAR(32), -- 数据归属地区
|
||||||
|
xgrsfid VARCHAR(64), -- 修改人身份ID
|
||||||
|
lrrsfid VARCHAR(64) -- 录入人身份ID
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 用户企业关联表
|
||||||
|
|
||||||
|
#### txw_mhzc_yhqygxb(用户企业关联表)
|
||||||
|
```sql
|
||||||
|
CREATE TABLE txw_mhzc_yhqygxb (
|
||||||
|
uuid VARCHAR(64) PRIMARY KEY,
|
||||||
|
qyuuid VARCHAR(64), -- 企业UUID
|
||||||
|
yh_uuid VARCHAR(64), -- 用户UUID
|
||||||
|
-- 其他字段...
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、认证流程详解
|
||||||
|
|
||||||
|
### 3.1 企业认证(DID扫码方式)- mhzc-web
|
||||||
|
|
||||||
|
**用户视角流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
未认证状态
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 显示"您未认证任何企业信息"提示 │
|
||||||
|
│ 点击"去认证" → 进入认证流程 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 显示 DID 二维码 │
|
||||||
|
│ 用户使用 DID APP 扫描二维码 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 轮询查询认证结果 │
|
||||||
|
│ GET /did/pub/backresult/login?reqId=xxx │
|
||||||
|
│ status=6 → 认证成功,显示企业信息卡片 │
|
||||||
|
│ status=5 → 认证失败,显示错误信息 │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**后端处理流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
DID服务器回调 POST /did/pub/callback/busi
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 验证 VerifiablePresentation │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 检查企业是否已认证 │
|
||||||
|
│ yhxxService.getYhxxByDid(holderDid) │
|
||||||
|
│ 已认证 → 返回"不能重复认证"错误 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
│ 未认证
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 验证企业名称一致性 │
|
||||||
|
│ DID中的entname 与 用户真实姓名匹配 │
|
||||||
|
│ 不匹配 → 返回"名称不一致"错误 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 创建/更新企业信息 │
|
||||||
|
│ TxwMhzcQyxxbServiceImpl.intQyxxByDid() │
|
||||||
|
│ 1. 检查企业是否已存在(按nsrsbh) │
|
||||||
|
│ 2. 不存在 → 新建企业记录 │
|
||||||
|
│ 3. 绑定用户与企业关系(yhqygxb) │
|
||||||
|
│ 4. 切换Session,绑定企业到用户 │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 企业入驻(表单申请方式)- gxzx-web
|
||||||
|
|
||||||
|
**用户视角流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
未认证状态
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 点击"发布"按钮 │
|
||||||
|
│ 检查企业认证状态 │
|
||||||
|
│ 未认证 → 提示"请先完成企业认证" │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 填写入驻表单 │
|
||||||
|
│ - 企业名称 │
|
||||||
|
│ - 统一社会信用代码 │
|
||||||
|
│ - 申请说明 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 提交申请 │
|
||||||
|
│ POST /gxzx/qyrz/qyrzsq │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 等待审核 │
|
||||||
|
│ 显示"待审核"状态 │
|
||||||
|
│ 可撤回申请 │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**后端处理流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /gxzx/qyrz/qyrzsq
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 创建入驻申请记录 │
|
||||||
|
│ TxwGxzxRzsqjlbServiceImpl.qyrzsq() │
|
||||||
|
│ - 插入 txw_gxzx_rzsqjlb 表 │
|
||||||
|
│ - ywlx_dm = "01" │
|
||||||
|
│ - shjg1 = "2" (待审核) │
|
||||||
|
│ - 关联当前用户信息 │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 企业认证审核 - yygl-web(运营后台)
|
||||||
|
|
||||||
|
**审核流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
运营人员登录 yygl-web
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 进入"企业认证审核"菜单 │
|
||||||
|
│ 显示待审核列表 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 查看企业详情 │
|
||||||
|
│ 企业名称、信用代码、手机号、申请时间、申请理由 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 选择审核结果 │
|
||||||
|
│ - 通过(shjg1 = 3) │
|
||||||
|
│ - 不通过(shjg1 = 4) │
|
||||||
|
│ + 填写审核意见 │
|
||||||
|
└─────────────────────┬───────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 提交审核 │
|
||||||
|
│ POST /mhzc/company/qyRzSp │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**后端处理:**
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /mhzc/company/qyRzSp
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ TxwMhzcQyxxbServiceImpl.qyRzSp() │
|
||||||
|
│ 1. 更新申请记录状态(shjg1, shyj1, shsj) │
|
||||||
|
│ 2. if 通过: │
|
||||||
|
│ - 创建企业信息(txw_mhzc_qyxxb) │
|
||||||
|
│ - 创建用户企业关联(txw_mhzc_yhqygxb) │
|
||||||
|
│ - 切换Session绑定企业 │
|
||||||
|
│ - 发送站内消息(审核通过模板) │
|
||||||
|
│ 3. if 不通过: │
|
||||||
|
│ - 发送站内消息(审核不通过模板) │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、模块分布
|
||||||
|
|
||||||
|
### 4.1 前端模块
|
||||||
|
|
||||||
|
| 项目 | 页面 | 功能 |
|
||||||
|
|------|------|------|
|
||||||
|
| txw-mhzc-web | `views/qyrz/index.vue` | 企业认证(DID方式) |
|
||||||
|
| txw-mhzc-web | `views/qy-rz/index.vue` | 企业入驻(预留) |
|
||||||
|
| txw-gxzx-web | `views/gxzx/index.vue` | 供需大厅发布时触发认证检查 |
|
||||||
|
| txw-yygl-web | `views/qysp/index.vue` | 企业认证审核(运营) |
|
||||||
|
| txw-yygl-web | `views/qyrz/index.vue` | 企业入驻审核(运营) |
|
||||||
|
| txw-mhzc-web | `views/gzt/components/EnterpriseCert.vue` | 工作台企业认证卡片 |
|
||||||
|
|
||||||
|
### 4.2 后端模块
|
||||||
|
|
||||||
|
| 服务 | Controller | Service | 说明 |
|
||||||
|
|------|------------|---------|------|
|
||||||
|
| txw-mhzc | `QyRzController` | `TxwGxzxRzsqjlbService` | 入驻申请 |
|
||||||
|
| txw-mhzc | `CompanyController` | `TxwMhzcQyxxbService` | 企业认证审核 |
|
||||||
|
| txw-gxzx | `QyRzController` | `TxwGxzxRzsqjlbService` | 入驻申请(gxzx独立) |
|
||||||
|
| txw-sso | `DidController` | `YhxxService` | DID认证 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、API接口
|
||||||
|
|
||||||
|
### 5.1 用户端API
|
||||||
|
|
||||||
|
| 接口 | 服务 | 方法 | 参数 | 说明 |
|
||||||
|
|------|------|------|------|------|
|
||||||
|
| `/mhzc/qyrz/qyrzsq` | mhzc | POST | `QyRzSqReqVO` | 提交入驻申请 |
|
||||||
|
| `/gxzx/qyrz/qyrzsq` | gxzx | POST | `QyRzSqReqVO` | 提交入驻申请 |
|
||||||
|
| `/mhzc/qyrz/currentQyrzList` | mhzc | POST | - | 查询当前用户入驻列表 |
|
||||||
|
| `/gxzx/qyrz/qyrzList` | gxzx | POST | `QyrzListReqVO` | 查询入驻申请列表 |
|
||||||
|
| `/mhzc/company/getCurrentRegisterList` | mhzc | POST | - | 查询当前认证记录 |
|
||||||
|
| `/mhzc/company/revokeSq` | mhzc | GET | uuid | 撤回申请 |
|
||||||
|
|
||||||
|
### 5.2 运营管理API
|
||||||
|
|
||||||
|
| 接口 | 服务 | 方法 | 参数 | 说明 |
|
||||||
|
|------|------|------|------|------|
|
||||||
|
| `/mhzc/company/qyRzSp` | mhzc | POST | `CompanySpReqVO` | 认证审核 |
|
||||||
|
| `/mhzc/company/getRegisterList` | mhzc | POST | `CompanySpReqVO` | 认证列表 |
|
||||||
|
| `/gxzx/qyrz/qyrzsp` | gxzx | POST | `QyRzSpReqVO` | 入驻审核 |
|
||||||
|
| `/gxzx/qyrz/qyrzList` | gxzx | POST | `QyrzListReqVO` | 入驻列表 |
|
||||||
|
| `/gxzx/company/getQyxxListByYwlx` | gxzx | GET | ywlx | 查询已入驻企业 |
|
||||||
|
|
||||||
|
### 5.3 DID认证API
|
||||||
|
|
||||||
|
| 接口 | 方法 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `/did/busilice/qrcode` | POST | 获取企业实名认证二维码 |
|
||||||
|
| `/did/pub/getvp/busi` | GET | 获取企业实名凭证 |
|
||||||
|
| `/did/pub/callback/busi` | POST | 企业实名回调 |
|
||||||
|
| `/did/pub/backresult/busi` | GET | 查询认证结果 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、审核状态流转
|
||||||
|
|
||||||
|
### 6.1 状态码定义
|
||||||
|
|
||||||
|
| 状态码 | 含义 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| `2` | 待审核 | 初始状态 |
|
||||||
|
| `3` | 通过 | 审核通过 |
|
||||||
|
| `4` | 不通过 | 审核拒绝 |
|
||||||
|
| `5` | 已撤销 | 用户撤回 |
|
||||||
|
|
||||||
|
### 6.2 状态流转图
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────┐
|
||||||
|
│ (新建) │
|
||||||
|
└────┬────┘
|
||||||
|
│ 提交申请
|
||||||
|
▼
|
||||||
|
┌─────────┐
|
||||||
|
│ 待审核 │ shjg1=2
|
||||||
|
│ (2) │
|
||||||
|
└────┬────┘
|
||||||
|
│
|
||||||
|
┌────┴────┐
|
||||||
|
│ │
|
||||||
|
通过│ │不通过
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
┌────────┐ ┌────────┐
|
||||||
|
│ 通过 │ │ 不通过 │
|
||||||
|
│ (3) │ │ (4) │
|
||||||
|
└────────┘ └────────┘
|
||||||
|
│
|
||||||
|
│ 用户撤回
|
||||||
|
▼
|
||||||
|
┌────────┐
|
||||||
|
│ 已撤销 │
|
||||||
|
│ (5) │
|
||||||
|
└────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、模块间关系
|
||||||
|
|
||||||
|
### 7.1 企业认证/入驻与用户的关系
|
||||||
|
|
||||||
|
```
|
||||||
|
用户登录(txw-sso)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
用户发起企业认证/入驻申请
|
||||||
|
│
|
||||||
|
├── mhzc-web: DID扫码认证
|
||||||
|
│ └─→ 创建 txw_mhzc_qyxxb(通过)
|
||||||
|
│
|
||||||
|
└── gxzx-web: 填表申请入驻
|
||||||
|
└─→ 创建 txw_gxzx_rzsqjlb(待审核)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
运营后台审核(yygl-web)
|
||||||
|
│
|
||||||
|
├── 通过 → 创建 txw_mhzc_qyxxb + txw_mhzc_yhqygxb
|
||||||
|
└── 不通过 → 更新状态为4
|
||||||
|
|
||||||
|
企业认证完成后:
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
用户可以使用以下功能:
|
||||||
|
- 发布供需信息(需gxdtrzbz=Y)
|
||||||
|
- 申请金融产品
|
||||||
|
- 发布碳资产交易
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 关键字段说明
|
||||||
|
|
||||||
|
| 字段 | 表 | 说明 |
|
||||||
|
|------|-----|------|
|
||||||
|
| `gxdtrzbz` | txw_mhzc_qyxxb | 供需大厅入驻标志,决定用户能否发布供需 |
|
||||||
|
| `yxbz` | txw_mhzc_qyxxb | 企业信息有效性 |
|
||||||
|
| `ywlxDm` | txw_gxzx_rzsqjlb | 业务类型,01=入驻 |
|
||||||
|
| `shjg1` | txw_mhzc_qyrzsqjlb | 审核结果 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、前端交互详解
|
||||||
|
|
||||||
|
### 8.1 mhzc-web 企业认证页面(qyrz/index.vue)
|
||||||
|
|
||||||
|
**页面状态机:**
|
||||||
|
|
||||||
|
| 状态 | 条件 | 显示内容 |
|
||||||
|
|------|------|---------|
|
||||||
|
| Tab1 | 有待审核/已通过记录 | 申请记录列表 + "去认证"按钮 |
|
||||||
|
| Tab2 | 未认证 | DID扫码界面 + 用户信息 |
|
||||||
|
| Tab3 | 已认证(yhxx.qymc存在) | 企业认证信息卡片 |
|
||||||
|
|
||||||
|
**核心代码逻辑:**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 初始化时检查企业认证状态
|
||||||
|
async yhinit() {
|
||||||
|
const { data } = await api.init();
|
||||||
|
this.yhxx = data;
|
||||||
|
if (this.yhxx?.qymc) {
|
||||||
|
this.pagetab = 3; // 已认证,显示认证卡片
|
||||||
|
} else {
|
||||||
|
this.Getrzqrcode(); // 未认证,显示二维码
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 轮询查询认证结果
|
||||||
|
async pollLoginResult() {
|
||||||
|
const { data } = await rzbackresultlogin(this.reqId);
|
||||||
|
if (data.status == 6) {
|
||||||
|
// 认证成功
|
||||||
|
this.stopPolling();
|
||||||
|
this.yhinit();
|
||||||
|
} else if (data.status == 5) {
|
||||||
|
// 认证失败
|
||||||
|
this.stopPolling();
|
||||||
|
MessagePlugin.info({ content: data.msg });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 yygl-web 审核页面
|
||||||
|
|
||||||
|
**qysp/index.vue** - 企业认证审核
|
||||||
|
- 查询条件:企业名称、信用代码、审核状态、申请时间
|
||||||
|
- 审核操作:弹出对话框选择"通过/不通过" + 填写意见
|
||||||
|
- API调用:`qyRzSp()` → `/mhzc/company/qyRzSp`
|
||||||
|
|
||||||
|
**qyrz/index.vue** - 企业入驻审核
|
||||||
|
- 查询条件同上
|
||||||
|
- 审核操作同上
|
||||||
|
- API调用:`qyRzSp()` → `/gxzx/qyrz/qyrzsp`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、错误处理
|
||||||
|
|
||||||
|
### 9.1 用户端错误
|
||||||
|
|
||||||
|
| 场景 | 提示信息 |
|
||||||
|
|------|---------|
|
||||||
|
| 企业已认证 | "企业已认证" |
|
||||||
|
| 申请理由为空 | 校验提示"申请说明必填" |
|
||||||
|
| 统一社会信用代码格式错误 | 前端校验提示 |
|
||||||
|
| 审核不通过后重申请 | 允许重新提交 |
|
||||||
|
|
||||||
|
### 9.2 审核端错误
|
||||||
|
|
||||||
|
| 场景 | 逻辑 |
|
||||||
|
|------|------|
|
||||||
|
| 重复认证 | DidController 返回"不能重复认证" |
|
||||||
|
| 名称不一致 | 返回"名称不一致"错误 |
|
||||||
|
| 企业不存在 | 查询返回null,跳过创建 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、外部依赖
|
||||||
|
|
||||||
|
| 依赖服务 | 用途 |
|
||||||
|
|---------|------|
|
||||||
|
| **xxzxApi(消息中心)** | 发送审核结果站内消息 |
|
||||||
|
| **IMhzcApi** | 获取用户信息、切换Session |
|
||||||
|
| **SwitchSessionApi** | 绑定用户与企业关系 |
|
||||||
|
| **DID服务** | 企业实名认证(org.chainweaver.did.sdk) |
|
||||||
|
|
||||||
|
### 10.1 消息模板
|
||||||
|
|
||||||
|
| 模板ID | 用途 |
|
||||||
|
|--------|------|
|
||||||
|
| `gxdt_rzsp_sptg` | 入驻审核通过(gxzx) |
|
||||||
|
| `gxdt_rzsp_spsb` | 入驻审核不通过(gxzx) |
|
||||||
|
| `mhzc_qyrz_sptg` | 认证审核通过(mhzc) |
|
||||||
|
| `mhzc_qyrz_spsb` | 认证审核不通过(mhzc) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档生成时间: 2026-05-03*
|
||||||
|
*基于企业认证模块代码分析*
|
||||||
738
docs/功能说明书.md
Normal file
@ -0,0 +1,738 @@
|
|||||||
|
# 碳信网项目功能说明书
|
||||||
|
|
||||||
|
> 本文档基于代码实现分析生成,排除干扰项(Axure原型文件、node_modules、部署脚本等),专注于实际功能。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、项目定位
|
||||||
|
|
||||||
|
碳信网是一个**碳排放管理、碳资产交易及相关服务的综合平台**,包含:
|
||||||
|
- **公众门户**(txw-gxzx-web):面向企业提供碳服务供需、碳金融、碳交易等功能
|
||||||
|
- **碳门户主页**(txw-mhzc-web):面向用户的碳服务平台首页
|
||||||
|
- **运营管理后台**(txw-yygl-web):运营人员使用的管理后台
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、功能模块层级图
|
||||||
|
|
||||||
|
```
|
||||||
|
├─ P0 认证模块
|
||||||
|
│ ├─ 用户名密码登录
|
||||||
|
│ ├─ 短信验证码登录
|
||||||
|
│ ├─ OAuth2第三方登录
|
||||||
|
│ ├─ 登出
|
||||||
|
│ └─ 会话初始化
|
||||||
|
│
|
||||||
|
├─ P0 碳服务供需模块(gxzx)
|
||||||
|
│ ├─ 供需大厅浏览
|
||||||
|
│ ├─ 供需信息发布(供给/需求)
|
||||||
|
│ ├─ 供需收藏
|
||||||
|
│ └─ 企业标签筛选
|
||||||
|
│
|
||||||
|
├─ P0 碳金融模块(lsjr/lsxd)
|
||||||
|
│ ├─ 金融机构列表(银行/保险)
|
||||||
|
│ ├─ 金融产品列表
|
||||||
|
│ ├─ 产品详情查看
|
||||||
|
│ └─ 金融产品申请(信贷/保险)
|
||||||
|
│
|
||||||
|
├─ P0 碳交易模块(lsjy)
|
||||||
|
│ ├─ 碳资产列表浏览
|
||||||
|
│ ├─ 碳资产详情
|
||||||
|
│ ├─ 碳资产发布
|
||||||
|
│ └─ 碳资产上下架
|
||||||
|
│
|
||||||
|
├─ P0 企业入驻模块
|
||||||
|
│ ├─ 企业注册申请
|
||||||
|
│ ├─ 企业认证审核
|
||||||
|
│ └─ 企业入驻审核
|
||||||
|
│
|
||||||
|
├─ P1 用户中心
|
||||||
|
│ ├─ 工作台首页
|
||||||
|
│ ├─ 账号管理
|
||||||
|
│ ├─ 我的供给
|
||||||
|
│ ├─ 我的需求
|
||||||
|
│ ├─ 绿色交易管理
|
||||||
|
│ └─ 消息中心
|
||||||
|
│
|
||||||
|
├─ P1 运营管理
|
||||||
|
│ ├─ 用户管理
|
||||||
|
│ ├─ 轮播图管理
|
||||||
|
│ ├─ 公告发布管理
|
||||||
|
│ ├─ 服务供给审核
|
||||||
|
│ ├─ 需求审核
|
||||||
|
│ ├─ 绿色金融产品管理
|
||||||
|
│ ├─ 绿色交易审批
|
||||||
|
│ └─ 企业审批管理
|
||||||
|
│
|
||||||
|
├─ P1 搜索模块
|
||||||
|
│ ├─ 全局搜索
|
||||||
|
│ ├─ 热门搜索词
|
||||||
|
│ ├─ 搜索建议
|
||||||
|
│ └─ 搜索历史
|
||||||
|
│
|
||||||
|
├─ P2 企业出海模块
|
||||||
|
│ ├─ 电池法案解读
|
||||||
|
│ ├─ CBAM政策指引
|
||||||
|
│ └─ 航运燃料专题
|
||||||
|
│
|
||||||
|
├─ P2 碳能力平台
|
||||||
|
│ ├─ 碳核算平台
|
||||||
|
│ ├─ 碳认证机构
|
||||||
|
│ ├─ 碳交易平台
|
||||||
|
│ ├─ 碳金融服务
|
||||||
|
│ └─ 碳技术咨询
|
||||||
|
│
|
||||||
|
└─ P2 勋章系统
|
||||||
|
├─ 勋章配置管理
|
||||||
|
├─ 勋章审核列表
|
||||||
|
├─ 明星管理
|
||||||
|
└─ 抽奖记录管理
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、核心功能详解
|
||||||
|
|
||||||
|
### 3.1 认证模块(Authentication)
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
用户输入账号密码
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 登录表单验证 │ ← 检查图形验证码、短信验证码
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 调用登录API │ POST /sso/auth/login
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
成功 │ 失败
|
||||||
|
─────┼─────
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 保存Token │ 存储到sessionStorage
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 初始化用户会话 │ POST /mhzc/user/init
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ 跳转首页/工作台 │
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 账号密码登录 | `POST /sso/auth/login` | |
|
||||||
|
| 短信验证码登录 | `POST /sso/auth/loginBySMS` | |
|
||||||
|
| 第三方登录 | `POST /sso/starAuth/login` | mxlogin |
|
||||||
|
| OAuth2授权 | `POST /oauth2/authorize` | |
|
||||||
|
| 获取验证码 | `POST /sso/verify/get` | |
|
||||||
|
| 发送短信 | `POST /sso/auth/sendMsg` | |
|
||||||
|
| 登出 | `POST /sso/auth/logout` | |
|
||||||
|
| 会话初始化 | `POST /mhzc/user/init` | 获取用户信息和入驻状态 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 碳服务供需模块(供需大厅)
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
供需大厅首页
|
||||||
|
│
|
||||||
|
├── [供给] ───┬── 服务类型筛选
|
||||||
|
│ ├── 行业筛选
|
||||||
|
│ ├── 地区筛选
|
||||||
|
│ ├── 价格筛选
|
||||||
|
│ └── 关键词搜索
|
||||||
|
│
|
||||||
|
├── [需求] ───┬── 需求类型筛选(与供给类似)
|
||||||
|
│
|
||||||
|
└── [发布] ──┬── 检查企业认证状态
|
||||||
|
├── 未认证 → 提示去认证
|
||||||
|
└── 已认证 → 显示发布表单
|
||||||
|
│
|
||||||
|
├── 选择类型(供给/需求)
|
||||||
|
├── 填写标题、服务类型、行业、价格等
|
||||||
|
├── 设置有效期、联系人信息
|
||||||
|
└── 提交发布
|
||||||
|
```
|
||||||
|
|
||||||
|
**发布字段:**
|
||||||
|
| 字段 | 说明 | 必填 |
|
||||||
|
|------|------|------|
|
||||||
|
| ywlxDm | 业务类型(01供给/02需求) | 是 |
|
||||||
|
| title | 标题 | 是 |
|
||||||
|
| fwlx | 服务类型 | 是 |
|
||||||
|
| sshy | 所属行业 | 是 |
|
||||||
|
| price | 价格/预算 | 是 |
|
||||||
|
| qyuuid | 企业UUID | 是 |
|
||||||
|
| xzqh | 行政区划 | 否 |
|
||||||
|
| jzsj | 截止时间 | 否 |
|
||||||
|
| bq | 标签 | 否 |
|
||||||
|
| lxr | 联系人 | 否 |
|
||||||
|
| lxfs | 联系方式 | 否 |
|
||||||
|
| description | 详细描述 | 否 |
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 供需列表 | `POST /gxzx/gxdt/gxxxList` | 支持分页、类型筛选 |
|
||||||
|
| 发布供需 | `POST /gxzx/gxdt/gxfb` | |
|
||||||
|
| 收藏/取消收藏 | `POST /gxzx/gxdt/gxsc` | type: add/remove |
|
||||||
|
| 企业标签查询 | `POST /gxzx/gxdt/getQyuuidsByBq` | |
|
||||||
|
| 代码表查询 | `POST /yygl/cache/v1/list/${tableName}` | fwlx/xqlx/sshy等 |
|
||||||
|
|
||||||
|
**模块关系:**
|
||||||
|
- 供需大厅与企业入驻模块联动:未认证企业不能发布供需信息
|
||||||
|
- 供需信息需要审核后才能展示(通过运营后台tfwgj/tfwxq审核)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 碳金融模块(绿色信贷/保险)
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
碳金融首页
|
||||||
|
│
|
||||||
|
├── [绿色信贷] ───┬── 显示银行机构列表
|
||||||
|
│ └── 查看产品列表
|
||||||
|
│
|
||||||
|
└── [绿色保险] ───┬── 显示保险机构列表
|
||||||
|
└── 查看产品列表
|
||||||
|
|
||||||
|
查看产品详情
|
||||||
|
│
|
||||||
|
├── 显示产品信息(额度、期限、利率/保费等)
|
||||||
|
└── [立即申请]
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
申请表单(3步)
|
||||||
|
│
|
||||||
|
├── Step1: 填写信息
|
||||||
|
│ ├── 企业信息
|
||||||
|
│ ├── 联系人信息
|
||||||
|
│ └── 碳数据来源选择
|
||||||
|
│
|
||||||
|
├── Step2: 上传材料
|
||||||
|
│ └── 支持文件上传
|
||||||
|
│
|
||||||
|
└── Step3: 提交成功
|
||||||
|
```
|
||||||
|
|
||||||
|
**产品详情字段:**
|
||||||
|
| 字段 | 信贷产品 | 保险产品 |
|
||||||
|
|------|---------|---------|
|
||||||
|
| cpname | 产品名称 | 产品名称 |
|
||||||
|
| cpleixing | 产品类型 | 产品类型 |
|
||||||
|
| fgje | 最高额度 | 最高保额 |
|
||||||
|
| qx | 期限 | 保障期限 |
|
||||||
|
| fl | 费率 | 保费 |
|
||||||
|
| cppj | 产品配件/附加服务 | |
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 金融机构列表 | `POST /gxzx/lsjr/queryJgList` | type: xd/bx |
|
||||||
|
| 产品列表 | `POST /gxzx/lsjr/queryXdbxcpList` | 分页查询 |
|
||||||
|
| 产品详情 | `GET /gxzx/lsjr/queryXdbxcpxq` | |
|
||||||
|
| 信贷申请 | `POST /gxzx/lsjr/saveTbsqxx` | multipart |
|
||||||
|
| 保险申请 | `POST /gxzx/lsjr/saveTbsqxx` | multipart |
|
||||||
|
|
||||||
|
**模块关系:**
|
||||||
|
- 金融产品管理在运营后台(yygl-web/lscp/LsjrIndex.vue)
|
||||||
|
- 申请记录查看在运营后台(yygl-web/lscp/LsjrXq.vue)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.4 碳交易模块(绿色交易)
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
绿色交易大厅
|
||||||
|
│
|
||||||
|
├── 资产类型筛选
|
||||||
|
│ ├── 绿电绿证(ZC01)
|
||||||
|
│ ├── 碳配额(ZC02)
|
||||||
|
│ └── CCER(ZC03)
|
||||||
|
│
|
||||||
|
├── 价格区间筛选
|
||||||
|
│
|
||||||
|
└── 有效期筛选
|
||||||
|
|
||||||
|
查看资产详情
|
||||||
|
│
|
||||||
|
└── [联系/申请]
|
||||||
|
```
|
||||||
|
|
||||||
|
**资产发布字段:**
|
||||||
|
| 字段 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| zclx | 资产类型 |
|
||||||
|
| sl | 数量 |
|
||||||
|
| dj | 单价 |
|
||||||
|
| yxrq | 有效期 |
|
||||||
|
| zcnf | 资产年份 |
|
||||||
|
| lxr | 联系人 |
|
||||||
|
| lxfs | 联系方式 |
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 资产类型列表 | `GET /gxzx/lsjy/queryZclxList` | |
|
||||||
|
| 资产列表 | `POST /gxzx/lsjy/queryZcxxList` | 分页 |
|
||||||
|
| 资产详情 | `GET /gxzx/lsjy/queryZcxxxq` | |
|
||||||
|
| 发布/更新资产 | `POST /gxzx/lsjy/saveOrUpdate` | |
|
||||||
|
| 上下架 | `POST /gxzx/lsjy/zcsxj` | |
|
||||||
|
| 审批 | `POST /gxzx/lsjy/zcSp` | |
|
||||||
|
| 删除 | `POST /gxzx/lsjy/delete/${zcid}` | |
|
||||||
|
|
||||||
|
**模块关系:**
|
||||||
|
- 交易资产需要审核(运营后台lsjy审批)
|
||||||
|
- 与运营后台的绿色交易管理联动
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.5 企业入驻模块
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
企业入口选择
|
||||||
|
│
|
||||||
|
├── [企业认证] ← 已有企业资质,申请认证
|
||||||
|
│ │
|
||||||
|
│ ├── 填写企业信息
|
||||||
|
│ │ ├── 企业名称
|
||||||
|
│ │ ├── 统一社会信用代码
|
||||||
|
│ │ └── 营业执照等资质
|
||||||
|
│ └── 提交认证申请
|
||||||
|
│ │
|
||||||
|
│ ▼
|
||||||
|
│ 运营后台审核(通过/拒绝)
|
||||||
|
│
|
||||||
|
└── [企业入驻] ← 新企业申请入驻平台
|
||||||
|
│
|
||||||
|
├── 填写入驻信息
|
||||||
|
│ ├── 企业基本信息
|
||||||
|
│ ├── 联系人信息
|
||||||
|
│ └── 期望服务类型
|
||||||
|
└── 提交入驻申请
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
运营后台审核
|
||||||
|
```
|
||||||
|
|
||||||
|
**认证/入驻字段:**
|
||||||
|
| 字段 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| qymc | 企业名称 |
|
||||||
|
| tyshxydm | 统一社会信用代码 |
|
||||||
|
| frdb | 法定代表人 |
|
||||||
|
| lxr | 联系人 |
|
||||||
|
| lxfs | 联系方式 |
|
||||||
|
| qydz | 企业地址 |
|
||||||
|
| rzxs | 入驻形式 |
|
||||||
|
| qwlx | 期望服务类型 |
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 企业注册 | `POST /gxzx/qyrz/qyrzsq` | gxzx-web |
|
||||||
|
| 企业注册 | `POST /mhzc/company/register` | mhzc-web |
|
||||||
|
| 认证申请 | `POST /mhzc/company/register` | |
|
||||||
|
| 认证列表 | `POST /mhzc/company/getRegisterList` | 运营后台 |
|
||||||
|
| 认证审核 | `POST /mhzc/company/qyRzSp` | |
|
||||||
|
| 入驻列表 | `POST /gxzx/qyrz/qyrzList` | |
|
||||||
|
| 入驻审核 | `POST /gxzx/qyrz/qyrzsp` | |
|
||||||
|
|
||||||
|
**模块关系:**
|
||||||
|
- 企业认证/入驻状态决定用户可用功能
|
||||||
|
- 状态存储在init接口返回的`gxdtRzbz`字段
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.6 用户中心
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
用户中心首页(工作台)
|
||||||
|
│
|
||||||
|
├── 概览统计
|
||||||
|
│ ├── 供给数量
|
||||||
|
│ ├── 需求数量
|
||||||
|
│ └── 交易数量
|
||||||
|
│
|
||||||
|
├── 快捷操作
|
||||||
|
│ ├── 发布供给
|
||||||
|
│ ├── 发布需求
|
||||||
|
│ └── 查看更多
|
||||||
|
│
|
||||||
|
├── 我的供给列表
|
||||||
|
│
|
||||||
|
├── 我的需求列表
|
||||||
|
│
|
||||||
|
└── 政策新闻/公告
|
||||||
|
```
|
||||||
|
|
||||||
|
**用户中心子模块:**
|
||||||
|
| 模块 | 功能 |
|
||||||
|
|------|------|
|
||||||
|
| 工作台 | 统计概览、快捷操作、我的供给/需求 |
|
||||||
|
| 账号管理 | 个人信息、密码修改 |
|
||||||
|
| 企业认证 | 认证状态查询、认证申请 |
|
||||||
|
| 企业入驻 | 入驻状态查询、入驻申请 |
|
||||||
|
| 我的供给 | 查看我发布的供给信息 |
|
||||||
|
| 我的需求 | 查看我发布的需求信息 |
|
||||||
|
| 绿色交易 | 我发布的碳资产 |
|
||||||
|
| 消息中心 | 系统公告、我的消息 |
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 用户初始化 | `POST /mhzc/user/init` | 获取用户+企业信息 |
|
||||||
|
| 工作台统计 | `GET /gxzx/gxdt/getStats` | 获取统计数据 |
|
||||||
|
| 公告列表 | `POST /yygl/xx/getXxByXxflDmPage` | |
|
||||||
|
| 发布公告 | `POST /yygl/xx/xxfb` | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.7 运营管理模块
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
运营管理系统首页
|
||||||
|
│
|
||||||
|
├── 企业管理
|
||||||
|
│ ├── 企业认证审核 ← 审核企业资质
|
||||||
|
│ └── 企业入驻审核 ← 审核入驻申请
|
||||||
|
│
|
||||||
|
├── 用户管理
|
||||||
|
│ ├── 用户列表 ← 查看所有用户
|
||||||
|
│ ├── 冻结/解冻用户
|
||||||
|
│ └── 重置密码
|
||||||
|
│
|
||||||
|
├── 内容管理
|
||||||
|
│ ├── 轮播图管理 ← 首页Banner配置
|
||||||
|
│ └── 公告发布管理 ← 系统公告
|
||||||
|
│
|
||||||
|
├── 碳服务管理
|
||||||
|
│ ├── 服务供给审核 ← 审核供给信息
|
||||||
|
│ └── 需求审核 ← 审核需求信息
|
||||||
|
│
|
||||||
|
├── 绿色金融管理
|
||||||
|
│ ├── 产品管理 ← 增删改金融产品
|
||||||
|
│ └── 申请查看 ← 查看信贷/保险申请
|
||||||
|
│
|
||||||
|
└── 绿色交易管理
|
||||||
|
├── 交易管理 ← 查看/上下架资产
|
||||||
|
└── 交易审批 ← 审核新发布资产
|
||||||
|
```
|
||||||
|
|
||||||
|
**审核流程:**
|
||||||
|
```
|
||||||
|
用户提交申请
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
运营后台显示待审核列表
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
运营人员查看详情
|
||||||
|
│
|
||||||
|
├── [通过] → 更新状态为已通过
|
||||||
|
│ 信息公开展示
|
||||||
|
│
|
||||||
|
└── [拒绝] → 填写拒绝原因
|
||||||
|
更新状态为已拒绝
|
||||||
|
用户可修改后重新提交
|
||||||
|
```
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 认证审核 | `POST /mhzc/company/qyRzSp` | |
|
||||||
|
| 入驻审核 | `POST /gxzx/qyrz/qyrzsp` | |
|
||||||
|
| 服务审核 | `POST /gxzx/gxdt/gxsp` | ywlxDm=01 |
|
||||||
|
| 需求审核 | `POST /gxzx/gxdt/gxsp` | ywlxDm=02 |
|
||||||
|
| 交易审批 | `POST /gxzx/lsjy/zcSp` | |
|
||||||
|
| 用户列表 | `POST /mhzc/user/getAllUser` | |
|
||||||
|
| 冻结用户 | `POST /mhzc/user/lockUser` | |
|
||||||
|
| 解冻用户 | `POST /mhzc/user/unlockUser` | |
|
||||||
|
| 重置密码 | `POST /sso/auth/resetPassword` | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.8 搜索模块
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
搜索入口
|
||||||
|
│
|
||||||
|
├── 输入关键词
|
||||||
|
│ │
|
||||||
|
│ ├── 显示搜索建议(下拉提示)
|
||||||
|
│ │
|
||||||
|
│ └── 回车/点击搜索
|
||||||
|
│ │
|
||||||
|
│ ▼
|
||||||
|
│ 搜索结果页
|
||||||
|
│ │
|
||||||
|
│ ├── 按类型分类展示
|
||||||
|
│ │ ├── 资讯
|
||||||
|
│ │ ├── 企业
|
||||||
|
│ │ ├── 产品
|
||||||
|
│ │ └──供需信息
|
||||||
|
│ │
|
||||||
|
│ └── 热门搜索词展示
|
||||||
|
│
|
||||||
|
└── 热门搜索词点击直接搜索
|
||||||
|
```
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 全局搜索 | `GET /mhzc/search` | keyword, categoryType |
|
||||||
|
| 热门搜索 | `GET /mhzc/search/hot` | |
|
||||||
|
| 搜索建议 | `GET /mhzc/search/suggest` | keyword |
|
||||||
|
| 搜索历史 | `GET /mhzc/search/history` | |
|
||||||
|
| 清除历史 | `DELETE /mhzc/search/history` | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.9 企业出海模块
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
企业出海专题页
|
||||||
|
│
|
||||||
|
├── [电池法案] ← EU Battery Act
|
||||||
|
│ ├── 政策要求
|
||||||
|
│ ├── 合规指引
|
||||||
|
│ └── 案例分享
|
||||||
|
│
|
||||||
|
├── [CBAM] ← Carbon Border Adjustment Mechanism
|
||||||
|
│ ├── 政策解读
|
||||||
|
│ ├── 合规指引
|
||||||
|
│ └── 案例分析
|
||||||
|
│
|
||||||
|
└── [航运燃料] ← Shipping Fuel
|
||||||
|
├── 政策要求
|
||||||
|
├── 合规指引
|
||||||
|
└── 案例分享
|
||||||
|
```
|
||||||
|
|
||||||
|
**模块关系:**
|
||||||
|
- 企业出海模块与碳服务供需模块独立
|
||||||
|
- 不涉及交易流程,仅信息展示
|
||||||
|
- 提供合规服务申请入口
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.10 碳能力平台
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
碳能力平台首页
|
||||||
|
│
|
||||||
|
├── [碳核算平台] ← 碳核算机构目录
|
||||||
|
│
|
||||||
|
├── [碳认证机构] ← 碳认证服务目录
|
||||||
|
│
|
||||||
|
├── [碳交易平台] ← 碳交易机构目录
|
||||||
|
│
|
||||||
|
├── [碳金融服务] ← 碳金融服务机构
|
||||||
|
│
|
||||||
|
└── [碳技术咨询] ← 碳技术咨询服务
|
||||||
|
```
|
||||||
|
|
||||||
|
**模块关系:**
|
||||||
|
- 仅做机构展示
|
||||||
|
- 点击可查看机构详情
|
||||||
|
- 不涉及交易流程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.11 勋章系统(mhcz-web特有)
|
||||||
|
|
||||||
|
**功能流程:**
|
||||||
|
|
||||||
|
```
|
||||||
|
勋章管理(运营后台)
|
||||||
|
│
|
||||||
|
├── 勋章配置
|
||||||
|
│ ├── 配置勋章名称、图标、规则
|
||||||
|
│ └── 配置勋章状态(启用/停用)
|
||||||
|
│
|
||||||
|
├── 勋章审核
|
||||||
|
│ ├── 查看用户申请列表
|
||||||
|
│ └── 审核通过/拒绝
|
||||||
|
│
|
||||||
|
└── 勋章模板
|
||||||
|
├── 管理勋章模板
|
||||||
|
└── 模板明细查询
|
||||||
|
|
||||||
|
明星管理
|
||||||
|
│
|
||||||
|
├── 明星列表
|
||||||
|
│ ├── 明星基本信息
|
||||||
|
│ └── 明星认证状态
|
||||||
|
│
|
||||||
|
└── 期望明星统计
|
||||||
|
└── 统计分析用户期望的明星
|
||||||
|
```
|
||||||
|
|
||||||
|
**API清单:**
|
||||||
|
| 功能 | 接口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 勋章配置列表 | `POST /yhzxApi/xz/getXzpzList` | |
|
||||||
|
| 勋章审核列表 | `POST /yhzxApi/xz/getXzsqList` | |
|
||||||
|
| 明星列表 | `POST /yhzxApi/user/getStarList` | |
|
||||||
|
| 创建明星 | `POST /yhzxApi/user/createStar` | |
|
||||||
|
| 抽奖记录 | `POST /yhzxApi/shdz/getCjjlPage` | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、模块间关系图
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────┐
|
||||||
|
│ SSO认证 │
|
||||||
|
│ 系统 │
|
||||||
|
└──────┬───────┘
|
||||||
|
│ 所有模块依赖
|
||||||
|
┌──────────────┼──────────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||||
|
│ gxzx-web │ │ mhzc-web │ │ yygl-web │
|
||||||
|
└────┬─────┘ └────┬─────┘ └────┬─────┘
|
||||||
|
│ │ │
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||||
|
│ 供需大厅 │ │ 服务中心 │ │ 运营管理 │
|
||||||
|
│ 碳金融 │ │ 用户中心 │ │ 企业审核 │
|
||||||
|
│ 碳交易 │ │ 碳交易市场 │ │ 内容管理 │
|
||||||
|
└──────────┘ └──────────┘ └──────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────┐
|
||||||
|
│ 企业入驻模块 │
|
||||||
|
│ (共享) │
|
||||||
|
└──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**依赖关系说明:**
|
||||||
|
|
||||||
|
| 模块 | 依赖模块 | 说明 |
|
||||||
|
|------|---------|------|
|
||||||
|
| 供需大厅 | 企业入驻 | 未认证不能发布 |
|
||||||
|
| 碳金融 | 企业入驻 | 申请需要企业信息 |
|
||||||
|
| 碳交易 | 企业入驻 | 发布需要企业信息 |
|
||||||
|
| 用户中心 | 认证模块 | 需要登录态 |
|
||||||
|
| 运营管理 | 认证模块 | 需要管理员权限 |
|
||||||
|
| 运营管理 | 企业入驻 | 审核入驻申请 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、数据流概览
|
||||||
|
|
||||||
|
### 5.1 用户会话数据
|
||||||
|
|
||||||
|
```
|
||||||
|
登录 → sessionStorage['yhxx']
|
||||||
|
│
|
||||||
|
├── userId
|
||||||
|
├── username
|
||||||
|
├── companyUuid
|
||||||
|
├── gxdtRzbz (企业认证状态)
|
||||||
|
└── ... 其他用户信息
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 核心数据状态
|
||||||
|
|
||||||
|
| 状态字段 | 说明 | 影响功能 |
|
||||||
|
|---------|------|---------|
|
||||||
|
| gxdtRzbz | 企业认证状态 | 供需发布、金融申请 |
|
||||||
|
| qyrzSpzt | 入驻审核状态 | 企业入驻功能 |
|
||||||
|
| sjfwZt | 上下架状态 | 信息是否展示 |
|
||||||
|
|
||||||
|
### 5.3 审核流程数据
|
||||||
|
|
||||||
|
```
|
||||||
|
提交申请
|
||||||
|
↓
|
||||||
|
pending (待审核)
|
||||||
|
↓
|
||||||
|
approved/rejected (通过/拒绝)
|
||||||
|
↓
|
||||||
|
if approved → 公开显示
|
||||||
|
if rejected → 可修改重提交
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、功能优先级汇总
|
||||||
|
|
||||||
|
### P0 - 核心功能(系统运行必需)
|
||||||
|
|
||||||
|
| 模块 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 认证 | 账号密码登录 | 基础认证 |
|
||||||
|
| 认证 | 会话初始化 | 获取用户权限信息 |
|
||||||
|
| 供需 | 供需大厅浏览 | 核心业务入口 |
|
||||||
|
| 供需 | 供需发布 | 核心业务操作 |
|
||||||
|
| 金融 | 产品列表/详情 | 金融业务入口 |
|
||||||
|
| 金融 | 金融申请 | 核心业务操作 |
|
||||||
|
| 交易 | 碳资产交易 | 核心业务 |
|
||||||
|
| 企业入驻 | 企业注册/认证 | 基础业务 |
|
||||||
|
|
||||||
|
### P1 - 重要功能(业务完整性)
|
||||||
|
|
||||||
|
| 模块 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 运营管理 | 企业审核 | 运营基础功能 |
|
||||||
|
| 运营管理 | 内容管理 | 运营基础功能 |
|
||||||
|
| 运营管理 | 用户管理 | 运营基础功能 |
|
||||||
|
| 用户中心 | 工作台 | 用户入口 |
|
||||||
|
| 搜索 | 全局搜索 | 信息检索 |
|
||||||
|
|
||||||
|
### P2 - 扩展功能(增值服务)
|
||||||
|
|
||||||
|
| 模块 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 企业出海 | CBAM解读 | 增值服务 |
|
||||||
|
| 碳能力平台 | 机构目录 | 增值服务 |
|
||||||
|
| 勋章系统 | 勋章管理 | 用户激励 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、接口前缀汇总
|
||||||
|
|
||||||
|
| 前缀 | 后端服务 | 用途 |
|
||||||
|
|------|---------|------|
|
||||||
|
| `/sso/*` | txw-sso | 认证服务 |
|
||||||
|
| `/mhzc/*` | txw-mhzc | 碳门户服务 |
|
||||||
|
| `/gxzx/*` | txw-gxzx | 可信碳信息服务 |
|
||||||
|
| `/yygl/*` | txw-yygl | 运营管理服务 |
|
||||||
|
| `/yhzxApi/*` | txw-mhzc | 用户中心API |
|
||||||
|
| `/ggzcApi/*` | txw-common | 公共API |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档生成时间: 2026-05-03*
|
||||||
|
*基于代码实现分析生成,排除干扰项*
|
||||||
40
txw-mhzc-web/src/pages/index/api/yhfk/index.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { fetchSso } from '@/core/request';
|
||||||
|
|
||||||
|
const basurl = '/mhzc';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 提交反馈(新增/编辑)
|
||||||
|
submit(params) {
|
||||||
|
return fetchSso({
|
||||||
|
url: `${basurl}/yhfk/submit`,
|
||||||
|
method: 'post',
|
||||||
|
loading: true,
|
||||||
|
data: JSON.stringify(params),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 我的反馈分页列表
|
||||||
|
myList(params) {
|
||||||
|
return fetchSso({
|
||||||
|
url: `${basurl}/yhfk/myList`,
|
||||||
|
method: 'post',
|
||||||
|
loading: true,
|
||||||
|
data: JSON.stringify(params),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 反馈详情
|
||||||
|
detail(uuid) {
|
||||||
|
return fetchSso({
|
||||||
|
url: `${basurl}/yhfk/detail?uuid=${uuid}`,
|
||||||
|
method: 'get',
|
||||||
|
loading: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 撤销反馈
|
||||||
|
cancel(uuid) {
|
||||||
|
return fetchSso({
|
||||||
|
url: `${basurl}/yhfk/cancel?uuid=${uuid}`,
|
||||||
|
method: 'get',
|
||||||
|
loading: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -106,6 +106,11 @@ function zhanghugl() {
|
|||||||
return import(/* webpackChunkName: "zhanghugl" */ '@/pages/index/views/yhzx/zhanghugl/index.vue');
|
return import(/* webpackChunkName: "zhanghugl" */ '@/pages/index/views/yhzx/zhanghugl/index.vue');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户反馈
|
||||||
|
function yhfk() {
|
||||||
|
return import(/* webpackChunkName: "yhfk" */ '@/pages/index/views/yhfk/index.vue');
|
||||||
|
}
|
||||||
|
|
||||||
// md文档查看器
|
// md文档查看器
|
||||||
function mdviewer() {
|
function mdviewer() {
|
||||||
return import(/* webpackChunkName: "mdviewer" */ '@/pages/index/views/mdviewer/index.vue');
|
return import(/* webpackChunkName: "mdviewer" */ '@/pages/index/views/mdviewer/index.vue');
|
||||||
@ -188,6 +193,7 @@ export default [
|
|||||||
{ path: 'ggwhgl', component: newsCenter, name: 'ggwhgl', meta: { title: '消息中心' } },
|
{ path: 'ggwhgl', component: newsCenter, name: 'ggwhgl', meta: { title: '消息中心' } },
|
||||||
{ path: 'lsjy', component: lsjy, name: 'lsjy', meta: { title: '绿色交易' } },
|
{ path: 'lsjy', component: lsjy, name: 'lsjy', meta: { title: '绿色交易' } },
|
||||||
{ path: 'zhanghugl', component: zhanghugl, name: 'zhanghugl', meta: { title: '账号管理' } },
|
{ path: 'zhanghugl', component: zhanghugl, name: 'zhanghugl', meta: { title: '账号管理' } },
|
||||||
|
{ path: 'yhfk', component: yhfk, name: 'yhfk', meta: { title: '意见反馈' } },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -249,12 +249,6 @@ export default {
|
|||||||
if (this.$route.query.publish === '1') {
|
if (this.$route.query.publish === '1') {
|
||||||
this.handlePublish();
|
this.handlePublish();
|
||||||
}
|
}
|
||||||
// 如果URL有id参数,等待数据加载后定位到对应项
|
|
||||||
if (this.$route.query.id) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.scrollToItem(this.$route.query.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 初始化用户信息
|
// 初始化用户信息
|
||||||
@ -332,6 +326,7 @@ export default {
|
|||||||
async searchList() {
|
async searchList() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.cardList = [];
|
this.cardList = [];
|
||||||
|
const targetId = this.$route.query.id || '';
|
||||||
try {
|
try {
|
||||||
const prame = {
|
const prame = {
|
||||||
ywlxDm: '01',
|
ywlxDm: '01',
|
||||||
@ -340,6 +335,10 @@ export default {
|
|||||||
};
|
};
|
||||||
// 只展示收藏项:Y=是, N=否
|
// 只展示收藏项:Y=是, N=否
|
||||||
prame.scbz = this.filter.zzsscx ? 'Y' : 'N';
|
prame.scbz = this.filter.zzsscx ? 'Y' : 'N';
|
||||||
|
// URL携带id:按id精确查询单条
|
||||||
|
if (targetId) {
|
||||||
|
prame.gxUuid = targetId;
|
||||||
|
}
|
||||||
const { data } = await api.gxxxList(prame);
|
const { data } = await api.gxxxList(prame);
|
||||||
if (data.records) {
|
if (data.records) {
|
||||||
data.records.map((item) => {
|
data.records.map((item) => {
|
||||||
@ -355,6 +354,10 @@ export default {
|
|||||||
}
|
}
|
||||||
this.cardList = data.records || [];
|
this.cardList = data.records || [];
|
||||||
this.page.total = Number(data.total || 0);
|
this.page.total = Number(data.total || 0);
|
||||||
|
// 数据渲染后定位到对应项
|
||||||
|
if (targetId) {
|
||||||
|
this.scrollToItem(targetId);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.cardList = [];
|
this.cardList = [];
|
||||||
this.page.total = 0;
|
this.page.total = 0;
|
||||||
|
|||||||
@ -268,12 +268,6 @@ export default {
|
|||||||
if (this.$route.query.publish === '1') {
|
if (this.$route.query.publish === '1') {
|
||||||
this.handlePublish();
|
this.handlePublish();
|
||||||
}
|
}
|
||||||
// 如果URL有id参数,等待数据加载后定位到对应项
|
|
||||||
if (this.$route.query.id) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.scrollToItem(this.$route.query.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 加载代码表
|
// 加载代码表
|
||||||
@ -310,6 +304,7 @@ export default {
|
|||||||
async searchList() {
|
async searchList() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.cardList = [];
|
this.cardList = [];
|
||||||
|
const targetId = this.$route.query.id || '';
|
||||||
try {
|
try {
|
||||||
const prame = {
|
const prame = {
|
||||||
ywlxDm: '02',
|
ywlxDm: '02',
|
||||||
@ -319,6 +314,10 @@ export default {
|
|||||||
if (prame.dq === '000000') {
|
if (prame.dq === '000000') {
|
||||||
prame.dq = '';
|
prame.dq = '';
|
||||||
}
|
}
|
||||||
|
// URL携带id:按id精确查询单条
|
||||||
|
if (targetId) {
|
||||||
|
prame.gxUuid = targetId;
|
||||||
|
}
|
||||||
const { data } = await api.gxxxList(prame);
|
const { data } = await api.gxxxList(prame);
|
||||||
if (data.records) {
|
if (data.records) {
|
||||||
data.records.map((item) => {
|
data.records.map((item) => {
|
||||||
@ -334,6 +333,10 @@ export default {
|
|||||||
}
|
}
|
||||||
this.cardList = data.records || [];
|
this.cardList = data.records || [];
|
||||||
this.page.total = Number(data.total || 0);
|
this.page.total = Number(data.total || 0);
|
||||||
|
// 数据渲染后定位到对应项
|
||||||
|
if (targetId) {
|
||||||
|
this.scrollToItem(targetId);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.cardList = [];
|
this.cardList = [];
|
||||||
this.page.total = 0;
|
this.page.total = 0;
|
||||||
|
|||||||
@ -176,6 +176,20 @@ export default {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'bzyzc',
|
||||||
|
title: '帮助与支持',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 'yhfk',
|
||||||
|
title: '意见反馈',
|
||||||
|
icon: 'chat',
|
||||||
|
name: 'yhfk',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
],
|
],
|
||||||
ejcdList: [],
|
ejcdList: [],
|
||||||
iFrameSrc: '',
|
iFrameSrc: '',
|
||||||
|
|||||||
@ -17,13 +17,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { UploadIcon, CloudUploadIcon, EditIcon, BulletpointIcon } from 'tdesign-icons-vue';
|
import { UploadIcon, CloudUploadIcon, EditIcon, BulletpointIcon, ChatIcon } from 'tdesign-icons-vue';
|
||||||
|
|
||||||
const iconMap = {
|
const iconMap = {
|
||||||
upload: UploadIcon,
|
upload: UploadIcon,
|
||||||
'cloud-upload': CloudUploadIcon,
|
'cloud-upload': CloudUploadIcon,
|
||||||
edit: EditIcon,
|
edit: EditIcon,
|
||||||
bulletpoint: BulletpointIcon,
|
bulletpoint: BulletpointIcon,
|
||||||
|
chat: ChatIcon,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -33,6 +34,7 @@ export default {
|
|||||||
CloudUploadIcon,
|
CloudUploadIcon,
|
||||||
EditIcon,
|
EditIcon,
|
||||||
BulletpointIcon,
|
BulletpointIcon,
|
||||||
|
ChatIcon,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -41,6 +43,7 @@ export default {
|
|||||||
// { label: '发布数据', to: '/yhzx/tfwgj?action=publishData', icon: 'cloud-upload', bgColor: '#E6F8F0', color: '#344F3D' },
|
// { label: '发布数据', to: '/yhzx/tfwgj?action=publishData', icon: 'cloud-upload', bgColor: '#E6F8F0', color: '#344F3D' },
|
||||||
{ label: '发布需求', to: '/yhzx/tfwxq', icon: 'edit', bgColor: '#E6F8F0', color: '#344F3D' },
|
{ label: '发布需求', to: '/yhzx/tfwxq', icon: 'edit', bgColor: '#E6F8F0', color: '#344F3D' },
|
||||||
// { label: '资质申请', to: '/yhzx/zzgl', icon: 'bulletpoint', bgColor: '#E6F8F0', color: '#344F3D' },
|
// { label: '资质申请', to: '/yhzx/zzgl', icon: 'bulletpoint', bgColor: '#E6F8F0', color: '#344F3D' },
|
||||||
|
{ label: '意见反馈', to: '/yhzx/yhfk', icon: 'chat', bgColor: '#E6F8F0', color: '#344F3D' },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 13 KiB |
@ -319,7 +319,7 @@ export default {
|
|||||||
icon: require('@/pages/index/views/home2/assets/closed-loop@2x.png')
|
icon: require('@/pages/index/views/home2/assets/closed-loop@2x.png')
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
hotSearchTags: ["碳核查", "ESG", "碳资产管理", "ISO 14067"],
|
hotSearchTags: ["碳达峰", "碳核查", "ESG", "碳资产管理", "ISO 14067"],
|
||||||
// 企业出海数据
|
// 企业出海数据
|
||||||
overseas2List: [
|
overseas2List: [
|
||||||
{ name: '电池法案', btnName: "申请服务", link: '', desc: "欧盟电池法案管控电池全生命周期,用碳足迹、电池护照、再生料、回收、供应链尽调设硬性准入门槛,强制绿色循环。", icon: require('@/pages/index/assets/home-dcfa-icon.png') },
|
{ name: '电池法案', btnName: "申请服务", link: '', desc: "欧盟电池法案管控电池全生命周期,用碳足迹、电池护照、再生料、回收、供应链尽调设硬性准入门槛,强制绿色循环。", icon: require('@/pages/index/assets/home-dcfa-icon.png') },
|
||||||
@ -333,7 +333,7 @@ export default {
|
|||||||
{ name: '平台公告', type: 'ptgg' }
|
{ name: '平台公告', type: 'ptgg' }
|
||||||
],
|
],
|
||||||
// 合作伙伴数据
|
// 合作伙伴数据
|
||||||
partnerCount: '200+',
|
partnerCount: ' 40+ ',
|
||||||
partnerList: [
|
partnerList: [
|
||||||
{ name: '合作伙伴', logo: require('@/pages/index/views/home2/assets/partner-1.png') },
|
{ name: '合作伙伴', logo: require('@/pages/index/views/home2/assets/partner-1.png') },
|
||||||
{ name: '合作伙伴', logo: require('@/pages/index/views/home2/assets/partner-2.png') },
|
{ name: '合作伙伴', logo: require('@/pages/index/views/home2/assets/partner-2.png') },
|
||||||
@ -554,11 +554,11 @@ export default {
|
|||||||
},
|
},
|
||||||
getDefaultPic(type) {
|
getDefaultPic(type) {
|
||||||
const defaultPics = {
|
const defaultPics = {
|
||||||
gjzc: '/static_res/images/news/default-news.png',
|
gjzc: 'static_res/images/news/default-news.png',
|
||||||
hyzx: '/static_res/images/news/default-hydt.png',
|
hyzx: 'static_res/images/news/default-hyzx.png',
|
||||||
ptgg: '/static_res/images/news/default-ptgg.png'
|
ptgg: 'static_res/images/news/default-ptgg.png'
|
||||||
};
|
};
|
||||||
return defaultPics[type] || '/static_res/images/news/default-news.png';
|
return defaultPics[type] || 'static_res/images/news/default-hyzx.png';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
padding: 60px 300px;
|
padding: 60px 0;
|
||||||
background: url(../../assets/hyzt/banner.png);
|
background: url(../../assets/hyzt/banner.png);
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -79,6 +79,8 @@ export default {
|
|||||||
font-size: 64px;
|
font-size: 64px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #000;
|
color: #000;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 1300px;
|
||||||
}
|
}
|
||||||
.desc {
|
.desc {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
|||||||
501
txw-mhzc-web/src/pages/index/views/yhfk/index.vue
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
<template>
|
||||||
|
<div class="yhfk-page">
|
||||||
|
<div class="yhfk-page-search">
|
||||||
|
<t-form
|
||||||
|
ref="searchform"
|
||||||
|
:data="formData"
|
||||||
|
layout="inline"
|
||||||
|
@submit="onSubmit"
|
||||||
|
@reset="onReset"
|
||||||
|
>
|
||||||
|
<t-form-item label="反馈类型" name="fklx">
|
||||||
|
<t-select v-model="formData.fklx" placeholder="请选择" clearable style="width: 160px">
|
||||||
|
<t-option v-for="item in fklxOptions" :key="item.value" :value="item.value" :label="item.label" />
|
||||||
|
</t-select>
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="处理状态" name="czzt">
|
||||||
|
<t-select v-model="formData.czzt" placeholder="请选择" clearable style="width: 160px">
|
||||||
|
<t-option v-for="item in czztOptions" :key="item.value" :value="item.value" :label="item.label" />
|
||||||
|
</t-select>
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="反馈标题" name="bt">
|
||||||
|
<t-input v-model="formData.bt" placeholder="请输入" clearable style="width: 200px" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="反馈起始日期" name="lrrqq">
|
||||||
|
<t-date-picker v-model="formData.lrrqq" clearable style="width: 160px" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="反馈截止日期" name="lrrqz">
|
||||||
|
<t-date-picker v-model="formData.lrrqz" clearable style="width: 160px" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item>
|
||||||
|
<t-space>
|
||||||
|
<t-button theme="primary" type="submit">查询</t-button>
|
||||||
|
<t-button theme="default" type="reset">重置</t-button>
|
||||||
|
</t-space>
|
||||||
|
</t-form-item>
|
||||||
|
</t-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="yhfk-page-table">
|
||||||
|
<div class="table-toolbar">
|
||||||
|
<t-button theme="primary" @click="openSubmit()">我要反馈</t-button>
|
||||||
|
</div>
|
||||||
|
<t-table
|
||||||
|
:data="list"
|
||||||
|
:columns="columns"
|
||||||
|
row-key="uuid"
|
||||||
|
:max-height="540"
|
||||||
|
:pagination="pagination"
|
||||||
|
@page-change="onPageChange"
|
||||||
|
:loading="tableloading"
|
||||||
|
>
|
||||||
|
<template #fklx="{ row }">
|
||||||
|
<t-tag :theme="fklxTagTheme(row.fklx)" variant="light">{{ row.fklxMc || row.fklx }}</t-tag>
|
||||||
|
</template>
|
||||||
|
<template #czzt="{ row }">
|
||||||
|
<t-tag :theme="czztTagTheme(row.czzt)" variant="light">{{ row.czztMc || row.czzt }}</t-tag>
|
||||||
|
</template>
|
||||||
|
<template #cz="{ row }">
|
||||||
|
<t-button variant="text" theme="primary" @click="openDetail(row)">查看详情</t-button>
|
||||||
|
<t-button variant="text" theme="primary" v-if="row.czzt === '0'" @click="openSubmit(row)">编辑</t-button>
|
||||||
|
<t-button variant="text" theme="danger" v-if="row.czzt === '0'" @click="onCancel(row)">撤销</t-button>
|
||||||
|
</template>
|
||||||
|
</t-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 提交反馈弹窗 -->
|
||||||
|
<t-dialog
|
||||||
|
:visible.sync="submitVisible"
|
||||||
|
:header="submitForm.uuid ? '编辑反馈' : '提交反馈'"
|
||||||
|
:footer="false"
|
||||||
|
:closeOnOverlayClick="false"
|
||||||
|
width="640px"
|
||||||
|
@close="closeSubmit"
|
||||||
|
>
|
||||||
|
<t-form
|
||||||
|
ref="submitFormRef"
|
||||||
|
:data="submitForm"
|
||||||
|
:rules="submitRules"
|
||||||
|
labelAlign="top"
|
||||||
|
@submit="onSave"
|
||||||
|
>
|
||||||
|
<t-form-item label="反馈类型" name="fklx">
|
||||||
|
<t-radio-group v-model="submitForm.fklx">
|
||||||
|
<t-radio v-for="item in fklxOptions" :key="item.value" :value="item.value">{{ item.label }}</t-radio>
|
||||||
|
</t-radio-group>
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="反馈标题" name="bt">
|
||||||
|
<t-input v-model="submitForm.bt" placeholder="请输入反馈标题(不超过100字)" :maxlength="100" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="反馈内容" name="nr">
|
||||||
|
<t-textarea
|
||||||
|
v-model="submitForm.nr"
|
||||||
|
placeholder="请详细描述您遇到的问题或建议(不超过2000字)"
|
||||||
|
:autosize="{ minRows: 5, maxRows: 10 }"
|
||||||
|
:maxlength="2000"
|
||||||
|
show-limit-number
|
||||||
|
/>
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="联系人" name="lxr">
|
||||||
|
<t-input v-model="submitForm.lxr" placeholder="请输入联系人姓名" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="联系电话" name="lxdh">
|
||||||
|
<t-input v-model="submitForm.lxdh" placeholder="请输入联系电话" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="联系邮箱" name="lxyx">
|
||||||
|
<t-input v-model="submitForm.lxyx" placeholder="请输入邮箱地址" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item>
|
||||||
|
<div style="width: 100%; text-align: center">
|
||||||
|
<t-button theme="primary" type="submit" style="margin-right: 12px">提交</t-button>
|
||||||
|
<t-button theme="default" variant="base" @click="closeSubmit">取消</t-button>
|
||||||
|
</div>
|
||||||
|
</t-form-item>
|
||||||
|
</t-form>
|
||||||
|
</t-dialog>
|
||||||
|
|
||||||
|
<!-- 反馈详情弹窗 -->
|
||||||
|
<t-dialog
|
||||||
|
:visible.sync="detailVisible"
|
||||||
|
header="反馈详情"
|
||||||
|
:footer="false"
|
||||||
|
:closeOnOverlayClick="true"
|
||||||
|
width="680px"
|
||||||
|
class="yhfk-detail-dialog"
|
||||||
|
>
|
||||||
|
<div class="detail-card" v-if="detail.uuid">
|
||||||
|
<div class="detail-header">
|
||||||
|
<div class="detail-header-top">
|
||||||
|
<t-tag :theme="fklxTagTheme(detail.fklx)" variant="light-outline" size="medium">
|
||||||
|
{{ detail.fklxMc || detail.fklx }}
|
||||||
|
</t-tag>
|
||||||
|
<t-tag :theme="czztTagTheme(detail.czzt)" variant="light" size="medium">
|
||||||
|
{{ detail.czztMc }}
|
||||||
|
</t-tag>
|
||||||
|
</div>
|
||||||
|
<div class="detail-title">{{ detail.bt }}</div>
|
||||||
|
<div class="detail-time">提交于 {{ detail.lrrq }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="detail-section">
|
||||||
|
<div class="detail-section-title">反馈内容</div>
|
||||||
|
<div class="detail-content">{{ detail.nr }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="detail-section">
|
||||||
|
<div class="detail-section-title">联系方式</div>
|
||||||
|
<div class="detail-grid">
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="detail-label">联系人</span>
|
||||||
|
<span class="detail-value">{{ detail.lxr || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="detail-label">联系电话</span>
|
||||||
|
<span class="detail-value">{{ detail.lxdh || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item detail-item-full">
|
||||||
|
<span class="detail-label">联系邮箱</span>
|
||||||
|
<span class="detail-value">{{ detail.lxyx || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="detail-section detail-section-result" v-if="detail.czyj || detail.czrq">
|
||||||
|
<div class="detail-section-title">处理结果</div>
|
||||||
|
<div class="detail-content" v-if="detail.czyj">{{ detail.czyj }}</div>
|
||||||
|
<div class="detail-time detail-time-end" v-if="detail.czrq">处理时间:{{ detail.czrq }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { MessagePlugin, DialogPlugin } from 'tdesign-vue';
|
||||||
|
import api from '@/pages/index/api/yhfk/index';
|
||||||
|
|
||||||
|
const FKLX_OPTIONS = [
|
||||||
|
{ value: 'bug', label: '问题反馈' },
|
||||||
|
{ value: 'suggest', label: '建议改进' },
|
||||||
|
{ value: 'function', label: '功能需求' },
|
||||||
|
{ value: 'other', label: '其他' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const CZZT_OPTIONS = [
|
||||||
|
{ value: '0', label: '待处理' },
|
||||||
|
{ value: '1', label: '处理中' },
|
||||||
|
{ value: '2', label: '已处理' },
|
||||||
|
{ value: '3', label: '已关闭' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'YhfkPage',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fklxOptions: FKLX_OPTIONS,
|
||||||
|
czztOptions: CZZT_OPTIONS,
|
||||||
|
formData: {
|
||||||
|
fklx: '',
|
||||||
|
czzt: '',
|
||||||
|
bt: '',
|
||||||
|
lrrqq: '',
|
||||||
|
lrrqz: '',
|
||||||
|
},
|
||||||
|
list: [],
|
||||||
|
tableloading: false,
|
||||||
|
pagination: {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ align: 'center', colKey: 'serial-number', width: '70px', title: '序号' },
|
||||||
|
{ align: 'left', width: '120px', colKey: 'fklx', title: '反馈类型' },
|
||||||
|
{ align: 'left', minWidth: '200px', colKey: 'bt', title: '反馈标题', ellipsis: true },
|
||||||
|
{ align: 'left', width: '160px', colKey: 'lrrq', title: '提交时间' },
|
||||||
|
{ align: 'left', width: '120px', colKey: 'czzt', title: '处理状态' },
|
||||||
|
{ align: 'left', width: '180px', colKey: 'cz', title: '操作', fixed: 'right' },
|
||||||
|
],
|
||||||
|
submitVisible: false,
|
||||||
|
submitForm: this.defaultSubmitForm(),
|
||||||
|
submitRules: {
|
||||||
|
fklx: [{ required: true, message: '请选择反馈类型', type: 'error' }],
|
||||||
|
bt: [{ required: true, message: '请输入反馈标题', type: 'error' }],
|
||||||
|
nr: [{ required: true, message: '请输入反馈内容', type: 'error' }],
|
||||||
|
lxdh: [
|
||||||
|
{
|
||||||
|
pattern: /^1[3-9]\d{9}$/,
|
||||||
|
message: '请输入有效的手机号',
|
||||||
|
type: 'warning',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lxyx: [
|
||||||
|
{
|
||||||
|
pattern: /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/,
|
||||||
|
message: '请输入有效的邮箱地址',
|
||||||
|
type: 'warning',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
detailVisible: false,
|
||||||
|
detail: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.onQuery();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
defaultSubmitForm() {
|
||||||
|
return {
|
||||||
|
uuid: '',
|
||||||
|
fklx: 'bug',
|
||||||
|
bt: '',
|
||||||
|
nr: '',
|
||||||
|
lxr: '',
|
||||||
|
lxdh: '',
|
||||||
|
lxyx: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
fklxTagTheme(fklx) {
|
||||||
|
const map = { bug: 'danger', suggest: 'primary', function: 'success', other: 'default' };
|
||||||
|
return map[fklx] || 'default';
|
||||||
|
},
|
||||||
|
czztTagTheme(czzt) {
|
||||||
|
const map = { 0: 'warning', 1: 'primary', 2: 'success', 3: 'default' };
|
||||||
|
return map[czzt] || 'default';
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
this.pagination.current = 1;
|
||||||
|
this.onQuery();
|
||||||
|
},
|
||||||
|
onReset() {
|
||||||
|
this.formData = { fklx: '', czzt: '', bt: '', lrrqq: '', lrrqz: '' };
|
||||||
|
this.pagination.current = 1;
|
||||||
|
this.onQuery();
|
||||||
|
},
|
||||||
|
onPageChange(pageInfo) {
|
||||||
|
this.pagination.current = pageInfo.current;
|
||||||
|
this.pagination.pageSize = pageInfo.pageSize;
|
||||||
|
this.onQuery();
|
||||||
|
},
|
||||||
|
async onQuery() {
|
||||||
|
this.tableloading = true;
|
||||||
|
const params = {
|
||||||
|
...this.formData,
|
||||||
|
pageNum: this.pagination.current,
|
||||||
|
pageSize: this.pagination.pageSize,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const res = await api.myList(params);
|
||||||
|
this.list = res?.data?.records || [];
|
||||||
|
this.pagination.total = Number(res?.data?.total || 0);
|
||||||
|
} catch (err) {
|
||||||
|
this.list = [];
|
||||||
|
this.pagination.total = 0;
|
||||||
|
} finally {
|
||||||
|
this.tableloading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openSubmit(row) {
|
||||||
|
if (row && row.uuid) {
|
||||||
|
this.submitForm = {
|
||||||
|
uuid: row.uuid,
|
||||||
|
fklx: row.fklx,
|
||||||
|
bt: row.bt,
|
||||||
|
nr: row.nr,
|
||||||
|
lxr: row.lxr || '',
|
||||||
|
lxdh: row.lxdh || '',
|
||||||
|
lxyx: row.lxyx || '',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.submitForm = this.defaultSubmitForm();
|
||||||
|
}
|
||||||
|
this.submitVisible = true;
|
||||||
|
},
|
||||||
|
closeSubmit() {
|
||||||
|
this.submitVisible = false;
|
||||||
|
this.submitForm = this.defaultSubmitForm();
|
||||||
|
},
|
||||||
|
async onSave({ validateResult }) {
|
||||||
|
if (validateResult !== true) return;
|
||||||
|
try {
|
||||||
|
const res = await api.submit(this.submitForm);
|
||||||
|
if (res?.code === 1 || res?.code === 0) {
|
||||||
|
MessagePlugin.success(this.submitForm.uuid ? '修改成功' : '提交成功');
|
||||||
|
this.closeSubmit();
|
||||||
|
this.onQuery();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// 错误信息已由全局拦截器处理
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async openDetail(row) {
|
||||||
|
try {
|
||||||
|
const res = await api.detail(row.uuid);
|
||||||
|
this.detail = res?.data || {};
|
||||||
|
this.detailVisible = true;
|
||||||
|
} catch (err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel(row) {
|
||||||
|
const dialog = DialogPlugin.confirm({
|
||||||
|
header: '提示',
|
||||||
|
body: '确认撤销该条反馈吗?撤销后无法恢复。',
|
||||||
|
onConfirm: async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.cancel(row.uuid);
|
||||||
|
if (res?.code === 1 || res?.code === 0) {
|
||||||
|
MessagePlugin.success('撤销成功');
|
||||||
|
this.onQuery();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
dialog.destroy();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClose: () => dialog.destroy(),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.yhfk-page {
|
||||||
|
height: 100%;
|
||||||
|
padding: 24px;
|
||||||
|
background: #ecf1f9;
|
||||||
|
}
|
||||||
|
.yhfk-page-search {
|
||||||
|
padding: 16px 24px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.yhfk-page-table {
|
||||||
|
margin-top: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.table-toolbar {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.detail-box {
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .yhfk-detail-dialog .t-dialog__body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .yhfk-detail-dialog .t-dialog__body > div {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card {
|
||||||
|
padding: 24px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #e7e7e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header-top {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1d2129;
|
||||||
|
line-height: 1.5;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-time {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #86909c;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-section {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1d2129;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-left: 10px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-section-title::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 3px;
|
||||||
|
height: 14px;
|
||||||
|
background: #0052d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
background: #f7f8fa;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: #4e5969;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item-full {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #86909c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-value {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1d2129;
|
||||||
|
font-weight: 500;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-section-result .detail-content {
|
||||||
|
background: #f2f8ff;
|
||||||
|
border-left: 3px solid #0052d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-time-end {
|
||||||
|
margin-top: 12px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -287,20 +287,20 @@ module.exports = {
|
|||||||
// 会误伤 SPA 路由 /view/mhzc/...,刷新时整页请求被转发到后端导致 Proxy error。必须用 ^ 限定为路径前缀。
|
// 会误伤 SPA 路由 /view/mhzc/...,刷新时整页请求被转发到后端导致 Proxy error。必须用 ^ 限定为路径前缀。
|
||||||
proxy: {
|
proxy: {
|
||||||
'^/sso': {
|
'^/sso': {
|
||||||
// target: 'http://localhost:9301',
|
target: 'http://localhost:9300',
|
||||||
target: 'http://carbon.liantu.tech',
|
// target: 'http://carbon.liantu.tech',
|
||||||
// target: 'http://10.23.20.13:94/',
|
// target: 'http://10.23.20.13:94/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
'^/mhzc': {
|
'^/mhzc': {
|
||||||
// target: 'http://localhost:9302',
|
target: 'http://localhost:9300',
|
||||||
target: 'http://carbon.liantu.tech',
|
// target: 'http://carbon.liantu.tech',
|
||||||
// target: 'http://10.23.20.13:94/',
|
// target: 'http://10.23.20.13:94/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
'^/gxzx': {
|
'^/gxzx': {
|
||||||
// target: 'http://localhost:9303',
|
target: 'http://localhost:9300',
|
||||||
target: 'http://carbon.liantu.tech',
|
// target: 'http://carbon.liantu.tech',
|
||||||
// target: 'http://10.23.20.13:94/',
|
// target: 'http://10.23.20.13:94/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
|
|||||||
26
txw-mhzc/sql/txw_mhzc_yhfkb.sql
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
-- 用户反馈表
|
||||||
|
CREATE TABLE `txw_mhzc_yhfkb` (
|
||||||
|
`uuid` VARCHAR(50) NOT NULL COMMENT 'UUID',
|
||||||
|
`fklx` VARCHAR(20) NOT NULL COMMENT '反馈类型(bug=问题反馈、suggest=建议改进、function=功能需求、other=其他)',
|
||||||
|
`fklx_mc` VARCHAR(50) DEFAULT NULL COMMENT '反馈类型名称',
|
||||||
|
`bt` VARCHAR(200) NOT NULL COMMENT '反馈标题',
|
||||||
|
`nr` TEXT COMMENT '反馈内容',
|
||||||
|
`tp` VARCHAR(2000) DEFAULT NULL COMMENT '附件图片(多个用逗号分隔)',
|
||||||
|
`lxr` VARCHAR(50) DEFAULT NULL COMMENT '联系人',
|
||||||
|
`lxdh` VARCHAR(50) DEFAULT NULL COMMENT '联系电话',
|
||||||
|
`lxyx` VARCHAR(100) DEFAULT NULL COMMENT '联系邮箱',
|
||||||
|
`czzt` CHAR(1) DEFAULT '0' COMMENT '处理状态(0=待处理、1=处理中、2=已处理、3=已关闭)',
|
||||||
|
`czyj` TEXT COMMENT '处理意见',
|
||||||
|
`czrq` DATETIME DEFAULT NULL COMMENT '处理日期',
|
||||||
|
`czruuid` VARCHAR(50) DEFAULT NULL COMMENT '处理人UUID',
|
||||||
|
`qyuuid` VARCHAR(50) DEFAULT NULL COMMENT '企业UUID',
|
||||||
|
`qymc` VARCHAR(200) DEFAULT NULL COMMENT '企业名称',
|
||||||
|
`lrrq` DATETIME DEFAULT NULL COMMENT '录入日期',
|
||||||
|
`lrruuid` VARCHAR(50) DEFAULT NULL COMMENT '录入人UUID',
|
||||||
|
`xgrq` DATETIME DEFAULT NULL COMMENT '修改日期',
|
||||||
|
`xgruuid` VARCHAR(50) DEFAULT NULL COMMENT '修改人UUID',
|
||||||
|
PRIMARY KEY (`uuid`),
|
||||||
|
KEY `idx_lrruuid` (`lrruuid`),
|
||||||
|
KEY `idx_czzt` (`czzt`),
|
||||||
|
KEY `idx_lrrq` (`lrrq`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户反馈表';
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package com.css.txw.mhzc.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||||
|
import com.css.txw.mhzc.pojo.vo.YhfkReqVO;
|
||||||
|
import com.css.txw.mhzc.pojo.vo.YhfkVO;
|
||||||
|
import com.css.txw.mhzc.service.TxwMhzcYhfkbService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Tag(name = "用户反馈接口")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/yhfk")
|
||||||
|
@Validated
|
||||||
|
@Slf4j
|
||||||
|
public class YhfkController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TxwMhzcYhfkbService yhfkbService;
|
||||||
|
|
||||||
|
@PostMapping("/submit")
|
||||||
|
@Operation(summary = "提交反馈", description = "新增或编辑(仅未处理状态可编辑)")
|
||||||
|
public CommonResult<String> submit(@RequestBody YhfkVO reqVO) {
|
||||||
|
return CommonResult.success(yhfkbService.submit(reqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/myList")
|
||||||
|
@Operation(summary = "我的反馈分页列表", description = "分页查询当前登录用户提交的反馈记录")
|
||||||
|
public CommonResult<Page<YhfkVO>> myList(@RequestBody YhfkReqVO reqVO) {
|
||||||
|
return CommonResult.success(yhfkbService.myFkPage(reqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/detail")
|
||||||
|
@Operation(summary = "反馈详情", description = "根据UUID查询反馈详情")
|
||||||
|
public CommonResult<YhfkVO> detail(@RequestParam("uuid") String uuid) {
|
||||||
|
return CommonResult.success(yhfkbService.getDetail(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/cancel")
|
||||||
|
@Operation(summary = "撤销反馈", description = "撤销自己提交的、且未处理的反馈")
|
||||||
|
public CommonResult<String> cancel(@RequestParam("uuid") String uuid) {
|
||||||
|
return CommonResult.success(yhfkbService.cancel(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -28,6 +28,7 @@ public interface TxwGxzxGxxxbMapper extends BaseMapper<TxwGxzxGxxxbDO> {
|
|||||||
.and(!GyUtils.isNull(reqVO.getNr()),w->w.like(TxwGxzxGxxxbDO::getBt1,reqVO.getNr()).or().like(TxwGxzxGxxxbDO::getFwnr,reqVO.getNr()).or().like(TxwGxzxGxxxbDO::getQymc,reqVO.getNr()))
|
.and(!GyUtils.isNull(reqVO.getNr()),w->w.like(TxwGxzxGxxxbDO::getBt1,reqVO.getNr()).or().like(TxwGxzxGxxxbDO::getFwnr,reqVO.getNr()).or().like(TxwGxzxGxxxbDO::getQymc,reqVO.getNr()))
|
||||||
.eq(TxwGxzxGxxxbDO::getSjzt,"Y")
|
.eq(TxwGxzxGxxxbDO::getSjzt,"Y")
|
||||||
.eq(TxwGxzxGxxxbDO::getZt,"3")
|
.eq(TxwGxzxGxxxbDO::getZt,"3")
|
||||||
|
.eq(!GyUtils.isNull(reqVO.getGxUuid()),TxwGxzxGxxxbDO::getGxUuid,reqVO.getGxUuid())
|
||||||
.in(!GyUtils.isNull(reqVO.getSshy()),TxwGxzxGxxxbDO::getSshy,reqVO.getSshy())
|
.in(!GyUtils.isNull(reqVO.getSshy()),TxwGxzxGxxxbDO::getSshy,reqVO.getSshy())
|
||||||
.like(!GyUtils.isNull(reqVO.getDq()),TxwGxzxGxxxbDO::getFwfw,reqVO.getDq())
|
.like(!GyUtils.isNull(reqVO.getDq()),TxwGxzxGxxxbDO::getFwfw,reqVO.getDq())
|
||||||
.lt(!GyUtils.isNull(reqVO.getFbsjz()),TxwGxzxGxxxbDO::getLrrq,reqVO.getFbsjz())
|
.lt(!GyUtils.isNull(reqVO.getFbsjz()),TxwGxzxGxxxbDO::getLrrq,reqVO.getFbsjz())
|
||||||
|
|||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.css.txw.mhzc.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||||
|
import com.css.txw.mhzc.pojo.domain.TxwMhzcYhfkbDO;
|
||||||
|
import com.css.txw.mhzc.pojo.vo.YhfkReqVO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Claude
|
||||||
|
* @description 针对表【txw_mhzc_yhfkb(用户反馈表)】的数据库操作Mapper
|
||||||
|
*/
|
||||||
|
public interface TxwMhzcYhfkbMapper extends BaseMapper<TxwMhzcYhfkbDO> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询用户反馈列表
|
||||||
|
*/
|
||||||
|
default Page<TxwMhzcYhfkbDO> getYhfkPage(YhfkReqVO reqVO, String yhUuid) {
|
||||||
|
QueryWrapper<TxwMhzcYhfkbDO> wrapper = new QueryWrapper<>();
|
||||||
|
if (!GyUtils.isNull(yhUuid)) {
|
||||||
|
wrapper.lambda().eq(TxwMhzcYhfkbDO::getLrruuid, yhUuid);
|
||||||
|
}
|
||||||
|
if (!GyUtils.isNull(reqVO.getFklx())) {
|
||||||
|
wrapper.lambda().eq(TxwMhzcYhfkbDO::getFklx, reqVO.getFklx());
|
||||||
|
}
|
||||||
|
if (!GyUtils.isNull(reqVO.getCzzt())) {
|
||||||
|
wrapper.lambda().eq(TxwMhzcYhfkbDO::getCzzt, reqVO.getCzzt());
|
||||||
|
}
|
||||||
|
if (!GyUtils.isNull(reqVO.getBt())) {
|
||||||
|
wrapper.lambda().like(TxwMhzcYhfkbDO::getBt, reqVO.getBt());
|
||||||
|
}
|
||||||
|
if (!GyUtils.isNull(reqVO.getLrrqq())) {
|
||||||
|
wrapper.lambda().ge(TxwMhzcYhfkbDO::getLrrq, reqVO.getLrrqq());
|
||||||
|
}
|
||||||
|
if (!GyUtils.isNull(reqVO.getLrrqz())) {
|
||||||
|
wrapper.lambda().le(TxwMhzcYhfkbDO::getLrrq, reqVO.getLrrqz() + " 23:59:59");
|
||||||
|
}
|
||||||
|
wrapper.lambda().orderByDesc(TxwMhzcYhfkbDO::getLrrq);
|
||||||
|
Page<TxwMhzcYhfkbDO> page = new Page<>(reqVO.getPageNo(), reqVO.getPageSize());
|
||||||
|
return selectPage(page, wrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,135 @@
|
|||||||
|
package com.css.txw.mhzc.pojo.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户反馈表
|
||||||
|
* @TableName txw_mhzc_yhfkb
|
||||||
|
*/
|
||||||
|
@TableName(value = "txw_mhzc_yhfkb")
|
||||||
|
@Data
|
||||||
|
public class TxwMhzcYhfkbDO implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UUID
|
||||||
|
*/
|
||||||
|
@TableId(value = "uuid")
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈类型(bug=问题反馈、suggest=建议改进、function=功能需求、other=其他)
|
||||||
|
*/
|
||||||
|
@TableField(value = "fklx")
|
||||||
|
private String fklx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈类型名称
|
||||||
|
*/
|
||||||
|
@TableField(value = "fklx_mc")
|
||||||
|
private String fklxMc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈标题
|
||||||
|
*/
|
||||||
|
@TableField(value = "bt")
|
||||||
|
private String bt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈内容
|
||||||
|
*/
|
||||||
|
@TableField(value = "nr")
|
||||||
|
private String nr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附件图片(多个用逗号分隔)
|
||||||
|
*/
|
||||||
|
@TableField(value = "tp")
|
||||||
|
private String tp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系人
|
||||||
|
*/
|
||||||
|
@TableField(value = "lxr")
|
||||||
|
private String lxr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系电话
|
||||||
|
*/
|
||||||
|
@TableField(value = "lxdh")
|
||||||
|
private String lxdh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系邮箱
|
||||||
|
*/
|
||||||
|
@TableField(value = "lxyx")
|
||||||
|
private String lxyx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理状态(0=待处理、1=处理中、2=已处理、3=已关闭)
|
||||||
|
*/
|
||||||
|
@TableField(value = "czzt")
|
||||||
|
private String czzt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理意见
|
||||||
|
*/
|
||||||
|
@TableField(value = "czyj")
|
||||||
|
private String czyj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理日期
|
||||||
|
*/
|
||||||
|
@TableField(value = "czrq")
|
||||||
|
private Date czrq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理人UUID
|
||||||
|
*/
|
||||||
|
@TableField(value = "czruuid")
|
||||||
|
private String czruuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业UUID
|
||||||
|
*/
|
||||||
|
@TableField(value = "qyuuid")
|
||||||
|
private String qyuuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业名称
|
||||||
|
*/
|
||||||
|
@TableField(value = "qymc")
|
||||||
|
private String qymc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 录入日期
|
||||||
|
*/
|
||||||
|
@TableField(value = "lrrq")
|
||||||
|
private Date lrrq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 录入人UUID
|
||||||
|
*/
|
||||||
|
@TableField(value = "lrruuid")
|
||||||
|
private String lrruuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改日期
|
||||||
|
*/
|
||||||
|
@TableField(value = "xgrq")
|
||||||
|
private Date xgrq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改人UUID
|
||||||
|
*/
|
||||||
|
@TableField(value = "xgruuid")
|
||||||
|
private String xgruuid;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
||||||
@ -23,6 +23,9 @@ public class GxxxReqVO extends PageParam implements Serializable{
|
|||||||
//收藏标志
|
//收藏标志
|
||||||
private String scbz;
|
private String scbz;
|
||||||
|
|
||||||
|
//供需UUID(按ID精确查询单条)
|
||||||
|
private String gxUuid;
|
||||||
|
|
||||||
//地区
|
//地区
|
||||||
private String dq;
|
private String dq;
|
||||||
//
|
//
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.css.txw.mhzc.pojo.vo;
|
||||||
|
|
||||||
|
import com.css.ggzc.framework.common.pojo.PageParam;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class YhfkReqVO extends PageParam implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈类型(bug=问题反馈、suggest=建议改进、function=功能需求、other=其他)
|
||||||
|
*/
|
||||||
|
private String fklx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理状态(0=待处理、1=处理中、2=已处理、3=已关闭)
|
||||||
|
*/
|
||||||
|
private String czzt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈标题(模糊查询)
|
||||||
|
*/
|
||||||
|
private String bt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈起始日期(yyyy-MM-dd)
|
||||||
|
*/
|
||||||
|
private String lrrqq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈截止日期(yyyy-MM-dd)
|
||||||
|
*/
|
||||||
|
private String lrrqz;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
package com.css.txw.mhzc.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class YhfkVO implements Serializable {
|
||||||
|
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈类型
|
||||||
|
*/
|
||||||
|
private String fklx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈类型名称
|
||||||
|
*/
|
||||||
|
private String fklxMc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈标题
|
||||||
|
*/
|
||||||
|
private String bt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈内容
|
||||||
|
*/
|
||||||
|
private String nr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附件图片(多个用逗号分隔)
|
||||||
|
*/
|
||||||
|
private String tp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系人
|
||||||
|
*/
|
||||||
|
private String lxr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系电话
|
||||||
|
*/
|
||||||
|
private String lxdh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系邮箱
|
||||||
|
*/
|
||||||
|
private String lxyx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理状态(0=待处理、1=处理中、2=已处理、3=已关闭)
|
||||||
|
*/
|
||||||
|
private String czzt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理状态名称
|
||||||
|
*/
|
||||||
|
private String czztMc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理意见
|
||||||
|
*/
|
||||||
|
private String czyj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理日期
|
||||||
|
*/
|
||||||
|
private String czrq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理人UUID
|
||||||
|
*/
|
||||||
|
private String czruuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业UUID
|
||||||
|
*/
|
||||||
|
private String qyuuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业名称
|
||||||
|
*/
|
||||||
|
private String qymc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 录入日期
|
||||||
|
*/
|
||||||
|
private String lrrq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 录入人UUID
|
||||||
|
*/
|
||||||
|
private String lrruuid;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.css.txw.mhzc.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.css.txw.mhzc.pojo.domain.TxwMhzcYhfkbDO;
|
||||||
|
import com.css.txw.mhzc.pojo.vo.YhfkReqVO;
|
||||||
|
import com.css.txw.mhzc.pojo.vo.YhfkVO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Claude
|
||||||
|
* @description 针对表【txw_mhzc_yhfkb(用户反馈表)】的数据库操作Service
|
||||||
|
*/
|
||||||
|
public interface TxwMhzcYhfkbService extends IService<TxwMhzcYhfkbDO> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交反馈
|
||||||
|
*/
|
||||||
|
String submit(YhfkVO yhfkVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销反馈(仅限当前用户、且未处理)
|
||||||
|
*/
|
||||||
|
String cancel(String uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前用户反馈分页列表
|
||||||
|
*/
|
||||||
|
Page<YhfkVO> myFkPage(YhfkReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反馈详情
|
||||||
|
*/
|
||||||
|
YhfkVO getDetail(String uuid);
|
||||||
|
|
||||||
|
}
|
||||||
@ -107,7 +107,7 @@ public class SearchServiceImpl implements SearchService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getHotSearchKeywords() {
|
public List<String> getHotSearchKeywords() {
|
||||||
return Arrays.asList("碳核查", "ESG", "碳资产管理", "ISO 14067");
|
return Arrays.asList("碳达峰", "碳核查", "ESG", "碳资产管理", "ISO 14067");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import com.css.txw.mhzc.service.TxwMhzcHydtbService;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -26,18 +27,20 @@ public class TxwMhzcHydtbServiceImpl extends ServiceImpl<TxwMhzcHydtbMapper, Txw
|
|||||||
@Resource
|
@Resource
|
||||||
private TxwMhzcHydtbMapper hydtbMapper;
|
private TxwMhzcHydtbMapper hydtbMapper;
|
||||||
|
|
||||||
|
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HydtbVO> getByLx(String lx) {
|
public List<HydtbVO> getByLx(String lx) {
|
||||||
List<TxwMhzcHydtbDO> list = hydtbMapper.getByLx(lx);
|
List<TxwMhzcHydtbDO> list = hydtbMapper.getByLx(lx);
|
||||||
if (GyUtils.isNull(list)) return null;
|
if (GyUtils.isNull(list)) return null;
|
||||||
return BeanUtils.toBean(list, HydtbVO.class);
|
return list.stream().map(this::toVO).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HydtbVO> getAll() {
|
public List<HydtbVO> getAll() {
|
||||||
List<TxwMhzcHydtbDO> list = hydtbMapper.getAllOrderByFbsj();
|
List<TxwMhzcHydtbDO> list = hydtbMapper.getAllOrderByFbsj();
|
||||||
if (GyUtils.isNull(list)) return null;
|
if (GyUtils.isNull(list)) return null;
|
||||||
return BeanUtils.toBean(list, HydtbVO.class);
|
return list.stream().map(this::toVO).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -46,4 +49,12 @@ public class TxwMhzcHydtbServiceImpl extends ServiceImpl<TxwMhzcHydtbMapper, Txw
|
|||||||
if (GyUtils.isNull(all)) return null;
|
if (GyUtils.isNull(all)) return null;
|
||||||
return all.stream().collect(Collectors.groupingBy(HydtbVO::getLx));
|
return all.stream().collect(Collectors.groupingBy(HydtbVO::getLx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HydtbVO toVO(TxwMhzcHydtbDO hydtbDO) {
|
||||||
|
HydtbVO vo = BeanUtils.toBean(hydtbDO, HydtbVO.class);
|
||||||
|
if (hydtbDO.getFbsj() != null) {
|
||||||
|
vo.setFbsj(hydtbDO.getFbsj().format(DTF));
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,144 @@
|
|||||||
|
package com.css.txw.mhzc.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.css.ggzc.framework.common.exception.ServiceException;
|
||||||
|
import com.css.ggzc.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
|
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||||
|
import com.css.ggzc.framework.common.util.object.BeanUtils;
|
||||||
|
import com.css.ggzc.framework.session.SessionUtils;
|
||||||
|
import com.css.txw.mhzc.mapper.TxwMhzcYhfkbMapper;
|
||||||
|
import com.css.txw.mhzc.pojo.domain.TxwMhzcYhfkbDO;
|
||||||
|
import com.css.txw.mhzc.pojo.vo.YhfkReqVO;
|
||||||
|
import com.css.txw.mhzc.pojo.vo.YhfkVO;
|
||||||
|
import com.css.txw.mhzc.service.TxwMhzcYhfkbService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Claude
|
||||||
|
* @description 针对表【txw_mhzc_yhfkb(用户反馈表)】的数据库操作Service实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class TxwMhzcYhfkbServiceImpl extends ServiceImpl<TxwMhzcYhfkbMapper, TxwMhzcYhfkbDO>
|
||||||
|
implements TxwMhzcYhfkbService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TxwMhzcYhfkbMapper yhfkbMapper;
|
||||||
|
|
||||||
|
private static final Map<String, String> FKLX_MAP = new HashMap<>();
|
||||||
|
private static final Map<String, String> CZZT_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
FKLX_MAP.put("bug", "问题反馈");
|
||||||
|
FKLX_MAP.put("suggest", "建议改进");
|
||||||
|
FKLX_MAP.put("function", "功能需求");
|
||||||
|
FKLX_MAP.put("other", "其他");
|
||||||
|
|
||||||
|
CZZT_MAP.put("0", "待处理");
|
||||||
|
CZZT_MAP.put("1", "处理中");
|
||||||
|
CZZT_MAP.put("2", "已处理");
|
||||||
|
CZZT_MAP.put("3", "已关闭");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String submit(YhfkVO yhfkVO) {
|
||||||
|
if (GyUtils.isNull(yhfkVO.getFklx())) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "反馈类型不能为空");
|
||||||
|
}
|
||||||
|
if (GyUtils.isNull(yhfkVO.getBt())) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "反馈标题不能为空");
|
||||||
|
}
|
||||||
|
if (GyUtils.isNull(yhfkVO.getNr())) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "反馈内容不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
TxwMhzcYhfkbDO yhfkbDO = BeanUtils.toBean(yhfkVO, TxwMhzcYhfkbDO.class);
|
||||||
|
Date now = new Date();
|
||||||
|
if (GyUtils.isNull(yhfkVO.getUuid())) {
|
||||||
|
yhfkbDO.setUuid(IdUtil.fastSimpleUUID());
|
||||||
|
yhfkbDO.setFklxMc(FKLX_MAP.getOrDefault(yhfkVO.getFklx(), ""));
|
||||||
|
yhfkbDO.setCzzt("0");
|
||||||
|
yhfkbDO.setQyuuid(SessionUtils.getQyuuid());
|
||||||
|
yhfkbDO.setLrrq(now);
|
||||||
|
yhfkbDO.setLrruuid(SessionUtils.getYhUuid());
|
||||||
|
this.save(yhfkbDO);
|
||||||
|
} else {
|
||||||
|
TxwMhzcYhfkbDO old = this.getById(yhfkVO.getUuid());
|
||||||
|
if (old == null) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "反馈不存在");
|
||||||
|
}
|
||||||
|
if (!"0".equals(old.getCzzt())) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "已受理的反馈无法修改");
|
||||||
|
}
|
||||||
|
yhfkbDO.setFklxMc(FKLX_MAP.getOrDefault(yhfkVO.getFklx(), ""));
|
||||||
|
yhfkbDO.setXgrq(now);
|
||||||
|
yhfkbDO.setXgruuid(SessionUtils.getYhUuid());
|
||||||
|
this.updateById(yhfkbDO);
|
||||||
|
}
|
||||||
|
return yhfkbDO.getUuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String cancel(String uuid) {
|
||||||
|
TxwMhzcYhfkbDO yhfkbDO = this.getById(uuid);
|
||||||
|
if (yhfkbDO == null) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "反馈不存在");
|
||||||
|
}
|
||||||
|
if (!SessionUtils.getYhUuid().equals(yhfkbDO.getLrruuid())) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "无权撤销他人反馈");
|
||||||
|
}
|
||||||
|
if (!"0".equals(yhfkbDO.getCzzt())) {
|
||||||
|
throw new ServiceException(GlobalErrorCodeConstants.ERROR.getCode(), "已受理的反馈无法撤销");
|
||||||
|
}
|
||||||
|
this.removeById(uuid);
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<YhfkVO> myFkPage(YhfkReqVO reqVO) {
|
||||||
|
String yhUuid = SessionUtils.getYhUuid();
|
||||||
|
Page<TxwMhzcYhfkbDO> doPage = yhfkbMapper.getYhfkPage(reqVO, yhUuid);
|
||||||
|
Page<YhfkVO> voPage = new Page<>();
|
||||||
|
voPage.setCurrent(doPage.getCurrent());
|
||||||
|
voPage.setSize(doPage.getSize());
|
||||||
|
voPage.setTotal(doPage.getTotal());
|
||||||
|
if (GyUtils.isNull(doPage.getRecords())) {
|
||||||
|
return voPage;
|
||||||
|
}
|
||||||
|
List<YhfkVO> records = doPage.getRecords().stream().map(this::toVO).collect(Collectors.toList());
|
||||||
|
voPage.setRecords(records);
|
||||||
|
return voPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public YhfkVO getDetail(String uuid) {
|
||||||
|
TxwMhzcYhfkbDO yhfkbDO = this.getById(uuid);
|
||||||
|
if (yhfkbDO == null) return null;
|
||||||
|
return toVO(yhfkbDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String DATE_FMT = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
private YhfkVO toVO(TxwMhzcYhfkbDO yhfkbDO) {
|
||||||
|
YhfkVO vo = BeanUtils.toBean(yhfkbDO, YhfkVO.class);
|
||||||
|
vo.setFklxMc(FKLX_MAP.getOrDefault(yhfkbDO.getFklx(), yhfkbDO.getFklxMc()));
|
||||||
|
vo.setCzztMc(CZZT_MAP.getOrDefault(yhfkbDO.getCzzt(), ""));
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FMT);
|
||||||
|
if (yhfkbDO.getLrrq() != null) {
|
||||||
|
vo.setLrrq(sdf.format(yhfkbDO.getLrrq()));
|
||||||
|
}
|
||||||
|
if (yhfkbDO.getCzrq() != null) {
|
||||||
|
vo.setCzrq(sdf.format(yhfkbDO.getCzrq()));
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||