feat: org disable 整改 + biz_meeting 补字段 + 表格 0/1 显示标准化
1. backend: 禁用主账号 dual-write + 子账号登录校验主账号状态
- BizOrgServiceImpl.toggleStatus: 同步 biz_org.status 与 sys_user.status
- BizOrgController.toggleStatus: 严格校验 '0'/'1'
- BizAuthController.smsLogin 4.5: 子账号校验主账号状态拦截
2. fix: BizMeeting 补 9 个字段 getters/setters
- projectId / projectName / orgName / supervisionOpinion / supervisionBy
- supervisionTime / invitationUrl / scheduleUrl / laborSigned
- 解决 Meetings.vue 修改/复制 projectId 为空的 bug
3. frontend: 0/1 status 标准化显示
- 10 个 Orgs/People 表格 el-tag 由 raw 0/1 改为 正常/禁用
- 4 个 People 页面修复 row.status || '正常' 在 '0' 时不
回退的 bug (字符串 '0' 是 truthy)
- 筛选下拉 / 编辑表单 / onToggleStatus label 全部对齐 0/1 语义
- DB 迁移: 10 行脏数据 (7 正常/合作中 → 0, 3 禁用 → 1)
- 备份表 biz_org_backup_20260819
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,388 @@
|
|||||||
|
# /manager/sponsor-orgs (合规 — 支持单位管理)
|
||||||
|
|
||||||
|
> 页面: `ry-vue3/src/views/manager/SponsorOrgs.vue` (120 行)
|
||||||
|
> 角色: 合规 (manager)
|
||||||
|
> 接口: `GET /business/org/list?orgType=sponsor&...`
|
||||||
|
> 数据表: `biz_org` (主), `sys_user` (people join)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §0 组件定位 (四跳)
|
||||||
|
|
||||||
|
| 跳 | 位置 | 关键引用 |
|
||||||
|
|---|---|---|
|
||||||
|
| ① 菜单 | `AdminLayout.vue:101` | `MENU.manager` 第 6 项: `{ path: '/manager/sponsor-orgs', title: '支持单位管理', icon: Connection }` |
|
||||||
|
| ② 路由 | `router/index.js:74` | `{ path: 'sponsor-orgs', name: 'manager-sponsor-orgs', component: () => import('@/views/manager/SponsorOrgs.vue'), meta: { title: '支持单位管理' } }` |
|
||||||
|
| ③ 组件 | `ry-vue3/src/views/manager/SponsorOrgs.vue` | 任务审查目标 |
|
||||||
|
| ④ 原型 | `proto/html/components/support-unit-manage.html` | 父级 `manager.html:210` 菜单: `<a data-page="components/support-unit-manage.html" class="menu-link">支持单位管理</a>` |
|
||||||
|
|
||||||
|
> 注: 原型组件名 `support-unit-manage.html` ≠ 路由名 `sponsor-orgs`, 按"菜单→原型" 唯一对应规则锁定。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §1 主要功能 + 可见性
|
||||||
|
|
||||||
|
### 1.1 主要功能 (manager 端查看-only)
|
||||||
|
|
||||||
|
| 功能 | 前端 | 后端 | 数据表 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 列表 + 筛选 | `SponsorOrgs.vue:30-54` | `GET /business/org/list` | `biz_org` |
|
||||||
|
| 详情查看 (dialog) | `SponsorOrgs.vue:56-74` | `GET /business/org/{orgId}` | `biz_org` |
|
||||||
|
| 跳人员管理 | `SponsorOrgs.vue:108-110` | 路由跳转, 不走 HTTP | — |
|
||||||
|
|
||||||
|
### 1.2 可见性 (三层过滤)
|
||||||
|
|
||||||
|
| 层 | 配置 | 校验 |
|
||||||
|
|---|---|---|
|
||||||
|
| 前端菜单 | `AdminLayout.vue:95-106` `MENU.manager` | 无 `requireMain` 标签, 也无 `store.isMain` 判断 — 只要 store.role==='manager' 即可见 |
|
||||||
|
| 路由守卫 | `router/index.js:74` `meta: { title: '支持单位管理' }` | **无 meta.role**, 不走路由权限拦截 (项目普遍现状) |
|
||||||
|
| 后端 SQL | `BizOrgMapper.xml:38` `<if test="orgType != null and orgType != ''"> and org_type = #{orgType} </if>` | 前端硬编码 `q.orgType='sponsor'` (SponsorOrgs.vue:85), 走 SQL 物理隔离 |
|
||||||
|
|
||||||
|
**不能看到的人群**:
|
||||||
|
- sponsor / executor / admin / leader / doctor 各自有独立菜单 (admin/SponsorOrgs.vue 是 admin 端全 CRUD, manager 端只读)
|
||||||
|
|
||||||
|
**数据隔离**: **前端硬编码 `orgType='sponsor'` + Mapper SQL `<if>` 拼接** — 任何调用 /business/org/list 的前端调用方都必须传 orgType, 否则查出所有公司。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §2 筛选项 (filter-form)
|
||||||
|
|
||||||
|
| UI label | 控件 | 绑定字段 | 后端 SQL | 命中表.字段 | 选项来源 | 原型对照 |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| 公司名称 | `el-input` (clearable) | `q.orgName` | `BizOrgMapper.xml:39` `org_name like concat('%', #{orgName}, '%')` | `biz_org.org_name` | — | ✅ "单位名称" |
|
||||||
|
| 税号/统一社会信用代码 | `el-input` (clearable) | `q.taxNo` | `BizOrgMapper.xml:40` `tax_no = #{taxNo}` | `biz_org.tax_no` | — | ✅ "税号/统一社会信用代码" |
|
||||||
|
| 合作状态 | `el-select` (clearable) | `q.status` | `BizOrgMapper.xml:41` `status = #{status}` | `biz_org.status` | **写死** 2 个 option (0=正常, 1=禁用) | ✅ |
|
||||||
|
| 查找 / 重置 | `el-button` | — | — | — | — | ✅ "查找" |
|
||||||
|
|
||||||
|
**⚠️ 状态 filter 错乱** (SponsorOrgs.vue:19-23):
|
||||||
|
```vue
|
||||||
|
<el-option label="正常/合作中" value="0" /> <!-- 1 个 label 对应 2 个数据状态 -->
|
||||||
|
<el-option label="合作中" value="合作中" />
|
||||||
|
<el-option label="禁用" value="禁用" />
|
||||||
|
```
|
||||||
|
DB 实测 sponsor 端 status 分布:
|
||||||
|
```
|
||||||
|
status COUNT
|
||||||
|
0 10 ← 数字 (默认值)
|
||||||
|
合作中 1 ← 字符串
|
||||||
|
禁用 4 ← 字符串
|
||||||
|
正常 2 ← 字符串
|
||||||
|
```
|
||||||
|
**混合形态**: 历史数据用 "0"/"1" 数字, 新数据 (admin 端 dialog) 用 "正常"/"合作中"/"禁用" 字符串。filter 把 "0" 标 "正常/合作中" 是历史债务, 但业务上是合理的 (3 类用户能筛 3 类数据)。
|
||||||
|
|
||||||
|
**❌ 缺失的筛选项** (原型 line 272-277, 287-294):
|
||||||
|
- 创建日期 起止 (daterange) — 原型做出占位但实现无
|
||||||
|
- 单位地址 — 原型 line 287-290 单独占位
|
||||||
|
|
||||||
|
**❌ 控件宽度未设** (SponsorOrgs.vue:12, 15, 18): admin 端 (`SponsorOrgs.vue:13-19`) 分别 200px/220px/140px, manager 端没设 → 浏览器默认 100% 撑开, 视觉不一致。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §3 工具栏
|
||||||
|
|
||||||
|
| 按钮 | 功能 | 接口 | 涉及表 | 原型对照 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| (无) | — | — | — | 原型无工具栏 (line 256 完成 header 后直接进 filter) |
|
||||||
|
|
||||||
|
**实现新增强功能**: **操作列禁用/恢复** 在 admin 端 (`admin/SponsorOrgs.vue:57-59`) 有, manager 端**故意去掉** (查看-only 角色拆分, 跟 admin 端 CRUD 清晰分离)。✅ 业务合理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §4 表格 (el-table)
|
||||||
|
|
||||||
|
### 4.1 数据来源 SQL
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT org_id, user_id, org_name, org_type, business_nature, address, tax_no, status, create_time,
|
||||||
|
contact_name, contact_phone, intent_count,
|
||||||
|
create_by, update_by, update_time
|
||||||
|
FROM biz_org
|
||||||
|
WHERE 1=1
|
||||||
|
[AND user_id = #{userId}]
|
||||||
|
[AND org_type = #{orgType}] ← 前端硬编码 'sponsor'
|
||||||
|
[AND org_name LIKE concat('%', #{orgName}, '%')]
|
||||||
|
[AND tax_no = #{taxNo}]
|
||||||
|
[AND status = #{status}]
|
||||||
|
ORDER BY org_id DESC
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 表格列映射
|
||||||
|
|
||||||
|
| 列名 | `row.*` | DB 表.字段 | 原型对照 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| # | (i+1) | — | ✅ 原型无 # 列, 实现新增 (item 1) |
|
||||||
|
| 公司名称 | `row.orgName` | `biz_org.org_name` | ✅ "单位名称" |
|
||||||
|
| 公司地址 | `row.address` | `biz_org.address` | ✅ "单位地址" |
|
||||||
|
| 税号/统一社会信用代码 | `row.taxNo` | `biz_org.tax_no` | ✅ "税号/统一社会信用代码" |
|
||||||
|
| 合作状态 | `row.status` (el-tag) | `biz_org.status` | ✅ "合作状态" |
|
||||||
|
| 创建日期 | `row.createTime` (slice 0,10) | `biz_org.create_time` | ✅ "创建日期" |
|
||||||
|
| 联系人 | `row.contactName` | `biz_org.contact_name` | ⚠️ 原型无 |
|
||||||
|
| 联系电话 | `row.contactPhone` | `biz_org.contact_phone` | ⚠️ 原型无 |
|
||||||
|
| 操作 | (el-button x2) | — | ✅ "人员管理"+"查看" |
|
||||||
|
|
||||||
|
**实现新增** (超出原型): # 序号、联系人、联系电话 — 是改进 (item 8.1)。
|
||||||
|
|
||||||
|
**⚠️ createTime 显示 (SponsorOrgs.vue:41)**:
|
||||||
|
```vue
|
||||||
|
{{ row.createTime ? String(row.createTime).slice(0,10) : '' }}
|
||||||
|
```
|
||||||
|
- 后端 `BizOrg.createTime` 是 `java.util.Date` (line 48), Jackson 默认序列化为 ISO 字符串 "2026-08-18T12:34:56" → slice 0,10 拿 → "2026-08-18" ✓
|
||||||
|
- 但 BizOrg 类**没有 `@JsonFormat` 注解** → 输出 ISO 8601, 不是 "yyyy-MM-dd HH:mm:ss"。admin 端 (line 47) 同样的 slice 写法。
|
||||||
|
- 风险: 如果后端 Spring 配置 `spring.jackson.date-format` 改成 `yyyy-MM-dd HH:mm:ss`, slice 0,10 拿到 "2026-08-18" 还是 OK; 但若配置空, 输出时间戳数字 `"1723965296000"`, slice 0,10 拿到 "1723965296" 就乱码。建议跟 §10 一起改用 `formatDate()` 工具。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §5 行内操作
|
||||||
|
|
||||||
|
| 按钮 | 触发函数 | 接口 | 后端动作 | 涉及表.字段 | 原型对照 |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| 查看 | `view(row)` (line 107) | `GET /business/org/{orgId}` | `BizOrgController.getInfo` (Controller.java:62) → `bizOrgService.getById` → `bizOrgMapper.selectByPrimaryKey` | `biz_org` (整行) | ✅ "查看" |
|
||||||
|
| 人员管理 | `goPeople(row)` (line 108-110) | 路由跳转 | `router.push('/manager/sponsor-people?orgId=...&orgName=...')` | — | ✅ "人员管理" |
|
||||||
|
|
||||||
|
**manager 端没有的按钮** (admin 端独有, manager 端只读):
|
||||||
|
- 编辑 → admin 端 `onEdit(row)` → `bizUpdate('org', form)` → `BizOrgController.edit` (PUT) → `mapper.updateByPrimaryKey`
|
||||||
|
|
||||||
|
**manager 端已加的按钮** (合规角色该有禁用权限, 2026-08-19 补):
|
||||||
|
- 禁用/恢复 → `onToggleStatus(row)` → `toggleOrgStatus` helper → `PUT /business/org/toggleStatus` → `BizOrgServiceImpl.toggleStatus` 同步主账号 sys_user.status → 子账号 login 时被 4.5 节拦截
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §6 Java Entity ↔ 数据库表 一致性
|
||||||
|
|
||||||
|
### 6.1 biz_org DDL (实测, 2026-08-18)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE `biz_org` (
|
||||||
|
`org_id` bigint NOT NULL AUTO_INCREMENT,
|
||||||
|
`org_name` varchar(200) NOT NULL,
|
||||||
|
`org_type` varchar(20) NOT NULL DEFAULT 'sponsor' COMMENT 'sponsor/��/execution', -- COMMENT 乱码
|
||||||
|
`business_nature` varchar(20) DEFAULT NULL COMMENT '私营/国营/...',
|
||||||
|
`address` varchar(500) DEFAULT NULL COMMENT '��λ��ַ',
|
||||||
|
`tax_no` varchar(50) DEFAULT NULL COMMENT '˰��/ͳһ...',
|
||||||
|
`contact_name` varchar(50) DEFAULT NULL COMMENT '��ϵ��',
|
||||||
|
`contact_phone` varchar(20) DEFAULT NULL COMMENT '��ϵ�绰',
|
||||||
|
`intent_count` int DEFAULT '0' COMMENT '意向项目数',
|
||||||
|
`status` varchar(20) DEFAULT '0' COMMENT '合作状态 合作中/已签约/暂停',
|
||||||
|
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||||
|
`create_time` datetime DEFAULT NULL,
|
||||||
|
`update_by` varchar(64) DEFAULT '',
|
||||||
|
`update_time` datetime DEFAULT NULL,
|
||||||
|
`user_id` bigint DEFAULT NULL COMMENT '主账号 sys_user.user_id',
|
||||||
|
PRIMARY KEY (`org_id`),
|
||||||
|
UNIQUE KEY `uk_org_user_type` (`user_id`,`org_type`),
|
||||||
|
KEY `idx_org_type_status` (`org_type`,`status`),
|
||||||
|
KEY `idx_org_type_name` (`org_type`,`org_name`),
|
||||||
|
KEY `idx_org_user_type_name` (`user_id`,`org_type`,`org_name`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4
|
||||||
|
COMMENT='֧�ֵ�λ��';
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ 所有中文 COMMENT 在客户端显示乱码 (DB 字符集 utf8mb4_unicode_ci, 但客户端 mysql shell 默认 GBK)。结构本身无误。
|
||||||
|
|
||||||
|
### 6.2 Entity ↔ DB 字段对照
|
||||||
|
|
||||||
|
| 实体字段 | DB 中文列名 (推断) | 类型 | 表字段 | 类型 | 一致? |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| `orgId` | 主键 | `Long` | `org_id` | `bigint NOT NULL AUTO_INCREMENT` | ✅ |
|
||||||
|
| `userId` | 主账号 | `Long` | `user_id` | `bigint DEFAULT NULL` | ✅ |
|
||||||
|
| `orgName` | 单位名称 | `String` | `org_name` | `varchar(200) NOT NULL` | ✅ |
|
||||||
|
| `orgType` | 单位类型 | `String` | `org_type` | `varchar(20) NOT NULL DEFAULT 'sponsor'` | ✅ |
|
||||||
|
| `businessNature` | 企业性质 | `String` | `business_nature` | `varchar(20) DEFAULT NULL` | ✅ |
|
||||||
|
| `address` | 单位地址 | `String` | `address` | `varchar(500) DEFAULT NULL` | ✅ |
|
||||||
|
| `taxNo` | 税号 | `String` | `tax_no` | `varchar(50) DEFAULT NULL` | ✅ |
|
||||||
|
| `contactName` | 联系人 | `String` | `contact_name` | `varchar(50) DEFAULT NULL` | ✅ |
|
||||||
|
| `contactPhone` | 联系电话 | `String` | `contact_phone` | `varchar(20) DEFAULT NULL` | ✅ |
|
||||||
|
| `intentCount` | 意向项目数 | `Integer` | `intent_count` | `int DEFAULT 0` | ✅ |
|
||||||
|
| `status` | 合作状态 | `String` | `status` | `varchar(20) DEFAULT '0'` | ✅ |
|
||||||
|
| `createTime` | 创建时间 | `Date` | `create_time` | `datetime DEFAULT NULL` | ✅ |
|
||||||
|
| `updateTime` | 更新时间 | `Date` | `update_time` | `datetime DEFAULT NULL` | ✅ |
|
||||||
|
| `createBy` | 创建者 | `String` (BaseEntity) | `create_by` | `varchar(64) DEFAULT ''` | ✅ |
|
||||||
|
| `updateBy` | 更新者 | `String` (BaseEntity) | `update_by` | `varchar(64) DEFAULT ''` | ✅ |
|
||||||
|
|
||||||
|
**✅ 13 个字段 + 2 个 BaseEntity 字段 全部 mapper SELECT/resultMap 覆盖, 全部 getter/setter 完整 (不像 BizMeeting 漏 9 个)**。
|
||||||
|
|
||||||
|
### 6.3 修订说明
|
||||||
|
|
||||||
|
> 修订: v1 草稿说"BizOrg 缺 getter/setter", 实测对齐 ✓, 收回此说法。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §7 索引检查
|
||||||
|
|
||||||
|
| Key | 列 | 类型 | 用途覆盖 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| PRIMARY | `org_id` | UNIQUE BTREE | ✅ 主键查询 `WHERE org_id = ?` |
|
||||||
|
| `uk_org_user_type` | `(user_id, org_type)` | UNIQUE BTREE | ✅ "一用户一类型一公司" 强制; `selectMySponsorCompany` 用 ✓ |
|
||||||
|
| `idx_org_type_status` | `(org_type, status)` | BTREE | ✅ 列表筛选 `WHERE org_type='sponsor' AND status=?` 命中 |
|
||||||
|
| `idx_org_type_name` | `(org_type, org_name)` | BTREE | ✅ 列表筛选 `WHERE org_type='sponsor' AND org_name LIKE ?` 命中 |
|
||||||
|
| `idx_org_user_type_name` | `(user_id, org_type, org_name)` | BTREE | ✅ `selectSponsorOrgOptions` / `selectExecutorOrgOptions` JOIN sys_user 命中 |
|
||||||
|
|
||||||
|
**结论**: 列表主查询路径 `WHERE org_type='sponsor' [AND org_name LIKE ?] [AND status=?]` 走 `idx_org_type_status` 或 `idx_org_type_name`, **无需新增索引**。当前数据量 17 行 sponsor, 性能完全 OK。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §8 与原型差异 (实现偏离)
|
||||||
|
|
||||||
|
> 原型: `proto/html/components/support-unit-manage.html` (457 行)
|
||||||
|
|
||||||
|
### 8.1 实现新增 (超出原型)
|
||||||
|
|
||||||
|
| # | 项 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | 表格 # 序号列 | element-ui `type="index"` 自动生成, 视觉清爽 |
|
||||||
|
| 2 | 表格联系人 + 联系电话 | 详情 dialog 也有, 实际很有用 |
|
||||||
|
| 3 | el-dialog 详情 (descriptions 单列布局) | 原型是 dialog 跳转 `support-unit-view.html`, 实现是本页面 inline dialog |
|
||||||
|
| 4 | 详情里 "公司类型: 支持方" el-tag | 原型无 |
|
||||||
|
| 5 | 跳人员管理传 `orgId+orgName` | 原型是空链, 实现带 query 让 sponsor-people 页面回显 |
|
||||||
|
|
||||||
|
### 8.2 原型有但实现缺失
|
||||||
|
|
||||||
|
| # | 项 | 严重度 | 修复建议 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | **筛选: 创建日期 起止** | P2 | 加 `startTime` `endTime` 字段, mapper 加 `<if>` |
|
||||||
|
| 2 | **筛选: 单位地址** | P2 | 加 `q.address`, mapper 加模糊匹配 |
|
||||||
|
| 3 | 面包屑 + page-title (大标题) | P3 | style-alignment 明确去 page-title, 跟其它页一致 ✓ |
|
||||||
|
| 4 | 底部红色提示 *点击禁用后, 该企业下所有账号则均不可登录* | P3 | manager 端无禁用按钮, 该提示放在 admin 端或 manager 详情 dialog |
|
||||||
|
|
||||||
|
### 8.3 文字 / 标签差异
|
||||||
|
|
||||||
|
| 项 | 原型 | 实现 | 评价 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 字段名 | "单位名称" / "单位地址" | "公司名称" / "公司地址" | ⚠️ 同义, 实现统一用 "公司" — 跟前述 `/sponsor/account` 一致, 可接受 |
|
||||||
|
| 状态值 | `active` / `disabled` (英文) | `正常` / `合作中` / `禁用` / `0` / `1` (混合) | ⚠️ DB 实业务字符串, 原型是 demo 数据 |
|
||||||
|
| 标题 | `支持单位管理` | `支持单位管理` | ✅ |
|
||||||
|
| 面包屑 | `工作台 > 支持单位管理` | `首页 / 支持单位管理` | ⚠️ 跟 style-alignment 统一规范一致, 牺牲原型还原 |
|
||||||
|
|
||||||
|
### 8.4 总结
|
||||||
|
|
||||||
|
- 方向: **扩展 + 减负** — 实现在原型基础上加了更细的字段 (联系人/电话), 减了不应有的功能 (manager 端无禁用按钮)
|
||||||
|
- 与 admin 端分工清晰: admin 端全 CRUD, manager 端只读 + 跳转
|
||||||
|
- 状态值混合 (数字 + 字符串) 是真业务历史问题, 不是 frontend bug
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §9 表字段冗余 / 设计问题
|
||||||
|
|
||||||
|
### 9.1 ❌ `biz_org` vs `biz_support_unit` 共存?
|
||||||
|
|
||||||
|
旧表 `biz_support_unit` / `biz_execution_unit` 已合并到 `biz_org`, 整个项目**不应该再有支持方/执行方单独表**。
|
||||||
|
- 检查 admin/SponsorOrgs.vue 引用 — 全部走 `biz_org`
|
||||||
|
- 检查 sponsor-people 父级 — 走 `biz_org.org_id`
|
||||||
|
- ✅ 合并完成, 无遗留
|
||||||
|
|
||||||
|
### 9.2 ❌ JOIN 字段 vs 持久化字段
|
||||||
|
|
||||||
|
`biz_org.intent_count` (承办方意向项目数) 是**持久化字段**还是 **JOIN 派生**?
|
||||||
|
- 看 mapper `selectList` 是直查 `intent_count`, 没有 JOIN 或子查询派生
|
||||||
|
- 但是 intent_count 不会自动更新 (没人写过 UPDATE biz_org SET intent_count = ... 的代码)
|
||||||
|
- 推测: 是各业务点 (创建/删除意向时) 手动维护, **存在不一致风险** — 数据库里 17 行 sponsor, 抽查几行 `intent_count` 值, 看是否有 < 5 的; 大概率是历史脏数据
|
||||||
|
|
||||||
|
### 9.3 ❌ 唯一约束 `uk_org_user_type` 语义
|
||||||
|
|
||||||
|
`UNIQUE (user_id, org_type)` 表示"一个 sys_user 在同一个 org_type 下只能有一家公司"。
|
||||||
|
- ✅ 业务合理: 一个用户不能同时是 2 家支持方
|
||||||
|
- ✅ 当前 17 行 sponsor / 16 行 executor 各归属独立 user_id
|
||||||
|
|
||||||
|
### 9.4 ✅ 业务闭环: 禁用/恢复同步主账号 (P1 已修复)
|
||||||
|
|
||||||
|
admin 端 `onToggleStatus` 调 `toggleOrgStatus(orgId, status)` → 后端 `BizOrgServiceImpl.toggleStatus` (`IBizOrgService.java:23-30` + `BizOrgServiceImpl.java:60-77`):
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Transactional
|
||||||
|
public int toggleStatus(Long orgId, String newBizOrgStatus) {
|
||||||
|
BizOrg org = bizOrgMapper.selectByPrimaryKey(orgId);
|
||||||
|
// 1. UPDATE biz_org.status
|
||||||
|
// 2. 同步主账号 sys_user.status
|
||||||
|
// '禁用' → '1', '正常'/'合作中' → '0'
|
||||||
|
// 只联动主账号 (biz_org.user_id), 子账号不在此操作范围
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**实测 login 流程** (`BizAuthController.java:140-157`):
|
||||||
|
```java
|
||||||
|
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||||
|
return error("账号已被停用"); // 主账号自己
|
||||||
|
}
|
||||||
|
// 4.5 子账号专属: 校验主账号状态
|
||||||
|
if (user.getParentUserId() != null) {
|
||||||
|
SysUser parent = userMapper.selectUserById(user.getParentUserId());
|
||||||
|
if (UserStatus.DISABLE.getCode().equals(parent.getStatus())) {
|
||||||
|
return error("所属企业主账号已被停用, 请联系企业管理员"); // 子账号
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**设计取舍**:
|
||||||
|
- 禁用时**只动主账号** (1 个 UPDATE), 不批量改子账号 sys_user.status
|
||||||
|
- 子账号由 login 时校验主账号状态拦截 (减少无效 UPDATE, 责任分离)
|
||||||
|
- 满足原型红字 "该企业下所有账号均不可登录" — 主账号停用时, 该 org 下所有子账号登录都被拦
|
||||||
|
|
||||||
|
**正例参考**: BizExpertService 已有 `toggleStatus` 模式 (`BizExpertService.java:83-90`), BizOrg 改造后同模式 ✓
|
||||||
|
|
||||||
|
### 9.4.1 ✅ 状态值整体收口 (2026-08-19 v3 落地)
|
||||||
|
|
||||||
|
**最终约定**: `biz_org.status` ⚠️ **`'0'` = 正常, `'1'` = 禁用** (纯数字, 无字符串)
|
||||||
|
|
||||||
|
**整改后的统一映射**:
|
||||||
|
| 位置 | 状态表达 |
|
||||||
|
|---|---|
|
||||||
|
| DB `biz_org.status` | `'0'` / `'1'` |
|
||||||
|
| 前端 dropdown value | `'0'` / `'1'` |
|
||||||
|
| 前端 `statusTagType` | `s === '1' ? 'danger' : 'success'` |
|
||||||
|
| 前端 `isDisabled` | `row.status === '1'` |
|
||||||
|
| 前端 `onToggleStatus` payload | `'0'` / `'1'` |
|
||||||
|
| 后端 `toggleStatus` 入参 | `'0'` / `'1'` (controller 严格校验) |
|
||||||
|
| 后端 sys_user.status 同步 | 同码 (`'0'` / `'1'`) |
|
||||||
|
|
||||||
|
**清理动作**:
|
||||||
|
- 跑数据迁移: `'正常'`/`'合作中'` → `'0'` (7 行), `'禁用'` → `'1'` (3 行), 备份 `biz_org_backup_20260819`
|
||||||
|
- 8 个前端文件统一: `manager/SponsorOrgs.vue`, `manager/ExecutorOrgs.vue`, `manager/Orgs.vue`, `admin/SponsorOrgs.vue`, `admin/ExecutorOrgs.vue`, `admin/Orgs.vue`, `manager/SponsorPeople.vue`, `manager/ExecutorPeople.vue`, `admin/SponsorPeople.vue`, `admin/ExecutorPeople.vue` (实际 10 个)
|
||||||
|
- 后端 `BizOrgController.toggleStatus` 入参校验: 只接 `'0'`/`'1'`, 其它报"status 必须是 '0' (正常) 或 '1' (禁用)"
|
||||||
|
- 后端 `BizOrgServiceImpl.toggleStatus` 不再做中文映射, `'0'` → sys_user.status='0', `'1'` → '1' (直透同码)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §10 待修复列表 (按优先级)
|
||||||
|
|
||||||
|
| # | 问题 | 文件 | 修复建议 | 严重度 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 1 | 状态 filter "0" 选项文案 "正常/合作中" 模糊 | `manager/SponsorOrgs.vue`, `admin/SponsorOrgs.vue`, `admin/ExecutorOrgs.vue`, `manager/Orgs.vue` | 2026-08-19 落地: 全部收口 2 个 option (0=正常, 1=禁用), 删 0正常/1禁用/合作中/正常/禁用 字符串残骸 | ~~P2~~ → ✅ |
|
||||||
|
| 2 | admin 端也同源存在 "0"/"1" 鬼 option | 同上 | 同上 | ~~P2~~ → ✅ |
|
||||||
|
| 3 | 缺筛选: 创建日期起止 | `manager/SponsorOrgs.vue` + `BizOrgMapper.xml` | 加 `q.startTime/q.endTime` + `<if>` | P2 |
|
||||||
|
| 4 | 缺筛选: 单位地址 | `manager/SponsorOrgs.vue` + `BizOrgMapper.xml` | 加 `q.address` + `address LIKE ?` + 索引检查 | P2 |
|
||||||
|
| 5 | el-input / el-select 缺 width | `manager/SponsorOrgs.vue:12,15,18` | 加 `style="width:200px/220px/140px"` | P2 |
|
||||||
|
| 6 | createTime `String().slice(0,10)` 脆弱 | `manager/SponsorOrgs.vue:41` | 抽 `formatDate()` 工具函数, 兼容 ISO/时间戳/字符串 | P3 |
|
||||||
|
| 7 | admin 端禁用/恢复 不联动 sys_user.status | 已修复 — `BizOrgServiceImpl.toggleStatus` + `BizAuthController.smsLogin` 4.5 节 | 2026-08-19 落地: toggleStatus 同步主账号 sys_user.status; 登录时校验主账号状态拦截子账号 | ~~P1~~ → ✅ |
|
||||||
|
| 8 | `intent_count` 字段无自动维护 | `biz_org` + intent 业务代码 | 创建/删除意向时同步 +计数, 或改成派生 view (COUNT(*) WHERE user_id=org.user_id) | P3 |
|
||||||
|
| 9 | 原型"工作台"面包屑 vs 实现"首页" | `manager/SponsorOrgs.vue:8` | 跟 style-alignment 统一规范保持 "首页 / 支持单位管理" 即可, 接受偏离 | P3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §11 引用清单
|
||||||
|
|
||||||
|
| 文件 | 行号 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `ry-vue3/src/views/manager/SponsorOrgs.vue` | 1-120 | 任务审查目标 |
|
||||||
|
| `ry-vue3/src/views/admin/SponsorOrgs.vue` | 1-238 | 配套 admin 端 CRUD 版 |
|
||||||
|
| `ry-vue3/src/layout/AdminLayout.vue` | 95-106 | `MENU.manager` 含本菜单 (line 101) |
|
||||||
|
| `ry-vue3/src/router/index.js` | 74 | `manager-sponsor-orgs` 路由 |
|
||||||
|
| `ry-vue3/src/api/public.js` | 32-37, 90-94 | `bizList/bizGet/bizUpdate` 通用封装 |
|
||||||
|
| `ry-api/ruoyi-business/src/main/java/com/ruoyi/business/controller/BizOrgController.java` | 26-31 | `GET /business/org/list` |
|
||||||
|
| `ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizOrgServiceImpl.java` | 13-53 | service 实现 |
|
||||||
|
| `ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizOrg.java` | 13-80 | Entity 全字段 (13 + 2 BaseEntity) |
|
||||||
|
| `ry-api/ruoyi-business/src/main/resources/mapper/business/BizOrgMapper.xml` | 34-44 | `selectList` SQL |
|
||||||
|
| `proto/html/manager.html` | 210 | 菜单指向 `support-unit-manage.html` |
|
||||||
|
| `proto/html/components/support-unit-manage.html` | 1-457 | 原型 (业务目标) |
|
||||||
|
| MySQL `biz_org` | 实测 2026-08-18 | 17 行 sponsor, status 混合 0/合作中/禁用/正常 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录 A. 修复记录
|
||||||
|
|
||||||
|
| 时刻 | 内容 |
|
||||||
|
|---|---|
|
||||||
|
| 2026-08-19 v2 | **P1 #7 修复**: admin 端禁用 org 同步主账号 sys_user.status; 子账号登录时校验主账号状态拦截. 涉及: BizOrgServiceImpl.toggleStatus + BizOrgController.toggleStatus endpoint + BizAuthController.smsLogin 4.5 节点 + admin/ExecutorOrgs.vue & admin/SponsorOrgs.vue onToggleStatus 改调 toggleOrgStatus helper + api/public.js 加 toggleOrgStatus |
|
||||||
|
| 2026-08-19 v2.1 | manager 端补 禁用/恢复 按钮 (合规角色该有). 涉及: manager/SponsorOrgs.vue + manager/ExecutorOrgs.vue 加 onToggleStatus + isDisabled, 操作列 180→240 |
|
||||||
|
| 2026-08-19 v3 | **整体整改 0/1 收口**: DB biz_org.status 统一为 '0'=正常, '1'=禁用; 后端 `BizOrgController.toggleStatus` 严格校验 '0'/'1'; 前端 10 个 orgs/people 文件 (manager/admin × Sponsor/Executor + manager/Orgs + admin/Orgs) 表格 el-tag 显示由 raw `{{ row.status }}` 改为 `{{ row.status === '1' ? '禁用' : '正常' }}`; 筛选下拉 + 编辑表单 + onToggleStatus label 全部对齐 0/1 语义; DB migration 已迁移 10 行脏数据 (7 正常/合作中 → 0, 3 禁用 → 1), 备份表 `biz_org_backup_20260819` |
|
||||||
|
| 2026-08-19 v3.1 | 4 个 People 页面表格 el-tag 显示 bug 修复: `{{ row.status || '正常' }}` 在 status='0' 时 '0' 是 truthy, 不会回退到 '正常', 实际显示 '0' 给用户. 改为 `{{ row.status === '1' ? '禁用' : '正常' }}` 跟 Orgs 保持一致. 涉及: manager/SponsorPeople.vue + manager/ExecutorPeople.vue + admin/SponsorPeople.vue + admin/ExecutorPeople.vue |
|
||||||
|
| 2026-08-18 v1 | 初稿 11 章齐, 9 个待修复 |
|
||||||
+13
@@ -145,6 +145,19 @@ public class BizAuthController extends BaseController {
|
|||||||
return error("账号已被停用");
|
return error("账号已被停用");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4.5 子账号专属: 校验主账号状态
|
||||||
|
// sys_user.parent_user_id 不为 NULL = 子账号 (执行方/支持方员工), 需拦截主账号被禁用的情况
|
||||||
|
// 主账号自己 parent_user_id = NULL, 跳过本步
|
||||||
|
if (user.getParentUserId() != null) {
|
||||||
|
SysUser parent = userMapper.selectUserById(user.getParentUserId());
|
||||||
|
if (parent == null) {
|
||||||
|
return error("所属主账号不存在, 请联系管理员");
|
||||||
|
}
|
||||||
|
if (UserStatus.DISABLE.getCode().equals(parent.getStatus())) {
|
||||||
|
return error("所属企业主账号已被停用, 请联系企业管理员");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 5. 构造 LoginUser 并设 SecurityContext (兼容后续 spring security 鉴权)
|
// 5. 构造 LoginUser 并设 SecurityContext (兼容后续 spring security 鉴权)
|
||||||
LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
|
LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
|
||||||
Authentication authentication = new UsernamePasswordAuthenticationToken(
|
Authentication authentication = new UsernamePasswordAuthenticationToken(
|
||||||
|
|||||||
+19
@@ -87,6 +87,25 @@ public class BizOrgController extends BaseController {
|
|||||||
return toAjax(bizOrgService.updateByPrimaryKey(bizOrg));
|
return toAjax(bizOrgService.updateByPrimaryKey(bizOrg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用/禁用 org, 同步主账号 sys_user.status
|
||||||
|
* PUT /business/org/toggleStatus body { orgId, status: '0'/'1' }
|
||||||
|
* 注意: 用 Map 接 body 而不是 BizOrg, 防止前端误传其它字段 (如 remark/updateTime) 覆盖
|
||||||
|
* 入口只接 orgId + status 2 个字段, 业务可见面可控
|
||||||
|
* status 严格限定 '0' (正常) / '1' (禁用), 避免历史 '0'/'1'/'正常'/'合作中'/'禁用' 混合
|
||||||
|
*/
|
||||||
|
@Log(title = "公司管理", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/toggleStatus")
|
||||||
|
public AjaxResult toggleStatus(@RequestBody Map<String, Object> body) {
|
||||||
|
if (body.get("orgId") == null) return error("orgId 不能为空");
|
||||||
|
Long orgId = Long.valueOf(body.get("orgId").toString());
|
||||||
|
String status = body.get("status") == null ? null : body.get("status").toString();
|
||||||
|
if (status == null || (!"0".equals(status) && !"1".equals(status))) {
|
||||||
|
return error("status 必须是 '0' (正常) 或 '1' (禁用)");
|
||||||
|
}
|
||||||
|
return toAjax(bizOrgService.toggleStatus(orgId, status));
|
||||||
|
}
|
||||||
|
|
||||||
@Log(title = "公司管理", businessType = BusinessType.DELETE)
|
@Log(title = "公司管理", businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{orgIds}")
|
@DeleteMapping("/{orgIds}")
|
||||||
public AjaxResult remove(@PathVariable Long[] orgIds) {
|
public AjaxResult remove(@PathVariable Long[] orgIds) {
|
||||||
|
|||||||
@@ -104,4 +104,22 @@ public class BizMeeting extends BaseEntity {
|
|||||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||||
public Date getUpdateTime() { return updateTime; }
|
public Date getUpdateTime() { return updateTime; }
|
||||||
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
|
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
|
||||||
|
public Long getProjectId() { return projectId; }
|
||||||
|
public void setProjectId(Long projectId) { this.projectId = projectId; }
|
||||||
|
public String getProjectName() { return projectName; }
|
||||||
|
public void setProjectName(String projectName) { this.projectName = projectName; }
|
||||||
|
public String getOrgName() { return orgName; }
|
||||||
|
public void setOrgName(String orgName) { this.orgName = orgName; }
|
||||||
|
public String getSupervisionOpinion() { return supervisionOpinion; }
|
||||||
|
public void setSupervisionOpinion(String supervisionOpinion) { this.supervisionOpinion = supervisionOpinion; }
|
||||||
|
public String getSupervisionBy() { return supervisionBy; }
|
||||||
|
public void setSupervisionBy(String supervisionBy) { this.supervisionBy = supervisionBy; }
|
||||||
|
public Date getSupervisionTime() { return supervisionTime; }
|
||||||
|
public void setSupervisionTime(Date supervisionTime) { this.supervisionTime = supervisionTime; }
|
||||||
|
public String getInvitationUrl() { return invitationUrl; }
|
||||||
|
public void setInvitationUrl(String invitationUrl) { this.invitationUrl = invitationUrl; }
|
||||||
|
public String getScheduleUrl() { return scheduleUrl; }
|
||||||
|
public void setScheduleUrl(String scheduleUrl) { this.scheduleUrl = scheduleUrl; }
|
||||||
|
public String getLaborSigned() { return laborSigned; }
|
||||||
|
public void setLaborSigned(String laborSigned) { this.laborSigned = laborSigned; }
|
||||||
}
|
}
|
||||||
@@ -17,4 +17,12 @@ public interface IBizOrgService {
|
|||||||
List<Map<String, Object>> selectExecutorOrgOptions(BizOrg entity);
|
List<Map<String, Object>> selectExecutorOrgOptions(BizOrg entity);
|
||||||
/** 当前登录 sponsor 的所属公司 (主账号可改, 子账号只读) */
|
/** 当前登录 sponsor 的所属公司 (主账号可改, 子账号只读) */
|
||||||
Map<String, Object> selectMySponsorCompany(Long userId);
|
Map<String, Object> selectMySponsorCompany(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用/禁用 org, 同步主账号 sys_user.status
|
||||||
|
* biz_org.status: '禁用' → sys_user.status='1', '正常'/'合作中' → '0'
|
||||||
|
* 只联动主账号 (biz_org.user_id), 子账号不在此操作范围
|
||||||
|
* (子账号登录时由 BizAuthController 校验主账号状态拦截)
|
||||||
|
*/
|
||||||
|
int toggleStatus(Long orgId, String newBizOrgStatus);
|
||||||
}
|
}
|
||||||
|
|||||||
+32
@@ -4,16 +4,22 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import com.ruoyi.business.domain.BizOrg;
|
import com.ruoyi.business.domain.BizOrg;
|
||||||
import com.ruoyi.business.mapper.BizOrgMapper;
|
import com.ruoyi.business.mapper.BizOrgMapper;
|
||||||
import com.ruoyi.business.service.IBizOrgService;
|
import com.ruoyi.business.service.IBizOrgService;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.id.SnowflakeId;
|
import com.ruoyi.common.utils.id.SnowflakeId;
|
||||||
|
import com.ruoyi.system.mapper.SysUserMapper;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class BizOrgServiceImpl implements IBizOrgService {
|
public class BizOrgServiceImpl implements IBizOrgService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private BizOrgMapper bizOrgMapper;
|
private BizOrgMapper bizOrgMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysUserMapper sysUserMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BizOrg getById(Long orgId) { return bizOrgMapper.selectByPrimaryKey(orgId); }
|
public BizOrg getById(Long orgId) { return bizOrgMapper.selectByPrimaryKey(orgId); }
|
||||||
|
|
||||||
@@ -50,4 +56,30 @@ public class BizOrgServiceImpl implements IBizOrgService {
|
|||||||
public Map<String, Object> selectMySponsorCompany(Long userId) {
|
public Map<String, Object> selectMySponsorCompany(Long userId) {
|
||||||
return bizOrgMapper.selectMySponsorCompany(userId);
|
return bizOrgMapper.selectMySponsorCompany(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用/禁用 org, 同步主账号 sys_user.status
|
||||||
|
* biz_org.status: '0' (正常) / '1' (禁用) → sys_user.status 同码 ('0' 正常, '1' 停用)
|
||||||
|
* 只联动主账号 (biz_org.user_id), 子账号不在此操作范围
|
||||||
|
* (子账号登录时由 BizAuthController 校验主账号状态拦截)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public int toggleStatus(Long orgId, String newBizOrgStatus) {
|
||||||
|
// 1. 查 org 取主账号 user_id
|
||||||
|
BizOrg org = bizOrgMapper.selectByPrimaryKey(orgId);
|
||||||
|
if (org == null) throw new ServiceException("组织不存在");
|
||||||
|
if (org.getUserId() == null) throw new ServiceException("该组织未关联主账号");
|
||||||
|
|
||||||
|
// 2. UPDATE biz_org.status
|
||||||
|
BizOrg update = new BizOrg();
|
||||||
|
update.setOrgId(orgId);
|
||||||
|
update.setStatus(newBizOrgStatus);
|
||||||
|
int rows = bizOrgMapper.updateByPrimaryKey(update);
|
||||||
|
|
||||||
|
// 3. 同步主账号 sys_user.status (0=正常, 1=停用 — 跟 biz_org.status 同码)
|
||||||
|
sysUserMapper.updateUserStatus(org.getUserId(), newBizOrgStatus);
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ export const bizGet = (entity, id) => request.get(`/business/${entity}/${id}`)
|
|||||||
// opts 透传给 request (例如 { __silentError: true } 让拦截器不自动 toast, 由调用方控制)
|
// opts 透传给 request (例如 { __silentError: true } 让拦截器不自动 toast, 由调用方控制)
|
||||||
export const bizAdd = (entity, data, opts) => request.post(`/business/${entity}`, data, opts)
|
export const bizAdd = (entity, data, opts) => request.post(`/business/${entity}`, data, opts)
|
||||||
export const bizUpdate = (entity, data, opts) => request.put(`/business/${entity}`, data, opts)
|
export const bizUpdate = (entity, data, opts) => request.put(`/business/${entity}`, data, opts)
|
||||||
|
|
||||||
|
// org 启用/禁用: PUT /business/org/toggleStatus, 同步主账号 sys_user.status
|
||||||
|
// (bizUpdate('org', {orgId, status}) 只改 biz_org.status, 不联动主账号, 已被 toggleStatus 替代)
|
||||||
|
export const toggleOrgStatus = (orgId, status) => request.put('/business/org/toggleStatus', { orgId, status })
|
||||||
export const bizDelete = (entity, ids) => request.delete(`/business/${entity}/${ids}`)
|
export const bizDelete = (entity, ids) => request.delete(`/business/${entity}/${ids}`)
|
||||||
|
|
||||||
// 人员批量导入 (unitType: 'sponsor' | 'executor')
|
// 人员批量导入 (unitType: 'sponsor' | 'executor')
|
||||||
|
|||||||
@@ -16,11 +16,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="合作状态">
|
<el-form-item label="合作状态">
|
||||||
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
||||||
<el-option label="正常" value="正常" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="禁用" value="禁用" />
|
|
||||||
<el-option label="0正常" value="0" />
|
|
||||||
<el-option label="1禁用" value="1" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -40,7 +37,7 @@
|
|||||||
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
||||||
<el-table-column label="合作状态" width="100" align="center">
|
<el-table-column label="合作状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
||||||
@@ -91,9 +88,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="isEdit" label="状态">
|
<el-form-item v-if="isEdit" label="状态">
|
||||||
<el-select v-model="form.status" style="width:160px">
|
<el-select v-model="form.status" style="width:160px">
|
||||||
<el-option label="0正常" value="0" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="1禁用" value="1" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -108,7 +104,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { bizList, bizAdd, bizUpdate } from '@/api/public'
|
import { bizList, bizAdd, bizUpdate, toggleOrgStatus } from '@/api/public'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -119,12 +115,11 @@ const loading = ref(false)
|
|||||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '正常' || s === '0' || s === '合作中') return 'success'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
return s === '1' ? 'danger' : 'success'
|
||||||
return 'info'
|
|
||||||
}
|
}
|
||||||
function isDisabled(row) {
|
function isDisabled(row) {
|
||||||
return row.status === '禁用' || row.status === '1'
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
function formatDate(d) {
|
function formatDate(d) {
|
||||||
if (!d) return ''
|
if (!d) return ''
|
||||||
@@ -162,7 +157,7 @@ async function onToggleStatus(row) {
|
|||||||
} catch { return }
|
} catch { return }
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await bizUpdate('org', { orgId: row.orgId, status: newStatus })
|
await toggleOrgStatus(row.orgId, newStatus)
|
||||||
ElMessage.success('已' + label)
|
ElMessage.success('已' + label)
|
||||||
load()
|
load()
|
||||||
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
||||||
@@ -203,7 +198,7 @@ function onView(row) {
|
|||||||
`地址: ${row.address || '-'}\n` +
|
`地址: ${row.address || '-'}\n` +
|
||||||
`税号: ${row.taxNo || '-'}\n` +
|
`税号: ${row.taxNo || '-'}\n` +
|
||||||
`联系人: ${row.contactName || '-'} (${row.contactPhone || '-'})\n` +
|
`联系人: ${row.contactName || '-'} (${row.contactPhone || '-'})\n` +
|
||||||
`状态: ${row.status}\n` +
|
`状态: ${row.status === '1' ? '禁用' : '正常'}\n` +
|
||||||
`创建日期: ${formatDate(row.createTime)}`,
|
`创建日期: ${formatDate(row.createTime)}`,
|
||||||
'服务机构详情',
|
'服务机构详情',
|
||||||
{ confirmButtonText: '关闭' }
|
{ confirmButtonText: '关闭' }
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<el-table-column prop="position" label="职务" min-width="100" />
|
<el-table-column prop="position" label="职务" min-width="100" />
|
||||||
<el-table-column label="状态" width="100" align="center">
|
<el-table-column label="状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status || '正常' }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="120" fixed="right">
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
@@ -106,11 +106,11 @@ const loading = ref(false)
|
|||||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
return 'success'
|
return s === '1' ? 'danger' : 'success'
|
||||||
}
|
}
|
||||||
function isDisabled(row) {
|
function isDisabled(row) {
|
||||||
return row.status === '禁用' || row.status === '1'
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
|||||||
@@ -26,11 +26,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="合作状态">
|
<el-form-item label="合作状态">
|
||||||
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
||||||
<el-option label="正常" value="正常" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="禁用" value="禁用" />
|
|
||||||
<el-option label="0正常" value="0" />
|
|
||||||
<el-option label="1禁用" value="1" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -59,7 +56,7 @@
|
|||||||
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
||||||
<el-table-column label="合作状态" width="100" align="center">
|
<el-table-column label="合作状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
||||||
@@ -116,9 +113,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="isEdit" label="状态">
|
<el-form-item v-if="isEdit" label="状态">
|
||||||
<el-select v-model="form.status" style="width:160px">
|
<el-select v-model="form.status" style="width:160px">
|
||||||
<el-option label="正常/合作中" value="0" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="禁用" value="禁用" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -141,12 +137,11 @@ const loading = ref(false)
|
|||||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '正常' || s === '0' || s === '合作中') return 'success'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
return s === '1' ? 'danger' : 'success'
|
||||||
return 'info'
|
|
||||||
}
|
}
|
||||||
function isDisabled(row) {
|
function isDisabled(row) {
|
||||||
return row.status === '禁用' || row.status === '1'
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
function formatDate(d) {
|
function formatDate(d) {
|
||||||
if (!d) return ''
|
if (!d) return ''
|
||||||
@@ -171,7 +166,7 @@ function reset() {
|
|||||||
|
|
||||||
async function onToggleStatus(row) {
|
async function onToggleStatus(row) {
|
||||||
const disabled = isDisabled(row)
|
const disabled = isDisabled(row)
|
||||||
const newStatus = disabled ? (row.orgType === 'sponsor' ? '正常' : '0') : '禁用'
|
const newStatus = disabled ? '0' : '1' // 0=正常, 1=禁用
|
||||||
const label = disabled ? '恢复' : '禁用'
|
const label = disabled ? '恢复' : '禁用'
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
try {
|
try {
|
||||||
@@ -183,7 +178,7 @@ async function onToggleStatus(row) {
|
|||||||
} catch { return }
|
} catch { return }
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await bizUpdate('org', { orgId: row.orgId, status: newStatus })
|
await toggleOrgStatus(row.orgId, newStatus)
|
||||||
ElMessage.success('已' + label)
|
ElMessage.success('已' + label)
|
||||||
load()
|
load()
|
||||||
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
||||||
@@ -224,7 +219,7 @@ function onView(row) {
|
|||||||
`地址: ${row.address || '-'}\n` +
|
`地址: ${row.address || '-'}\n` +
|
||||||
`税号: ${row.taxNo || '-'}\n` +
|
`税号: ${row.taxNo || '-'}\n` +
|
||||||
`联系人: ${row.contactName || '-'} (${row.contactPhone || '-'})\n` +
|
`联系人: ${row.contactName || '-'} (${row.contactPhone || '-'})\n` +
|
||||||
`状态: ${row.status}\n` +
|
`状态: ${row.status === '1' ? '禁用' : '正常'}\n` +
|
||||||
`创建日期: ${formatDate(row.createTime)}`,
|
`创建日期: ${formatDate(row.createTime)}`,
|
||||||
'公司详情',
|
'公司详情',
|
||||||
{ confirmButtonText: '关闭' }
|
{ confirmButtonText: '关闭' }
|
||||||
|
|||||||
@@ -17,11 +17,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="合作状态">
|
<el-form-item label="合作状态">
|
||||||
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
||||||
<el-option label="正常" value="正常" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="禁用" value="禁用" />
|
|
||||||
<el-option label="0正常" value="0" />
|
|
||||||
<el-option label="1禁用" value="1" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -41,7 +38,7 @@
|
|||||||
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
||||||
<el-table-column label="合作状态" width="100" align="center">
|
<el-table-column label="合作状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
||||||
@@ -92,9 +89,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="isEdit" label="状态">
|
<el-form-item v-if="isEdit" label="状态">
|
||||||
<el-select v-model="form.status" style="width:160px">
|
<el-select v-model="form.status" style="width:160px">
|
||||||
<el-option label="正常" value="正常" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="禁用" value="禁用" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -109,7 +105,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { bizList, bizAdd, bizUpdate } from '@/api/public'
|
import { bizList, bizAdd, bizUpdate, toggleOrgStatus } from '@/api/public'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -120,12 +116,11 @@ const loading = ref(false)
|
|||||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '正常' || s === '0' || s === '合作中') return 'success'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
return s === '1' ? 'danger' : 'success'
|
||||||
return 'info'
|
|
||||||
}
|
}
|
||||||
function isDisabled(row) {
|
function isDisabled(row) {
|
||||||
return row.status === '禁用' || row.status === '1'
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
function formatDate(d) {
|
function formatDate(d) {
|
||||||
if (!d) return ''
|
if (!d) return ''
|
||||||
@@ -150,7 +145,7 @@ function reset() {
|
|||||||
|
|
||||||
async function onToggleStatus(row) {
|
async function onToggleStatus(row) {
|
||||||
const disabled = isDisabled(row)
|
const disabled = isDisabled(row)
|
||||||
const newStatus = disabled ? '正常' : '禁用'
|
const newStatus = disabled ? '0' : '1' // 0=正常, 1=禁用
|
||||||
const label = disabled ? '恢复' : '禁用'
|
const label = disabled ? '恢复' : '禁用'
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
try {
|
try {
|
||||||
@@ -162,7 +157,7 @@ async function onToggleStatus(row) {
|
|||||||
} catch { return }
|
} catch { return }
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await bizUpdate('org', { orgId: row.orgId, status: newStatus })
|
await toggleOrgStatus(row.orgId, newStatus)
|
||||||
ElMessage.success('已' + label)
|
ElMessage.success('已' + label)
|
||||||
load()
|
load()
|
||||||
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
||||||
@@ -174,7 +169,7 @@ const saving = ref(false)
|
|||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
orgId: null, orgType: 'sponsor', orgName: '', address: '', taxNo: '',
|
orgId: null, orgType: 'sponsor', orgName: '', address: '', taxNo: '',
|
||||||
contactName: '', contactPhone: '', status: '正常'
|
contactName: '', contactPhone: '', status: '0'
|
||||||
})
|
})
|
||||||
const rules = {
|
const rules = {
|
||||||
orgName: [{ required: true, message: '请输入公司名称', trigger: 'blur' }]
|
orgName: [{ required: true, message: '请输入公司名称', trigger: 'blur' }]
|
||||||
@@ -184,7 +179,7 @@ function openAdd() {
|
|||||||
isEdit.value = false
|
isEdit.value = false
|
||||||
Object.assign(form, {
|
Object.assign(form, {
|
||||||
orgId: null, orgType: 'sponsor', orgName: '', address: '', taxNo: '',
|
orgId: null, orgType: 'sponsor', orgName: '', address: '', taxNo: '',
|
||||||
contactName: '', contactPhone: '', status: '正常'
|
contactName: '', contactPhone: '', status: '0'
|
||||||
})
|
})
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
@@ -203,7 +198,7 @@ function onView(row) {
|
|||||||
`地址: ${row.address || '-'}\n` +
|
`地址: ${row.address || '-'}\n` +
|
||||||
`税号: ${row.taxNo || '-'}\n` +
|
`税号: ${row.taxNo || '-'}\n` +
|
||||||
`联系人: ${row.contactName || '-'} (${row.contactPhone || '-'})\n` +
|
`联系人: ${row.contactName || '-'} (${row.contactPhone || '-'})\n` +
|
||||||
`状态: ${row.status}\n` +
|
`状态: ${row.status === '1' ? '禁用' : '正常'}\n` +
|
||||||
`创建日期: ${formatDate(row.createTime)}`,
|
`创建日期: ${formatDate(row.createTime)}`,
|
||||||
'支持单位详情',
|
'支持单位详情',
|
||||||
{ confirmButtonText: '关闭' }
|
{ confirmButtonText: '关闭' }
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<el-table-column prop="position" label="职务" min-width="100" />
|
<el-table-column prop="position" label="职务" min-width="100" />
|
||||||
<el-table-column label="状态" width="100" align="center">
|
<el-table-column label="状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status || '正常' }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="120" fixed="right">
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
@@ -107,11 +107,11 @@ const loading = ref(false)
|
|||||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
return 'success'
|
return s === '1' ? 'danger' : 'success'
|
||||||
}
|
}
|
||||||
function isDisabled(row) {
|
function isDisabled(row) {
|
||||||
return row.status === '禁用' || row.status === '1'
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
|||||||
@@ -15,10 +15,9 @@
|
|||||||
<el-input v-model="q.taxNo" placeholder="输入税号" clearable />
|
<el-input v-model="q.taxNo" placeholder="输入税号" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="合作状态">
|
<el-form-item label="合作状态">
|
||||||
<el-select v-model="q.status" placeholder="请选择" clearable>
|
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
||||||
<el-option label="0正常" value="0" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="1禁用" value="1" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -34,7 +33,7 @@
|
|||||||
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
||||||
<el-table-column label="合作状态" width="100" align="center">
|
<el-table-column label="合作状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
||||||
@@ -42,10 +41,13 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="contactName" label="联系人" width="100" align="center" />
|
<el-table-column prop="contactName" label="联系人" width="100" align="center" />
|
||||||
<el-table-column prop="contactPhone" label="联系电话" width="130" align="center" />
|
<el-table-column prop="contactPhone" label="联系电话" width="130" align="center" />
|
||||||
<el-table-column label="操作" width="180" fixed="right">
|
<el-table-column label="操作" width="240" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button link type="primary" @click="view(row)">查看</el-button>
|
<el-button link type="primary" @click="view(row)">查看</el-button>
|
||||||
<el-button link type="primary" @click="goPeople(row)">人员管理</el-button>
|
<el-button link type="primary" @click="goPeople(row)">人员管理</el-button>
|
||||||
|
<el-button link :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||||
|
{{ isDisabled(row) ? '恢复' : '禁用' }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -62,7 +64,7 @@
|
|||||||
<el-descriptions-item label="公司地址">{{ currentRow.address }}</el-descriptions-item>
|
<el-descriptions-item label="公司地址">{{ currentRow.address }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="税号/统一社会信用代码">{{ currentRow.taxNo }}</el-descriptions-item>
|
<el-descriptions-item label="税号/统一社会信用代码">{{ currentRow.taxNo }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="合作状态">
|
<el-descriptions-item label="合作状态">
|
||||||
<el-tag :type="statusTagType(currentRow.status)">{{ currentRow.status }}</el-tag>
|
<el-tag :type="statusTagType(currentRow.status)">{{ currentRow.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="创建日期">{{ currentRow.createTime ? String(currentRow.createTime).slice(0,10) : '' }}</el-descriptions-item>
|
<el-descriptions-item label="创建日期">{{ currentRow.createTime ? String(currentRow.createTime).slice(0,10) : '' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="联系人">{{ currentRow.contactName || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="联系人">{{ currentRow.contactName || '-' }}</el-descriptions-item>
|
||||||
@@ -78,7 +80,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { bizList } from '@/api/public'
|
import { bizList, toggleOrgStatus } from '@/api/public'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -90,9 +93,11 @@ const currentRow = ref(null)
|
|||||||
const detailOpen = ref(false)
|
const detailOpen = ref(false)
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '正常' || s === '0' || s === '合作中') return 'success'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
return s === '1' ? 'danger' : 'success'
|
||||||
return 'info'
|
}
|
||||||
|
function isDisabled(row) {
|
||||||
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
@@ -109,6 +114,28 @@ function goPeople(row) {
|
|||||||
router.push({ path: '/manager/executor-people', query: { orgId: row.orgId, orgName: row.orgName } })
|
router.push({ path: '/manager/executor-people', query: { orgId: row.orgId, orgName: row.orgName } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 仅禁用主账号 (走 BizOrgServiceImpl.toggleStatus: 同步 biz_org.status + sys_user.status)
|
||||||
|
// 子账号由 BizAuthController.smsLogin 4.5 节校验主账号状态拦截
|
||||||
|
async function onToggleStatus(row) {
|
||||||
|
const disabled = isDisabled(row)
|
||||||
|
const newStatus = disabled ? '0' : '1' // 0=正常, 1=禁用
|
||||||
|
const label = disabled ? '恢复' : '禁用'
|
||||||
|
if (!disabled) {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
`确定要${label}「${row.orgName}」吗? ${label}后该企业主账号无法登录, 企业下子账号也将被拦截`,
|
||||||
|
'确认',
|
||||||
|
{ type: 'warning' }
|
||||||
|
)
|
||||||
|
} catch { return }
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await toggleOrgStatus(row.orgId, newStatus)
|
||||||
|
ElMessage.success('已' + label)
|
||||||
|
load()
|
||||||
|
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(load)
|
onMounted(load)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<el-table-column prop="position" label="职务" min-width="100" />
|
<el-table-column prop="position" label="职务" min-width="100" />
|
||||||
<el-table-column label="状态" width="100" align="center">
|
<el-table-column label="状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status || '正常' }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="120" fixed="right">
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
@@ -106,11 +106,11 @@ const loading = ref(false)
|
|||||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
return 'success'
|
return s === '1' ? 'danger' : 'success'
|
||||||
}
|
}
|
||||||
function isDisabled(row) {
|
function isDisabled(row) {
|
||||||
return row.status === '禁用' || row.status === '1'
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
|||||||
@@ -23,9 +23,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="合作状态">
|
<el-form-item label="合作状态">
|
||||||
<el-select v-model="q.status" placeholder="请选择" clearable>
|
<el-select v-model="q.status" placeholder="请选择" clearable>
|
||||||
<el-option label="正常/合作中" value="0" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="禁用" value="禁用" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -49,7 +48,7 @@
|
|||||||
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
||||||
<el-table-column label="合作状态" width="100" align="center">
|
<el-table-column label="合作状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
||||||
@@ -78,7 +77,7 @@
|
|||||||
<el-descriptions-item label="公司地址">{{ currentRow.address }}</el-descriptions-item>
|
<el-descriptions-item label="公司地址">{{ currentRow.address }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="税号/统一社会信用代码">{{ currentRow.taxNo }}</el-descriptions-item>
|
<el-descriptions-item label="税号/统一社会信用代码">{{ currentRow.taxNo }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="合作状态">
|
<el-descriptions-item label="合作状态">
|
||||||
<el-tag :type="statusTagType(currentRow.status)">{{ currentRow.status }}</el-tag>
|
<el-tag :type="statusTagType(currentRow.status)">{{ currentRow.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="创建日期">{{ currentRow.createTime ? String(currentRow.createTime).slice(0,10) : '' }}</el-descriptions-item>
|
<el-descriptions-item label="创建日期">{{ currentRow.createTime ? String(currentRow.createTime).slice(0,10) : '' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="联系人">{{ currentRow.contactName || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="联系人">{{ currentRow.contactName || '-' }}</el-descriptions-item>
|
||||||
@@ -105,9 +104,8 @@ const currentRow = ref(null)
|
|||||||
const detailOpen = ref(false)
|
const detailOpen = ref(false)
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '正常' || s === '0' || s === '合作中') return 'success'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
return s === '1' ? 'danger' : 'success'
|
||||||
return 'info'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
|||||||
@@ -15,10 +15,9 @@
|
|||||||
<el-input v-model="q.taxNo" placeholder="输入税号" clearable />
|
<el-input v-model="q.taxNo" placeholder="输入税号" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="合作状态">
|
<el-form-item label="合作状态">
|
||||||
<el-select v-model="q.status" placeholder="请选择" clearable>
|
<el-select v-model="q.status" placeholder="请选择" clearable style="width:140px">
|
||||||
<el-option label="正常/合作中" value="0" />
|
<el-option label="正常" value="0" />
|
||||||
<el-option label="合作中" value="合作中" />
|
<el-option label="禁用" value="1" />
|
||||||
<el-option label="禁用" value="禁用" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -34,7 +33,7 @@
|
|||||||
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
<el-table-column prop="taxNo" label="税号/统一社会信用代码" min-width="180" />
|
||||||
<el-table-column label="合作状态" width="100" align="center">
|
<el-table-column label="合作状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
<el-table-column prop="createTime" label="创建日期" width="120" align="center">
|
||||||
@@ -42,10 +41,13 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="contactName" label="联系人" width="100" align="center" />
|
<el-table-column prop="contactName" label="联系人" width="100" align="center" />
|
||||||
<el-table-column prop="contactPhone" label="联系电话" width="130" align="center" />
|
<el-table-column prop="contactPhone" label="联系电话" width="130" align="center" />
|
||||||
<el-table-column label="操作" width="180" fixed="right">
|
<el-table-column label="操作" width="240" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button link type="primary" @click="view(row)">查看</el-button>
|
<el-button link type="primary" @click="view(row)">查看</el-button>
|
||||||
<el-button link type="primary" @click="goPeople(row)">人员管理</el-button>
|
<el-button link type="primary" @click="goPeople(row)">人员管理</el-button>
|
||||||
|
<el-button link :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||||
|
{{ isDisabled(row) ? '恢复' : '禁用' }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -62,7 +64,7 @@
|
|||||||
<el-descriptions-item label="公司地址">{{ currentRow.address }}</el-descriptions-item>
|
<el-descriptions-item label="公司地址">{{ currentRow.address }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="税号/统一社会信用代码">{{ currentRow.taxNo }}</el-descriptions-item>
|
<el-descriptions-item label="税号/统一社会信用代码">{{ currentRow.taxNo }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="合作状态">
|
<el-descriptions-item label="合作状态">
|
||||||
<el-tag :type="statusTagType(currentRow.status)">{{ currentRow.status }}</el-tag>
|
<el-tag :type="statusTagType(currentRow.status)">{{ currentRow.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="创建日期">{{ currentRow.createTime ? String(currentRow.createTime).slice(0,10) : '' }}</el-descriptions-item>
|
<el-descriptions-item label="创建日期">{{ currentRow.createTime ? String(currentRow.createTime).slice(0,10) : '' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="联系人">{{ currentRow.contactName || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="联系人">{{ currentRow.contactName || '-' }}</el-descriptions-item>
|
||||||
@@ -78,7 +80,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { bizList } from '@/api/public'
|
import { bizList, toggleOrgStatus } from '@/api/public'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -90,9 +93,11 @@ const currentRow = ref(null)
|
|||||||
const detailOpen = ref(false)
|
const detailOpen = ref(false)
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '正常' || s === '0' || s === '合作中') return 'success'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
return s === '1' ? 'danger' : 'success'
|
||||||
return 'info'
|
}
|
||||||
|
function isDisabled(row) {
|
||||||
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
@@ -109,6 +114,28 @@ function goPeople(row) {
|
|||||||
router.push({ path: '/manager/sponsor-people', query: { orgId: row.orgId, orgName: row.orgName } })
|
router.push({ path: '/manager/sponsor-people', query: { orgId: row.orgId, orgName: row.orgName } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 仅禁用主账号 (走 BizOrgServiceImpl.toggleStatus: 同步 biz_org.status + sys_user.status)
|
||||||
|
// 子账号由 BizAuthController.smsLogin 4.5 节校验主账号状态拦截
|
||||||
|
async function onToggleStatus(row) {
|
||||||
|
const disabled = isDisabled(row)
|
||||||
|
const newStatus = disabled ? '0' : '1' // 0=正常, 1=禁用
|
||||||
|
const label = disabled ? '恢复' : '禁用'
|
||||||
|
if (!disabled) {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
`确定要${label}「${row.orgName}」吗? ${label}后该企业主账号无法登录, 企业下子账号也将被拦截`,
|
||||||
|
'确认',
|
||||||
|
{ type: 'warning' }
|
||||||
|
)
|
||||||
|
} catch { return }
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await toggleOrgStatus(row.orgId, newStatus)
|
||||||
|
ElMessage.success('已' + label)
|
||||||
|
load()
|
||||||
|
} catch (e) { ElMessage.error(e?.msg || '操作失败') }
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(load)
|
onMounted(load)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<el-table-column prop="position" label="职务" min-width="100" />
|
<el-table-column prop="position" label="职务" min-width="100" />
|
||||||
<el-table-column label="状态" width="100" align="center">
|
<el-table-column label="状态" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status || '正常' }}</el-tag>
|
<el-tag :type="statusTagType(row.status)" disable-transitions>{{ row.status === '1' ? '禁用' : '正常' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="120" fixed="right">
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
@@ -106,11 +106,11 @@ const loading = ref(false)
|
|||||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
function statusTagType(s) {
|
function statusTagType(s) {
|
||||||
if (s === '禁用' || s === '1') return 'danger'
|
// 统一: 0=正常(success), 1=禁用(danger)
|
||||||
return 'success'
|
return s === '1' ? 'danger' : 'success'
|
||||||
}
|
}
|
||||||
function isDisabled(row) {
|
function isDisabled(row) {
|
||||||
return row.status === '禁用' || row.status === '1'
|
return row.status === '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
|||||||
Reference in New Issue
Block a user